Fossil SCM

merge from trunk and extending Makefile.dmc with event

wolfgang 2010-10-05 09:56 wolfgangTicketCmd merge
Commit a6dd0bf3e1f1417321dd0bf0886652c108dda400
+1 -1
--- src/attach.c
+++ src/attach.c
@@ -351,11 +351,11 @@
351351
cgi_redirect(zFrom);
352352
}
353353
style_header("Delete Attachment");
354354
@ <form action="%s(g.zBaseURL)/attachdelete" method="post"><div>
355355
@ <p>Confirm that you want to delete the attachment named
356
- @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br />
356
+ @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br /></p>
357357
if( zTkt ){
358358
@ <input type="hidden" name="tkt" value="%h(zTkt)" />
359359
}else{
360360
@ <input type="hidden" name="page" value="%h(zPage)" />
361361
}
362362
--- src/attach.c
+++ src/attach.c
@@ -351,11 +351,11 @@
351 cgi_redirect(zFrom);
352 }
353 style_header("Delete Attachment");
354 @ <form action="%s(g.zBaseURL)/attachdelete" method="post"><div>
355 @ <p>Confirm that you want to delete the attachment named
356 @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br />
357 if( zTkt ){
358 @ <input type="hidden" name="tkt" value="%h(zTkt)" />
359 }else{
360 @ <input type="hidden" name="page" value="%h(zPage)" />
361 }
362
--- src/attach.c
+++ src/attach.c
@@ -351,11 +351,11 @@
351 cgi_redirect(zFrom);
352 }
353 style_header("Delete Attachment");
354 @ <form action="%s(g.zBaseURL)/attachdelete" method="post"><div>
355 @ <p>Confirm that you want to delete the attachment named
356 @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br /></p>
357 if( zTkt ){
358 @ <input type="hidden" name="tkt" value="%h(zTkt)" />
359 }else{
360 @ <input type="hidden" name="page" value="%h(zPage)" />
361 }
362
+1 -1
--- src/blob.c
+++ src/blob.c
@@ -72,11 +72,11 @@
7272
7373
/*
7474
** We find that the built-in isspace() function does not work for
7575
** some international character sets. So here is a substitute.
7676
*/
77
-static int blob_isspace(char c){
77
+int blob_isspace(char c){
7878
return c==' ' || (c<='\r' && c>='\t');
7979
}
8080
8181
/*
8282
** COMMAND: test-isspace
8383
--- src/blob.c
+++ src/blob.c
@@ -72,11 +72,11 @@
72
73 /*
74 ** We find that the built-in isspace() function does not work for
75 ** some international character sets. So here is a substitute.
76 */
77 static int blob_isspace(char c){
78 return c==' ' || (c<='\r' && c>='\t');
79 }
80
81 /*
82 ** COMMAND: test-isspace
83
--- src/blob.c
+++ src/blob.c
@@ -72,11 +72,11 @@
72
73 /*
74 ** We find that the built-in isspace() function does not work for
75 ** some international character sets. So here is a substitute.
76 */
77 int blob_isspace(char c){
78 return c==' ' || (c<='\r' && c>='\t');
79 }
80
81 /*
82 ** COMMAND: test-isspace
83
+160 -142
--- src/content.c
+++ src/content.c
@@ -19,33 +19,25 @@
1919
*/
2020
#include "config.h"
2121
#include "content.h"
2222
#include <assert.h>
2323
24
-/*
25
-** Macros for debugging
26
-*/
27
-#if 0
28
-# define CONTENT_TRACE(X) printf X;
29
-#else
30
-# define CONTENT_TRACE(X)
31
-#endif
32
-
3324
/*
3425
** The artifact retrival cache
3526
*/
36
-#define MX_CACHE_CNT 50 /* Maximum number of positive cache entries */
37
-#define EXPELL_INTERVAL 5 /* How often to expell from a full cache */
3827
static struct {
39
- int n; /* Current number of positive cache entries */
28
+ i64 szTotal; /* Total size of all entries in the cache */
29
+ int n; /* Current number of eache entries */
30
+ int nAlloc; /* Number of slots allocated in a[] */
4031
int nextAge; /* Age counter for implementing LRU */
4132
int skipCnt; /* Used to limit entries expelled from cache */
42
- struct { /* One instance of this for each cache entry */
33
+ struct cacheLine { /* One instance of this for each cache entry */
4334
int rid; /* Artifact id */
4435
int age; /* Age. Newer is larger */
4536
Blob content; /* Content of the artifact */
46
- } a[MX_CACHE_CNT]; /* The positive cache */
37
+ } *a; /* The positive cache */
38
+ Bag inCache; /* Set of artifacts currently in cache */
4739
4840
/*
4941
** The missing artifact cache.
5042
**
5143
** Artifacts whose record ID are in missingCache cannot be retrieved
@@ -56,10 +48,54 @@
5648
*/
5749
Bag missing; /* Cache of artifacts that are incomplete */
5850
Bag available; /* Cache of artifacts that are complete */
5951
} contentCache;
6052
53
+/*
54
+** Remove the oldest element from the content cache
55
+*/
56
+static void content_cache_expire_oldest(void){
57
+ int i;
58
+ int mnAge = contentCache.nextAge;
59
+ int mn = -1;
60
+ for(i=0; i<contentCache.n; i++){
61
+ if( contentCache.a[i].age<mnAge ){
62
+ mnAge = contentCache.a[i].age;
63
+ mn = i;
64
+ }
65
+ }
66
+ if( mn>=0 ){
67
+ bag_remove(&contentCache.inCache, contentCache.a[mn].rid);
68
+ contentCache.szTotal -= blob_size(&contentCache.a[mn].content);
69
+ blob_reset(&contentCache.a[mn].content);
70
+ contentCache.n--;
71
+ contentCache.a[mn] = contentCache.a[contentCache.n];
72
+ }
73
+}
74
+
75
+/*
76
+** Add an entry to the content cache
77
+*/
78
+void content_cache_insert(int rid, Blob *pBlob){
79
+ struct cacheLine *p;
80
+ if( contentCache.n>500 || contentCache.szTotal>50000000 ){
81
+ content_cache_expire_oldest();
82
+ }
83
+ if( contentCache.n>=contentCache.nAlloc ){
84
+ contentCache.nAlloc = contentCache.nAlloc*2 + 10;
85
+ contentCache.a = realloc(contentCache.a,
86
+ contentCache.nAlloc*sizeof(contentCache.a[0]));
87
+ if( contentCache.a==0 ) fossil_panic("out of memory");
88
+ }
89
+ p = &contentCache.a[contentCache.n++];
90
+ p->rid = rid;
91
+ p->age = contentCache.nextAge++;
92
+ contentCache.szTotal += blob_size(pBlob);
93
+ p->content = *pBlob;
94
+ blob_zero(pBlob);
95
+ bag_insert(&contentCache.inCache, rid);
96
+}
6197
6298
/*
6399
** Clear the content cache.
64100
*/
65101
void content_clear_cache(void){
@@ -67,11 +103,13 @@
67103
for(i=0; i<contentCache.n; i++){
68104
blob_reset(&contentCache.a[i].content);
69105
}
70106
bag_clear(&contentCache.missing);
71107
bag_clear(&contentCache.available);
108
+ bag_clear(&contentCache.inCache);
72109
contentCache.n = 0;
110
+ contentCache.szTotal = 0;
73111
}
74112
75113
/*
76114
** Return the srcid associated with rid. Or return 0 if rid is
77115
** original content and not a delta.
@@ -95,32 +133,31 @@
95133
** true if it is. Return false if rid is a phantom or depends on
96134
** a phantom.
97135
*/
98136
int content_is_available(int rid){
99137
int srcid;
100
- if( bag_find(&contentCache.missing, rid) ){
101
- return 0;
102
- }
103
- if( bag_find(&contentCache.available, rid) ){
104
- return 1;
105
- }
106
- if( db_int(-1, "SELECT size FROM blob WHERE rid=%d", rid)<0 ){
107
- bag_insert(&contentCache.missing, rid);
108
- return 0;
109
- }
110
- srcid = findSrcid(rid);
111
- if( srcid==0 ){
112
- bag_insert(&contentCache.available, rid);
113
- return 1;
114
- }
115
- if( content_is_available(srcid) ){
116
- bag_insert(&contentCache.available, rid);
117
- return 1;
118
- }else{
119
- bag_insert(&contentCache.missing, rid);
120
- return 0;
121
- }
138
+ int depth = 0; /* Limit to recursion depth */
139
+ while( depth++ < 10000000 ){
140
+ if( bag_find(&contentCache.missing, rid) ){
141
+ return 0;
142
+ }
143
+ if( bag_find(&contentCache.available, rid) ){
144
+ return 1;
145
+ }
146
+ if( db_int(-1, "SELECT size FROM blob WHERE rid=%d", rid)<0 ){
147
+ bag_insert(&contentCache.missing, rid);
148
+ return 0;
149
+ }
150
+ srcid = findSrcid(rid);
151
+ if( srcid==0 ){
152
+ bag_insert(&contentCache.available, rid);
153
+ return 1;
154
+ }
155
+ rid = srcid;
156
+ }
157
+ fossil_panic("delta-loop in repository");
158
+ return 0;
122159
}
123160
124161
/*
125162
** Mark artifact rid as being available now. Update the cache to
126163
** show that everything that was formerly unavailable because rid
@@ -163,113 +200,84 @@
163200
}
164201
db_reset(&q);
165202
return rc;
166203
}
167204
168
-
169205
/*
170206
** Extract the content for ID rid and put it into the
171207
** uninitialized blob. Return 1 on success. If the record
172208
** is a phantom, zero pBlob and return 0.
173209
*/
174210
int content_get(int rid, Blob *pBlob){
175
- Blob src;
176
- int srcid;
177
- int rc = 0;
211
+ int rc;
178212
int i;
179
- static Bag inProcess;
213
+ int nextRid;
180214
181215
assert( g.repositoryOpen );
182216
blob_zero(pBlob);
183217
if( rid==0 ) return 0;
184218
185219
/* Early out if we know the content is not available */
186220
if( bag_find(&contentCache.missing, rid) ){
187
- CONTENT_TRACE(("%*smiss from cache: %d\n",
188
- bag_count(&inProcess), "", rid))
189221
return 0;
190222
}
191223
192224
/* Look for the artifact in the cache first */
193
- for(i=0; i<contentCache.n; i++){
194
- if( contentCache.a[i].rid==rid ){
195
- *pBlob = contentCache.a[i].content;
196
- blob_zero(&contentCache.a[i].content);
197
- contentCache.n--;
198
- if( i<contentCache.n ){
199
- contentCache.a[i] = contentCache.a[contentCache.n];
200
- }
201
- CONTENT_TRACE(("%*scache: %d\n",
202
- bag_count(&inProcess), "", rid))
203
- return 1;
204
- }
205
- }
206
-
207
- /* See if we need to apply a delta to find this artifact */
208
- srcid = findSrcid(rid);
209
- CONTENT_TRACE(("%*ssearching for %d. Need %d.\n",
210
- bag_count(&inProcess), "", rid, srcid))
211
-
212
-
213
- if( srcid ){
214
- /* Yes, a delta is required */
215
- if( bag_find(&inProcess, srcid) ){
216
- db_multi_exec(
217
- "UPDATE blob SET content=NULL, size=-1 WHERE rid=%d;"
218
- "DELETE FROM delta WHERE rid=%d;"
219
- "INSERT OR IGNORE INTO phantom VALUES(%d);",
220
- srcid, srcid, srcid
221
- );
222
- blob_zero(pBlob);
223
- return 0;
224
- }
225
- bag_insert(&inProcess, srcid);
226
-
227
- if( content_get(srcid, &src) ){
228
- Blob delta;
229
- if( content_of_blob(rid, &delta) ){
230
- blob_init(pBlob,0,0);
231
- blob_delta_apply(&src, &delta, pBlob);
225
+ if( bag_find(&contentCache.inCache, rid) ){
226
+ for(i=0; i<contentCache.n; i++){
227
+ if( contentCache.a[i].rid==rid ){
228
+ blob_copy(pBlob, &contentCache.a[i].content);
229
+ contentCache.a[i].age = contentCache.nextAge++;
230
+ return 1;
231
+ }
232
+ }
233
+ }
234
+
235
+ nextRid = findSrcid(rid);
236
+ if( nextRid==0 ){
237
+ rc = content_of_blob(rid, pBlob);
238
+ }else{
239
+ int n = 1;
240
+ int nAlloc = 10;
241
+ int *a = 0;
242
+ int mx;
243
+ Blob delta, next;
244
+
245
+ a = malloc( sizeof(a[0])*nAlloc );
246
+ if( a==0 ) fossil_panic("out of memory");
247
+ a[0] = rid;
248
+ a[1] = nextRid;
249
+ n = 1;
250
+ while( !bag_find(&contentCache.inCache, nextRid)
251
+ && (nextRid = findSrcid(nextRid))>0 ){
252
+ n++;
253
+ if( n>=nAlloc ){
254
+ nAlloc = nAlloc*2 + 10;
255
+ a = realloc(a, nAlloc*sizeof(a[0]));
256
+ if( a==0 ) fossil_panic("out of memory");
257
+ }
258
+ a[n] = nextRid;
259
+ }
260
+ mx = n;
261
+ rc = content_get(a[n], pBlob);
262
+ n--;
263
+ while( rc && n>=0 ){
264
+ rc = content_of_blob(a[n], &delta);
265
+ if( rc ){
266
+ blob_delta_apply(pBlob, &delta, &next);
232267
blob_reset(&delta);
233
- rc = 1;
234
- }
235
-
236
- /* Save the srcid artifact in the cache */
237
- if( contentCache.n<MX_CACHE_CNT ){
238
- i = contentCache.n++;
239
- }else if( ((contentCache.skipCnt++)%EXPELL_INTERVAL)!=0 ){
240
- i = -1;
241
- }else{
242
- int j, best;
243
- best = contentCache.nextAge+1;
244
- i = -1;
245
- for(j=0; j<contentCache.n; j++){
246
- if( contentCache.a[j].age<best ){
247
- i = j;
248
- best = contentCache.a[j].age;
249
- }
250
- }
251
- CONTENT_TRACE(("%*sexpell %d from cache\n",
252
- bag_count(&inProcess), "", contentCache.a[i].rid))
253
- blob_reset(&contentCache.a[i].content);
254
- }
255
- if( i>=0 ){
256
- contentCache.a[i].content = src;
257
- contentCache.a[i].age = contentCache.nextAge++;
258
- contentCache.a[i].rid = srcid;
259
- CONTENT_TRACE(("%*sadd %d to cache\n",
260
- bag_count(&inProcess), "", srcid))
261
- }else{
262
- blob_reset(&src);
263
- }
264
- }
265
- bag_remove(&inProcess, srcid);
266
- }else{
267
- /* No delta required. Read content directly from the database */
268
- if( content_of_blob(rid, pBlob) ){
269
- rc = 1;
270
- }
268
+ if( (mx-n)%8==0 ){
269
+ content_cache_insert(a[n+1], pBlob);
270
+ }else{
271
+ blob_reset(pBlob);
272
+ }
273
+ *pBlob = next;
274
+ }
275
+ n--;
276
+ }
277
+ free(a);
278
+ if( !rc ) blob_reset(pBlob);
271279
}
272280
if( rc==0 ){
273281
bag_insert(&contentCache.missing, rid);
274282
}else{
275283
bag_insert(&contentCache.available, rid);
@@ -320,35 +328,45 @@
320328
321329
/*
322330
** When a record is converted from a phantom to a real record,
323331
** if that record has other records that are derived by delta,
324332
** then call manifest_crosslink() on those other records.
333
+**
334
+** Tail recursion is used to minimize stack depth.
325335
*/
326336
void after_dephantomize(int rid, int linkFlag){
327337
Stmt q;
328
- int prevTid = 0;
329
-
330
- /* The prevTid variable is used to delay invoking this routine
331
- ** recursively, if possible, until after the query has finalized,
332
- ** in order to avoid having an excessive number of prepared statements.
333
- ** This is most effective in the common case where the query returns
334
- ** just one row.
335
- */
336
- db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid);
337
- while( db_step(&q)==SQLITE_ROW ){
338
- int tid = db_column_int(&q, 0);
339
- if( prevTid ) after_dephantomize(prevTid, 1);
340
- prevTid = tid;
341
- }
342
- db_finalize(&q);
343
- if( prevTid ) after_dephantomize(prevTid, 1);
344
- if( linkFlag ){
345
- Blob content;
346
- content_get(rid, &content);
347
- manifest_crosslink(rid, &content);
348
- blob_reset(&content);
349
- }
338
+ int nChildAlloc = 0;
339
+ int *aChild = 0;
340
+
341
+ while( rid ){
342
+ int nChildUsed = 0;
343
+ int i;
344
+ if( linkFlag ){
345
+ Blob content;
346
+ content_get(rid, &content);
347
+ manifest_crosslink(rid, &content);
348
+ blob_reset(&content);
349
+ }
350
+ db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid);
351
+ while( db_step(&q)==SQLITE_ROW ){
352
+ int child = db_column_int(&q, 0);
353
+ if( nChildUsed>=nChildAlloc ){
354
+ nChildAlloc = nChildAlloc*2 + 10;
355
+ aChild = realloc(aChild, nChildAlloc*sizeof(aChild));
356
+ if( aChild==0 ) fossil_panic("out of memory");
357
+ }
358
+ aChild[nChildUsed++] = child;
359
+ }
360
+ db_finalize(&q);
361
+ for(i=1; i<nChildUsed; i++){
362
+ after_dephantomize(aChild[i], 1);
363
+ }
364
+ rid = nChildUsed>0 ? aChild[0] : 0;
365
+ linkFlag = 1;
366
+ }
367
+ free(aChild);
350368
}
351369
352370
/*
353371
** Write content into the database. Return the record ID. If the
354372
** content is already in the database, just return the record ID.
355373
356374
ADDED src/event.c
--- src/content.c
+++ src/content.c
@@ -19,33 +19,25 @@
19 */
20 #include "config.h"
21 #include "content.h"
22 #include <assert.h>
23
24 /*
25 ** Macros for debugging
26 */
27 #if 0
28 # define CONTENT_TRACE(X) printf X;
29 #else
30 # define CONTENT_TRACE(X)
31 #endif
32
33 /*
34 ** The artifact retrival cache
35 */
36 #define MX_CACHE_CNT 50 /* Maximum number of positive cache entries */
37 #define EXPELL_INTERVAL 5 /* How often to expell from a full cache */
38 static struct {
39 int n; /* Current number of positive cache entries */
 
 
40 int nextAge; /* Age counter for implementing LRU */
41 int skipCnt; /* Used to limit entries expelled from cache */
42 struct { /* One instance of this for each cache entry */
43 int rid; /* Artifact id */
44 int age; /* Age. Newer is larger */
45 Blob content; /* Content of the artifact */
46 } a[MX_CACHE_CNT]; /* The positive cache */
 
47
48 /*
49 ** The missing artifact cache.
50 **
51 ** Artifacts whose record ID are in missingCache cannot be retrieved
@@ -56,10 +48,54 @@
56 */
57 Bag missing; /* Cache of artifacts that are incomplete */
58 Bag available; /* Cache of artifacts that are complete */
59 } contentCache;
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
62 /*
63 ** Clear the content cache.
64 */
65 void content_clear_cache(void){
@@ -67,11 +103,13 @@
67 for(i=0; i<contentCache.n; i++){
68 blob_reset(&contentCache.a[i].content);
69 }
70 bag_clear(&contentCache.missing);
71 bag_clear(&contentCache.available);
 
72 contentCache.n = 0;
 
73 }
74
75 /*
76 ** Return the srcid associated with rid. Or return 0 if rid is
77 ** original content and not a delta.
@@ -95,32 +133,31 @@
95 ** true if it is. Return false if rid is a phantom or depends on
96 ** a phantom.
97 */
98 int content_is_available(int rid){
99 int srcid;
100 if( bag_find(&contentCache.missing, rid) ){
101 return 0;
102 }
103 if( bag_find(&contentCache.available, rid) ){
104 return 1;
105 }
106 if( db_int(-1, "SELECT size FROM blob WHERE rid=%d", rid)<0 ){
107 bag_insert(&contentCache.missing, rid);
108 return 0;
109 }
110 srcid = findSrcid(rid);
111 if( srcid==0 ){
112 bag_insert(&contentCache.available, rid);
113 return 1;
114 }
115 if( content_is_available(srcid) ){
116 bag_insert(&contentCache.available, rid);
117 return 1;
118 }else{
119 bag_insert(&contentCache.missing, rid);
120 return 0;
121 }
122 }
123
124 /*
125 ** Mark artifact rid as being available now. Update the cache to
126 ** show that everything that was formerly unavailable because rid
@@ -163,113 +200,84 @@
163 }
164 db_reset(&q);
165 return rc;
166 }
167
168
169 /*
170 ** Extract the content for ID rid and put it into the
171 ** uninitialized blob. Return 1 on success. If the record
172 ** is a phantom, zero pBlob and return 0.
173 */
174 int content_get(int rid, Blob *pBlob){
175 Blob src;
176 int srcid;
177 int rc = 0;
178 int i;
179 static Bag inProcess;
180
181 assert( g.repositoryOpen );
182 blob_zero(pBlob);
183 if( rid==0 ) return 0;
184
185 /* Early out if we know the content is not available */
186 if( bag_find(&contentCache.missing, rid) ){
187 CONTENT_TRACE(("%*smiss from cache: %d\n",
188 bag_count(&inProcess), "", rid))
189 return 0;
190 }
191
192 /* Look for the artifact in the cache first */
193 for(i=0; i<contentCache.n; i++){
194 if( contentCache.a[i].rid==rid ){
195 *pBlob = contentCache.a[i].content;
196 blob_zero(&contentCache.a[i].content);
197 contentCache.n--;
198 if( i<contentCache.n ){
199 contentCache.a[i] = contentCache.a[contentCache.n];
200 }
201 CONTENT_TRACE(("%*scache: %d\n",
202 bag_count(&inProcess), "", rid))
203 return 1;
204 }
205 }
206
207 /* See if we need to apply a delta to find this artifact */
208 srcid = findSrcid(rid);
209 CONTENT_TRACE(("%*ssearching for %d. Need %d.\n",
210 bag_count(&inProcess), "", rid, srcid))
211
212
213 if( srcid ){
214 /* Yes, a delta is required */
215 if( bag_find(&inProcess, srcid) ){
216 db_multi_exec(
217 "UPDATE blob SET content=NULL, size=-1 WHERE rid=%d;"
218 "DELETE FROM delta WHERE rid=%d;"
219 "INSERT OR IGNORE INTO phantom VALUES(%d);",
220 srcid, srcid, srcid
221 );
222 blob_zero(pBlob);
223 return 0;
224 }
225 bag_insert(&inProcess, srcid);
226
227 if( content_get(srcid, &src) ){
228 Blob delta;
229 if( content_of_blob(rid, &delta) ){
230 blob_init(pBlob,0,0);
231 blob_delta_apply(&src, &delta, pBlob);
 
 
 
232 blob_reset(&delta);
233 rc = 1;
234 }
235
236 /* Save the srcid artifact in the cache */
237 if( contentCache.n<MX_CACHE_CNT ){
238 i = contentCache.n++;
239 }else if( ((contentCache.skipCnt++)%EXPELL_INTERVAL)!=0 ){
240 i = -1;
241 }else{
242 int j, best;
243 best = contentCache.nextAge+1;
244 i = -1;
245 for(j=0; j<contentCache.n; j++){
246 if( contentCache.a[j].age<best ){
247 i = j;
248 best = contentCache.a[j].age;
249 }
250 }
251 CONTENT_TRACE(("%*sexpell %d from cache\n",
252 bag_count(&inProcess), "", contentCache.a[i].rid))
253 blob_reset(&contentCache.a[i].content);
254 }
255 if( i>=0 ){
256 contentCache.a[i].content = src;
257 contentCache.a[i].age = contentCache.nextAge++;
258 contentCache.a[i].rid = srcid;
259 CONTENT_TRACE(("%*sadd %d to cache\n",
260 bag_count(&inProcess), "", srcid))
261 }else{
262 blob_reset(&src);
263 }
264 }
265 bag_remove(&inProcess, srcid);
266 }else{
267 /* No delta required. Read content directly from the database */
268 if( content_of_blob(rid, pBlob) ){
269 rc = 1;
270 }
271 }
272 if( rc==0 ){
273 bag_insert(&contentCache.missing, rid);
274 }else{
275 bag_insert(&contentCache.available, rid);
@@ -320,35 +328,45 @@
320
321 /*
322 ** When a record is converted from a phantom to a real record,
323 ** if that record has other records that are derived by delta,
324 ** then call manifest_crosslink() on those other records.
 
 
325 */
326 void after_dephantomize(int rid, int linkFlag){
327 Stmt q;
328 int prevTid = 0;
329
330 /* The prevTid variable is used to delay invoking this routine
331 ** recursively, if possible, until after the query has finalized,
332 ** in order to avoid having an excessive number of prepared statements.
333 ** This is most effective in the common case where the query returns
334 ** just one row.
335 */
336 db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid);
337 while( db_step(&q)==SQLITE_ROW ){
338 int tid = db_column_int(&q, 0);
339 if( prevTid ) after_dephantomize(prevTid, 1);
340 prevTid = tid;
341 }
342 db_finalize(&q);
343 if( prevTid ) after_dephantomize(prevTid, 1);
344 if( linkFlag ){
345 Blob content;
346 content_get(rid, &content);
347 manifest_crosslink(rid, &content);
348 blob_reset(&content);
349 }
 
 
 
 
 
 
 
 
350 }
351
352 /*
353 ** Write content into the database. Return the record ID. If the
354 ** content is already in the database, just return the record ID.
355
356 DDED src/event.c
--- src/content.c
+++ src/content.c
@@ -19,33 +19,25 @@
19 */
20 #include "config.h"
21 #include "content.h"
22 #include <assert.h>
23
 
 
 
 
 
 
 
 
 
24 /*
25 ** The artifact retrival cache
26 */
 
 
27 static struct {
28 i64 szTotal; /* Total size of all entries in the cache */
29 int n; /* Current number of eache entries */
30 int nAlloc; /* Number of slots allocated in a[] */
31 int nextAge; /* Age counter for implementing LRU */
32 int skipCnt; /* Used to limit entries expelled from cache */
33 struct cacheLine { /* One instance of this for each cache entry */
34 int rid; /* Artifact id */
35 int age; /* Age. Newer is larger */
36 Blob content; /* Content of the artifact */
37 } *a; /* The positive cache */
38 Bag inCache; /* Set of artifacts currently in cache */
39
40 /*
41 ** The missing artifact cache.
42 **
43 ** Artifacts whose record ID are in missingCache cannot be retrieved
@@ -56,10 +48,54 @@
48 */
49 Bag missing; /* Cache of artifacts that are incomplete */
50 Bag available; /* Cache of artifacts that are complete */
51 } contentCache;
52
53 /*
54 ** Remove the oldest element from the content cache
55 */
56 static void content_cache_expire_oldest(void){
57 int i;
58 int mnAge = contentCache.nextAge;
59 int mn = -1;
60 for(i=0; i<contentCache.n; i++){
61 if( contentCache.a[i].age<mnAge ){
62 mnAge = contentCache.a[i].age;
63 mn = i;
64 }
65 }
66 if( mn>=0 ){
67 bag_remove(&contentCache.inCache, contentCache.a[mn].rid);
68 contentCache.szTotal -= blob_size(&contentCache.a[mn].content);
69 blob_reset(&contentCache.a[mn].content);
70 contentCache.n--;
71 contentCache.a[mn] = contentCache.a[contentCache.n];
72 }
73 }
74
75 /*
76 ** Add an entry to the content cache
77 */
78 void content_cache_insert(int rid, Blob *pBlob){
79 struct cacheLine *p;
80 if( contentCache.n>500 || contentCache.szTotal>50000000 ){
81 content_cache_expire_oldest();
82 }
83 if( contentCache.n>=contentCache.nAlloc ){
84 contentCache.nAlloc = contentCache.nAlloc*2 + 10;
85 contentCache.a = realloc(contentCache.a,
86 contentCache.nAlloc*sizeof(contentCache.a[0]));
87 if( contentCache.a==0 ) fossil_panic("out of memory");
88 }
89 p = &contentCache.a[contentCache.n++];
90 p->rid = rid;
91 p->age = contentCache.nextAge++;
92 contentCache.szTotal += blob_size(pBlob);
93 p->content = *pBlob;
94 blob_zero(pBlob);
95 bag_insert(&contentCache.inCache, rid);
96 }
97
98 /*
99 ** Clear the content cache.
100 */
101 void content_clear_cache(void){
@@ -67,11 +103,13 @@
103 for(i=0; i<contentCache.n; i++){
104 blob_reset(&contentCache.a[i].content);
105 }
106 bag_clear(&contentCache.missing);
107 bag_clear(&contentCache.available);
108 bag_clear(&contentCache.inCache);
109 contentCache.n = 0;
110 contentCache.szTotal = 0;
111 }
112
113 /*
114 ** Return the srcid associated with rid. Or return 0 if rid is
115 ** original content and not a delta.
@@ -95,32 +133,31 @@
133 ** true if it is. Return false if rid is a phantom or depends on
134 ** a phantom.
135 */
136 int content_is_available(int rid){
137 int srcid;
138 int depth = 0; /* Limit to recursion depth */
139 while( depth++ < 10000000 ){
140 if( bag_find(&contentCache.missing, rid) ){
141 return 0;
142 }
143 if( bag_find(&contentCache.available, rid) ){
144 return 1;
145 }
146 if( db_int(-1, "SELECT size FROM blob WHERE rid=%d", rid)<0 ){
147 bag_insert(&contentCache.missing, rid);
148 return 0;
149 }
150 srcid = findSrcid(rid);
151 if( srcid==0 ){
152 bag_insert(&contentCache.available, rid);
153 return 1;
154 }
155 rid = srcid;
156 }
157 fossil_panic("delta-loop in repository");
158 return 0;
 
159 }
160
161 /*
162 ** Mark artifact rid as being available now. Update the cache to
163 ** show that everything that was formerly unavailable because rid
@@ -163,113 +200,84 @@
200 }
201 db_reset(&q);
202 return rc;
203 }
204
 
205 /*
206 ** Extract the content for ID rid and put it into the
207 ** uninitialized blob. Return 1 on success. If the record
208 ** is a phantom, zero pBlob and return 0.
209 */
210 int content_get(int rid, Blob *pBlob){
211 int rc;
 
 
212 int i;
213 int nextRid;
214
215 assert( g.repositoryOpen );
216 blob_zero(pBlob);
217 if( rid==0 ) return 0;
218
219 /* Early out if we know the content is not available */
220 if( bag_find(&contentCache.missing, rid) ){
 
 
221 return 0;
222 }
223
224 /* Look for the artifact in the cache first */
225 if( bag_find(&contentCache.inCache, rid) ){
226 for(i=0; i<contentCache.n; i++){
227 if( contentCache.a[i].rid==rid ){
228 blob_copy(pBlob, &contentCache.a[i].content);
229 contentCache.a[i].age = contentCache.nextAge++;
230 return 1;
231 }
232 }
233 }
234
235 nextRid = findSrcid(rid);
236 if( nextRid==0 ){
237 rc = content_of_blob(rid, pBlob);
238 }else{
239 int n = 1;
240 int nAlloc = 10;
241 int *a = 0;
242 int mx;
243 Blob delta, next;
244
245 a = malloc( sizeof(a[0])*nAlloc );
246 if( a==0 ) fossil_panic("out of memory");
247 a[0] = rid;
248 a[1] = nextRid;
249 n = 1;
250 while( !bag_find(&contentCache.inCache, nextRid)
251 && (nextRid = findSrcid(nextRid))>0 ){
252 n++;
253 if( n>=nAlloc ){
254 nAlloc = nAlloc*2 + 10;
255 a = realloc(a, nAlloc*sizeof(a[0]));
256 if( a==0 ) fossil_panic("out of memory");
257 }
258 a[n] = nextRid;
259 }
260 mx = n;
261 rc = content_get(a[n], pBlob);
262 n--;
263 while( rc && n>=0 ){
264 rc = content_of_blob(a[n], &delta);
265 if( rc ){
266 blob_delta_apply(pBlob, &delta, &next);
267 blob_reset(&delta);
268 if( (mx-n)%8==0 ){
269 content_cache_insert(a[n+1], pBlob);
270 }else{
271 blob_reset(pBlob);
272 }
273 *pBlob = next;
274 }
275 n--;
276 }
277 free(a);
278 if( !rc ) blob_reset(pBlob);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279 }
280 if( rc==0 ){
281 bag_insert(&contentCache.missing, rid);
282 }else{
283 bag_insert(&contentCache.available, rid);
@@ -320,35 +328,45 @@
328
329 /*
330 ** When a record is converted from a phantom to a real record,
331 ** if that record has other records that are derived by delta,
332 ** then call manifest_crosslink() on those other records.
333 **
334 ** Tail recursion is used to minimize stack depth.
335 */
336 void after_dephantomize(int rid, int linkFlag){
337 Stmt q;
338 int nChildAlloc = 0;
339 int *aChild = 0;
340
341 while( rid ){
342 int nChildUsed = 0;
343 int i;
344 if( linkFlag ){
345 Blob content;
346 content_get(rid, &content);
347 manifest_crosslink(rid, &content);
348 blob_reset(&content);
349 }
350 db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid);
351 while( db_step(&q)==SQLITE_ROW ){
352 int child = db_column_int(&q, 0);
353 if( nChildUsed>=nChildAlloc ){
354 nChildAlloc = nChildAlloc*2 + 10;
355 aChild = realloc(aChild, nChildAlloc*sizeof(aChild));
356 if( aChild==0 ) fossil_panic("out of memory");
357 }
358 aChild[nChildUsed++] = child;
359 }
360 db_finalize(&q);
361 for(i=1; i<nChildUsed; i++){
362 after_dephantomize(aChild[i], 1);
363 }
364 rid = nChildUsed>0 ? aChild[0] : 0;
365 linkFlag = 1;
366 }
367 free(aChild);
368 }
369
370 /*
371 ** Write content into the database. Return the record ID. If the
372 ** content is already in the database, just return the record ID.
373
374 DDED src/event.c
--- a/src/event.c
+++ b/src/event.c
@@ -0,0 +1,2 @@
1
+mParsedblobblobmParsed?name=EVENTID&de='event-%q();
2
+}
--- a/src/event.c
+++ b/src/event.c
@@ -0,0 +1,2 @@
 
 
--- a/src/event.c
+++ b/src/event.c
@@ -0,0 +1,2 @@
1 mParsedblobblobmParsed?name=EVENTID&de='event-%q();
2 }
+89 -66
--- src/info.c
+++ src/info.c
@@ -779,11 +779,11 @@
779779
}
780780
}
781781
db_finalize(&q);
782782
if( nWiki==0 ){
783783
db_prepare(&q,
784
- "SELECT datetime(mtime), user, comment, type, uuid"
784
+ "SELECT datetime(mtime), user, comment, type, uuid, tagid"
785785
" FROM event, blob"
786786
" WHERE event.objid=%d"
787787
" AND blob.rid=%d",
788788
rid, rid
789789
);
@@ -800,14 +800,19 @@
800800
@ Wiki edit
801801
}else if( zType[0]=='t' ){
802802
@ Ticket change
803803
}else if( zType[0]=='c' ){
804804
@ Manifest of check-in
805
+ }else if( zType[0]=='e' ){
806
+ @ Instance of event
807
+ hyperlink_to_event_tagid(db_column_int(&q, 5));
805808
}else{
806809
@ Control file referencing
807810
}
808
- hyperlink_to_uuid(zUuid);
811
+ if( zType[0]!='e' ){
812
+ hyperlink_to_uuid(zUuid);
813
+ }
809814
@ - %w(zCom) by
810815
hyperlink_to_user(zUser,zDate," on");
811816
hyperlink_to_date(zDate, ".");
812817
if( pDownloadName && blob_size(pDownloadName)==0 ){
813818
blob_appendf(pDownloadName, "%.10s.txt", zUuid);
@@ -1260,10 +1265,90 @@
12601265
}else
12611266
{
12621267
artifact_page();
12631268
}
12641269
}
1270
+
1271
+/*
1272
+** Generate HTML that will present the user with a selection of
1273
+** potential background colors for timeline entries.
1274
+*/
1275
+void render_color_chooser(
1276
+ int fPropagate, /* Default value for propagation */
1277
+ const char *zDefaultColor, /* The current default color */
1278
+ const char *zIdPropagate, /* ID of form element checkbox. NULL for none */
1279
+ const char *zId, /* The ID of the form element */
1280
+ const char *zIdCustom /* ID of text box for custom color */
1281
+){
1282
+ static const struct SampleColors {
1283
+ const char *zCName;
1284
+ const char *zColor;
1285
+ } aColor[] = {
1286
+ { "(none)", "" },
1287
+ { "#f2dcdc", "#f2dcdc" },
1288
+ { "#f0ffc0", "#f0ffc0" },
1289
+ { "#bde5d6", "#bde5d6" },
1290
+ { "#c0ffc0", "#c0ffc0" },
1291
+ { "#c0fff0", "#c0fff0" },
1292
+ { "#c0f0ff", "#c0f0ff" },
1293
+ { "#d0c0ff", "#d0c0ff" },
1294
+ { "#ffc0ff", "#ffc0ff" },
1295
+ { "#ffc0d0", "#ffc0d0" },
1296
+ { "#fff0c0", "#fff0c0" },
1297
+ { "#c0c0c0", "#c0c0c0" },
1298
+ { "custom", "##" },
1299
+ };
1300
+ int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
1301
+ int stdClrFound = 0;
1302
+ int i;
1303
+
1304
+ @ <table border="0" cellpadding="0" cellspacing="1">
1305
+ if( zIdPropagate ){
1306
+ @ <tr><td colspan="6" align="left">
1307
+ if( fPropagate ){
1308
+ @ <input type="checkbox" name="%s(zIdPropagate)" checked="checked" />
1309
+ }else{
1310
+ @ <input type="checkbox" name="%s(zIdPropagate)" />
1311
+ }
1312
+ @ Propagate color to descendants</td></tr>
1313
+ }
1314
+ @ <tr>
1315
+ for(i=0; i<nColor; i++){
1316
+ if( aColor[i].zColor[0] ){
1317
+ @ <td style="background-color: %h(aColor[i].zColor);">
1318
+ }else{
1319
+ @ <td>
1320
+ }
1321
+ if( strcmp(zDefaultColor, aColor[i].zColor)==0 ){
1322
+ @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)"
1323
+ @ checked="checked" />
1324
+ stdClrFound=1;
1325
+ }else{
1326
+ @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)" />
1327
+ }
1328
+ @ %h(aColor[i].zCName)</td>
1329
+ if( (i%6)==5 && i+1<nColor ){
1330
+ @ </tr><tr>
1331
+ }
1332
+ }
1333
+ @ </tr><tr>
1334
+ if (stdClrFound){
1335
+ @ <td colspan="6">
1336
+ @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)" />
1337
+ }else{
1338
+ @ <td style="background-color: %h(zDefaultColor);" colspan="6">
1339
+ @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)"
1340
+ @ checked="checked" />
1341
+ }
1342
+ @ %h(aColor[i].zCName)&nbsp;
1343
+ @ <input type="text" name="%s(zIdCustom)"
1344
+ @ id="%s(zIdCustom)" class="checkinUserColor"
1345
+ @ value="%h(stdClrFound?"":zDefaultColor)" />
1346
+ @ </td>
1347
+ @ </tr>
1348
+ @ </table>
1349
+}
12651350
12661351
/*
12671352
** WEBPAGE: ci_edit
12681353
** URL: ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER
12691354
**
@@ -1290,31 +1375,10 @@
12901375
const char *zCloseFlag;
12911376
int fPropagateColor;
12921377
char *zUuid;
12931378
Blob comment;
12941379
Stmt q;
1295
- static const struct SampleColors {
1296
- const char *zCName;
1297
- const char *zColor;
1298
- } aColor[] = {
1299
- { "(none)", "" },
1300
- { "#f2dcdc", "#f2dcdc" },
1301
- { "#f0ffc0", "#f0ffc0" },
1302
- { "#bde5d6", "#bde5d6" },
1303
- { "#c0ffc0", "#c0ffc0" },
1304
- { "#c0fff0", "#c0fff0" },
1305
- { "#c0f0ff", "#c0f0ff" },
1306
- { "#d0c0ff", "#d0c0ff" },
1307
- { "#ffc0ff", "#ffc0ff" },
1308
- { "#ffc0d0", "#ffc0d0" },
1309
- { "#fff0c0", "#fff0c0" },
1310
- { "#c0c0c0", "#c0c0c0" },
1311
- { "custom", "##" },
1312
- };
1313
- int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
1314
- int stdClrFound;
1315
- int i;
13161380
13171381
login_check_credentials();
13181382
if( !g.okWrite ){ login_needed(); return; }
13191383
rid = name_to_rid(P("r"));
13201384
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1334,11 +1398,11 @@
13341398
if( zDate==0 ) fossil_redirect_home();
13351399
zNewDate = PD("dt",zDate);
13361400
zColor = db_text("", "SELECT bgcolor"
13371401
" FROM event WHERE objid=%d", rid);
13381402
zNewColor = PD("clr",zColor);
1339
- if( strcmp(zNewColor,aColor[nColor].zColor)==0 ){
1403
+ if( strcmp(zNewColor,"##")==0 ){
13401404
zNewColor = P("clrcust");
13411405
}
13421406
fPropagateColor = P("pclr")!=0;
13431407
zNewTagFlag = P("newtag") ? " checked" : "";
13441408
zNewTag = PD("tagname","");
@@ -1501,52 +1565,11 @@
15011565
@ <input type="text" name="dt" size="20" value="%h(zNewDate)" />
15021566
@ </td></tr>
15031567
15041568
@ <tr><td align="right" valign="top"><b>Background Color:</b></td>
15051569
@ <td valign="top">
1506
- @ <table border="0" cellpadding="0" cellspacing="1">
1507
- @ <tr><td colspan="6" align="left">
1508
- if( fPropagateColor ){
1509
- @ <input type="checkbox" name="pclr" checked="checked" />
1510
- }else{
1511
- @ <input type="checkbox" name="pclr" />
1512
- }
1513
- @ Propagate color to descendants</td></tr>
1514
- @ <tr>
1515
- for(i=0,stdClrFound=0; i<nColor; i++){
1516
- if( aColor[i].zColor[0] ){
1517
- @ <td style="background-color: %h(aColor[i].zColor);">
1518
- }else{
1519
- @ <td>
1520
- }
1521
- if( strcmp(zNewColor, aColor[i].zColor)==0 ){
1522
- @ <input type="radio" name="clr" value="%h(aColor[i].zColor)"
1523
- @ checked="checked" />
1524
- stdClrFound=1;
1525
- }else{
1526
- @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" />
1527
- }
1528
- @ %h(aColor[i].zCName)</td>
1529
- if( (i%6)==5 && i+1<nColor ){
1530
- @ </tr><tr>
1531
- }
1532
- }
1533
- @ </tr><tr>
1534
- if (stdClrFound){
1535
- @ <td colspan="6">
1536
- @ <input type="radio" name="clr" value="%h(aColor[nColor].zColor)" />
1537
- }else{
1538
- @ <td style="background-color: %h(zNewColor);" colspan="6">
1539
- @ <input type="radio" name="clr" value="%h(aColor[nColor].zColor)"
1540
- @ checked="checked" />
1541
- }
1542
- @ %h(aColor[i].zCName)&nbsp;
1543
- @ <input type="text" name="clrcust" id="clrcust" class="checkinUserColor"
1544
- @ value="%h(stdClrFound?"":zNewColor)" />
1545
- @ </td>
1546
- @ </tr>
1547
- @ </table>
1570
+ render_color_chooser(fPropagateColor, zNewColor, "pclr", "clr", "clrcust");
15481571
@ </td></tr>
15491572
15501573
@ <tr><td align="right" valign="top"><b>Tags:</b></td>
15511574
@ <td valign="top">
15521575
@ <input type="checkbox" name="newtag"%s(zNewTagFlag) />
15531576
--- src/info.c
+++ src/info.c
@@ -779,11 +779,11 @@
779 }
780 }
781 db_finalize(&q);
782 if( nWiki==0 ){
783 db_prepare(&q,
784 "SELECT datetime(mtime), user, comment, type, uuid"
785 " FROM event, blob"
786 " WHERE event.objid=%d"
787 " AND blob.rid=%d",
788 rid, rid
789 );
@@ -800,14 +800,19 @@
800 @ Wiki edit
801 }else if( zType[0]=='t' ){
802 @ Ticket change
803 }else if( zType[0]=='c' ){
804 @ Manifest of check-in
 
 
 
805 }else{
806 @ Control file referencing
807 }
808 hyperlink_to_uuid(zUuid);
 
 
809 @ - %w(zCom) by
810 hyperlink_to_user(zUser,zDate," on");
811 hyperlink_to_date(zDate, ".");
812 if( pDownloadName && blob_size(pDownloadName)==0 ){
813 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
@@ -1260,10 +1265,90 @@
1260 }else
1261 {
1262 artifact_page();
1263 }
1264 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1265
1266 /*
1267 ** WEBPAGE: ci_edit
1268 ** URL: ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER
1269 **
@@ -1290,31 +1375,10 @@
1290 const char *zCloseFlag;
1291 int fPropagateColor;
1292 char *zUuid;
1293 Blob comment;
1294 Stmt q;
1295 static const struct SampleColors {
1296 const char *zCName;
1297 const char *zColor;
1298 } aColor[] = {
1299 { "(none)", "" },
1300 { "#f2dcdc", "#f2dcdc" },
1301 { "#f0ffc0", "#f0ffc0" },
1302 { "#bde5d6", "#bde5d6" },
1303 { "#c0ffc0", "#c0ffc0" },
1304 { "#c0fff0", "#c0fff0" },
1305 { "#c0f0ff", "#c0f0ff" },
1306 { "#d0c0ff", "#d0c0ff" },
1307 { "#ffc0ff", "#ffc0ff" },
1308 { "#ffc0d0", "#ffc0d0" },
1309 { "#fff0c0", "#fff0c0" },
1310 { "#c0c0c0", "#c0c0c0" },
1311 { "custom", "##" },
1312 };
1313 int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
1314 int stdClrFound;
1315 int i;
1316
1317 login_check_credentials();
1318 if( !g.okWrite ){ login_needed(); return; }
1319 rid = name_to_rid(P("r"));
1320 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1334,11 +1398,11 @@
1334 if( zDate==0 ) fossil_redirect_home();
1335 zNewDate = PD("dt",zDate);
1336 zColor = db_text("", "SELECT bgcolor"
1337 " FROM event WHERE objid=%d", rid);
1338 zNewColor = PD("clr",zColor);
1339 if( strcmp(zNewColor,aColor[nColor].zColor)==0 ){
1340 zNewColor = P("clrcust");
1341 }
1342 fPropagateColor = P("pclr")!=0;
1343 zNewTagFlag = P("newtag") ? " checked" : "";
1344 zNewTag = PD("tagname","");
@@ -1501,52 +1565,11 @@
1501 @ <input type="text" name="dt" size="20" value="%h(zNewDate)" />
1502 @ </td></tr>
1503
1504 @ <tr><td align="right" valign="top"><b>Background Color:</b></td>
1505 @ <td valign="top">
1506 @ <table border="0" cellpadding="0" cellspacing="1">
1507 @ <tr><td colspan="6" align="left">
1508 if( fPropagateColor ){
1509 @ <input type="checkbox" name="pclr" checked="checked" />
1510 }else{
1511 @ <input type="checkbox" name="pclr" />
1512 }
1513 @ Propagate color to descendants</td></tr>
1514 @ <tr>
1515 for(i=0,stdClrFound=0; i<nColor; i++){
1516 if( aColor[i].zColor[0] ){
1517 @ <td style="background-color: %h(aColor[i].zColor);">
1518 }else{
1519 @ <td>
1520 }
1521 if( strcmp(zNewColor, aColor[i].zColor)==0 ){
1522 @ <input type="radio" name="clr" value="%h(aColor[i].zColor)"
1523 @ checked="checked" />
1524 stdClrFound=1;
1525 }else{
1526 @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" />
1527 }
1528 @ %h(aColor[i].zCName)</td>
1529 if( (i%6)==5 && i+1<nColor ){
1530 @ </tr><tr>
1531 }
1532 }
1533 @ </tr><tr>
1534 if (stdClrFound){
1535 @ <td colspan="6">
1536 @ <input type="radio" name="clr" value="%h(aColor[nColor].zColor)" />
1537 }else{
1538 @ <td style="background-color: %h(zNewColor);" colspan="6">
1539 @ <input type="radio" name="clr" value="%h(aColor[nColor].zColor)"
1540 @ checked="checked" />
1541 }
1542 @ %h(aColor[i].zCName)&nbsp;
1543 @ <input type="text" name="clrcust" id="clrcust" class="checkinUserColor"
1544 @ value="%h(stdClrFound?"":zNewColor)" />
1545 @ </td>
1546 @ </tr>
1547 @ </table>
1548 @ </td></tr>
1549
1550 @ <tr><td align="right" valign="top"><b>Tags:</b></td>
1551 @ <td valign="top">
1552 @ <input type="checkbox" name="newtag"%s(zNewTagFlag) />
1553
--- src/info.c
+++ src/info.c
@@ -779,11 +779,11 @@
779 }
780 }
781 db_finalize(&q);
782 if( nWiki==0 ){
783 db_prepare(&q,
784 "SELECT datetime(mtime), user, comment, type, uuid, tagid"
785 " FROM event, blob"
786 " WHERE event.objid=%d"
787 " AND blob.rid=%d",
788 rid, rid
789 );
@@ -800,14 +800,19 @@
800 @ Wiki edit
801 }else if( zType[0]=='t' ){
802 @ Ticket change
803 }else if( zType[0]=='c' ){
804 @ Manifest of check-in
805 }else if( zType[0]=='e' ){
806 @ Instance of event
807 hyperlink_to_event_tagid(db_column_int(&q, 5));
808 }else{
809 @ Control file referencing
810 }
811 if( zType[0]!='e' ){
812 hyperlink_to_uuid(zUuid);
813 }
814 @ - %w(zCom) by
815 hyperlink_to_user(zUser,zDate," on");
816 hyperlink_to_date(zDate, ".");
817 if( pDownloadName && blob_size(pDownloadName)==0 ){
818 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
@@ -1260,10 +1265,90 @@
1265 }else
1266 {
1267 artifact_page();
1268 }
1269 }
1270
1271 /*
1272 ** Generate HTML that will present the user with a selection of
1273 ** potential background colors for timeline entries.
1274 */
1275 void render_color_chooser(
1276 int fPropagate, /* Default value for propagation */
1277 const char *zDefaultColor, /* The current default color */
1278 const char *zIdPropagate, /* ID of form element checkbox. NULL for none */
1279 const char *zId, /* The ID of the form element */
1280 const char *zIdCustom /* ID of text box for custom color */
1281 ){
1282 static const struct SampleColors {
1283 const char *zCName;
1284 const char *zColor;
1285 } aColor[] = {
1286 { "(none)", "" },
1287 { "#f2dcdc", "#f2dcdc" },
1288 { "#f0ffc0", "#f0ffc0" },
1289 { "#bde5d6", "#bde5d6" },
1290 { "#c0ffc0", "#c0ffc0" },
1291 { "#c0fff0", "#c0fff0" },
1292 { "#c0f0ff", "#c0f0ff" },
1293 { "#d0c0ff", "#d0c0ff" },
1294 { "#ffc0ff", "#ffc0ff" },
1295 { "#ffc0d0", "#ffc0d0" },
1296 { "#fff0c0", "#fff0c0" },
1297 { "#c0c0c0", "#c0c0c0" },
1298 { "custom", "##" },
1299 };
1300 int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
1301 int stdClrFound = 0;
1302 int i;
1303
1304 @ <table border="0" cellpadding="0" cellspacing="1">
1305 if( zIdPropagate ){
1306 @ <tr><td colspan="6" align="left">
1307 if( fPropagate ){
1308 @ <input type="checkbox" name="%s(zIdPropagate)" checked="checked" />
1309 }else{
1310 @ <input type="checkbox" name="%s(zIdPropagate)" />
1311 }
1312 @ Propagate color to descendants</td></tr>
1313 }
1314 @ <tr>
1315 for(i=0; i<nColor; i++){
1316 if( aColor[i].zColor[0] ){
1317 @ <td style="background-color: %h(aColor[i].zColor);">
1318 }else{
1319 @ <td>
1320 }
1321 if( strcmp(zDefaultColor, aColor[i].zColor)==0 ){
1322 @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)"
1323 @ checked="checked" />
1324 stdClrFound=1;
1325 }else{
1326 @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)" />
1327 }
1328 @ %h(aColor[i].zCName)</td>
1329 if( (i%6)==5 && i+1<nColor ){
1330 @ </tr><tr>
1331 }
1332 }
1333 @ </tr><tr>
1334 if (stdClrFound){
1335 @ <td colspan="6">
1336 @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)" />
1337 }else{
1338 @ <td style="background-color: %h(zDefaultColor);" colspan="6">
1339 @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)"
1340 @ checked="checked" />
1341 }
1342 @ %h(aColor[i].zCName)&nbsp;
1343 @ <input type="text" name="%s(zIdCustom)"
1344 @ id="%s(zIdCustom)" class="checkinUserColor"
1345 @ value="%h(stdClrFound?"":zDefaultColor)" />
1346 @ </td>
1347 @ </tr>
1348 @ </table>
1349 }
1350
1351 /*
1352 ** WEBPAGE: ci_edit
1353 ** URL: ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER
1354 **
@@ -1290,31 +1375,10 @@
1375 const char *zCloseFlag;
1376 int fPropagateColor;
1377 char *zUuid;
1378 Blob comment;
1379 Stmt q;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1380
1381 login_check_credentials();
1382 if( !g.okWrite ){ login_needed(); return; }
1383 rid = name_to_rid(P("r"));
1384 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1334,11 +1398,11 @@
1398 if( zDate==0 ) fossil_redirect_home();
1399 zNewDate = PD("dt",zDate);
1400 zColor = db_text("", "SELECT bgcolor"
1401 " FROM event WHERE objid=%d", rid);
1402 zNewColor = PD("clr",zColor);
1403 if( strcmp(zNewColor,"##")==0 ){
1404 zNewColor = P("clrcust");
1405 }
1406 fPropagateColor = P("pclr")!=0;
1407 zNewTagFlag = P("newtag") ? " checked" : "";
1408 zNewTag = PD("tagname","");
@@ -1501,52 +1565,11 @@
1565 @ <input type="text" name="dt" size="20" value="%h(zNewDate)" />
1566 @ </td></tr>
1567
1568 @ <tr><td align="right" valign="top"><b>Background Color:</b></td>
1569 @ <td valign="top">
1570 render_color_chooser(fPropagateColor, zNewColor, "pclr", "clr", "clrcust");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1571 @ </td></tr>
1572
1573 @ <tr><td align="right" valign="top"><b>Tags:</b></td>
1574 @ <td valign="top">
1575 @ <input type="checkbox" name="newtag"%s(zNewTagFlag) />
1576
+12 -2
--- src/main.mk
+++ src/main.mk
@@ -35,10 +35,11 @@
3535
$(SRCDIR)/descendants.c \
3636
$(SRCDIR)/diff.c \
3737
$(SRCDIR)/diffcmd.c \
3838
$(SRCDIR)/doc.c \
3939
$(SRCDIR)/encode.c \
40
+ $(SRCDIR)/event.c \
4041
$(SRCDIR)/file.c \
4142
$(SRCDIR)/finfo.c \
4243
$(SRCDIR)/graph.c \
4344
$(SRCDIR)/http.c \
4445
$(SRCDIR)/http_socket.c \
@@ -108,10 +109,11 @@
108109
descendants_.c \
109110
diff_.c \
110111
diffcmd_.c \
111112
doc_.c \
112113
encode_.c \
114
+ event_.c \
113115
file_.c \
114116
finfo_.c \
115117
graph_.c \
116118
http_.c \
117119
http_socket_.c \
@@ -181,10 +183,11 @@
181183
$(OBJDIR)/descendants.o \
182184
$(OBJDIR)/diff.o \
183185
$(OBJDIR)/diffcmd.o \
184186
$(OBJDIR)/doc.o \
185187
$(OBJDIR)/encode.o \
188
+ $(OBJDIR)/event.o \
186189
$(OBJDIR)/file.o \
187190
$(OBJDIR)/finfo.o \
188191
$(OBJDIR)/graph.o \
189192
$(OBJDIR)/http.o \
190193
$(OBJDIR)/http_socket.o \
@@ -273,16 +276,16 @@
273276
# noop
274277
275278
clean:
276279
rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h
277280
rm -f translate makeheaders mkindex page_index.h headers
278
- rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h
281
+ rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h event.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h
279282
280283
page_index.h: $(TRANS_SRC) mkindex
281284
./mkindex $(TRANS_SRC) >$@
282285
headers: page_index.h makeheaders VERSION.h
283
- ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
286
+ ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
284287
touch headers
285288
headers: Makefile
286289
Makefile:
287290
add_.c: $(SRCDIR)/add.c translate
288291
./translate $(SRCDIR)/add.c >add_.c
@@ -450,10 +453,17 @@
450453
451454
$(OBJDIR)/encode.o: encode_.c encode.h $(SRCDIR)/config.h
452455
$(XTCC) -o $(OBJDIR)/encode.o -c encode_.c
453456
454457
encode.h: headers
458
+event_.c: $(SRCDIR)/event.c translate
459
+ ./translate $(SRCDIR)/event.c >event_.c
460
+
461
+$(OBJDIR)/event.o: event_.c event.h $(SRCDIR)/config.h
462
+ $(XTCC) -o $(OBJDIR)/event.o -c event_.c
463
+
464
+event.h: headers
455465
file_.c: $(SRCDIR)/file.c translate
456466
./translate $(SRCDIR)/file.c >file_.c
457467
458468
$(OBJDIR)/file.o: file_.c file.h $(SRCDIR)/config.h
459469
$(XTCC) -o $(OBJDIR)/file.o -c file_.c
460470
--- src/main.mk
+++ src/main.mk
@@ -35,10 +35,11 @@
35 $(SRCDIR)/descendants.c \
36 $(SRCDIR)/diff.c \
37 $(SRCDIR)/diffcmd.c \
38 $(SRCDIR)/doc.c \
39 $(SRCDIR)/encode.c \
 
40 $(SRCDIR)/file.c \
41 $(SRCDIR)/finfo.c \
42 $(SRCDIR)/graph.c \
43 $(SRCDIR)/http.c \
44 $(SRCDIR)/http_socket.c \
@@ -108,10 +109,11 @@
108 descendants_.c \
109 diff_.c \
110 diffcmd_.c \
111 doc_.c \
112 encode_.c \
 
113 file_.c \
114 finfo_.c \
115 graph_.c \
116 http_.c \
117 http_socket_.c \
@@ -181,10 +183,11 @@
181 $(OBJDIR)/descendants.o \
182 $(OBJDIR)/diff.o \
183 $(OBJDIR)/diffcmd.o \
184 $(OBJDIR)/doc.o \
185 $(OBJDIR)/encode.o \
 
186 $(OBJDIR)/file.o \
187 $(OBJDIR)/finfo.o \
188 $(OBJDIR)/graph.o \
189 $(OBJDIR)/http.o \
190 $(OBJDIR)/http_socket.o \
@@ -273,16 +276,16 @@
273 # noop
274
275 clean:
276 rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h
277 rm -f translate makeheaders mkindex page_index.h headers
278 rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h
279
280 page_index.h: $(TRANS_SRC) mkindex
281 ./mkindex $(TRANS_SRC) >$@
282 headers: page_index.h makeheaders VERSION.h
283 ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
284 touch headers
285 headers: Makefile
286 Makefile:
287 add_.c: $(SRCDIR)/add.c translate
288 ./translate $(SRCDIR)/add.c >add_.c
@@ -450,10 +453,17 @@
450
451 $(OBJDIR)/encode.o: encode_.c encode.h $(SRCDIR)/config.h
452 $(XTCC) -o $(OBJDIR)/encode.o -c encode_.c
453
454 encode.h: headers
 
 
 
 
 
 
 
455 file_.c: $(SRCDIR)/file.c translate
456 ./translate $(SRCDIR)/file.c >file_.c
457
458 $(OBJDIR)/file.o: file_.c file.h $(SRCDIR)/config.h
459 $(XTCC) -o $(OBJDIR)/file.o -c file_.c
460
--- src/main.mk
+++ src/main.mk
@@ -35,10 +35,11 @@
35 $(SRCDIR)/descendants.c \
36 $(SRCDIR)/diff.c \
37 $(SRCDIR)/diffcmd.c \
38 $(SRCDIR)/doc.c \
39 $(SRCDIR)/encode.c \
40 $(SRCDIR)/event.c \
41 $(SRCDIR)/file.c \
42 $(SRCDIR)/finfo.c \
43 $(SRCDIR)/graph.c \
44 $(SRCDIR)/http.c \
45 $(SRCDIR)/http_socket.c \
@@ -108,10 +109,11 @@
109 descendants_.c \
110 diff_.c \
111 diffcmd_.c \
112 doc_.c \
113 encode_.c \
114 event_.c \
115 file_.c \
116 finfo_.c \
117 graph_.c \
118 http_.c \
119 http_socket_.c \
@@ -181,10 +183,11 @@
183 $(OBJDIR)/descendants.o \
184 $(OBJDIR)/diff.o \
185 $(OBJDIR)/diffcmd.o \
186 $(OBJDIR)/doc.o \
187 $(OBJDIR)/encode.o \
188 $(OBJDIR)/event.o \
189 $(OBJDIR)/file.o \
190 $(OBJDIR)/finfo.o \
191 $(OBJDIR)/graph.o \
192 $(OBJDIR)/http.o \
193 $(OBJDIR)/http_socket.o \
@@ -273,16 +276,16 @@
276 # noop
277
278 clean:
279 rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h
280 rm -f translate makeheaders mkindex page_index.h headers
281 rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h event.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h
282
283 page_index.h: $(TRANS_SRC) mkindex
284 ./mkindex $(TRANS_SRC) >$@
285 headers: page_index.h makeheaders VERSION.h
286 ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h
287 touch headers
288 headers: Makefile
289 Makefile:
290 add_.c: $(SRCDIR)/add.c translate
291 ./translate $(SRCDIR)/add.c >add_.c
@@ -450,10 +453,17 @@
453
454 $(OBJDIR)/encode.o: encode_.c encode.h $(SRCDIR)/config.h
455 $(XTCC) -o $(OBJDIR)/encode.o -c encode_.c
456
457 encode.h: headers
458 event_.c: $(SRCDIR)/event.c translate
459 ./translate $(SRCDIR)/event.c >event_.c
460
461 $(OBJDIR)/event.o: event_.c event.h $(SRCDIR)/config.h
462 $(XTCC) -o $(OBJDIR)/event.o -c event_.c
463
464 event.h: headers
465 file_.c: $(SRCDIR)/file.c translate
466 ./translate $(SRCDIR)/file.c >file_.c
467
468 $(OBJDIR)/file.o: file_.c file.h $(SRCDIR)/config.h
469 $(XTCC) -o $(OBJDIR)/file.o -c file_.c
470
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -29,10 +29,11 @@
2929
descendants
3030
diff
3131
diffcmd
3232
doc
3333
encode
34
+ event
3435
file
3536
finfo
3637
graph
3738
http
3839
http_socket
3940
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -29,10 +29,11 @@
29 descendants
30 diff
31 diffcmd
32 doc
33 encode
 
34 file
35 finfo
36 graph
37 http
38 http_socket
39
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -29,10 +29,11 @@
29 descendants
30 diff
31 diffcmd
32 doc
33 encode
34 event
35 file
36 finfo
37 graph
38 http
39 http_socket
40
+99 -7
--- src/manifest.c
+++ src/manifest.c
@@ -32,10 +32,11 @@
3232
#define CFTYPE_CLUSTER 2
3333
#define CFTYPE_CONTROL 3
3434
#define CFTYPE_WIKI 4
3535
#define CFTYPE_TICKET 5
3636
#define CFTYPE_ATTACHMENT 6
37
+#define CFTYPE_EVENT 7
3738
3839
/*
3940
** A parsed manifest or cluster.
4041
*/
4142
struct Manifest {
@@ -45,10 +46,12 @@
4546
double rDate; /* Date and time from D card. 0.0 if no D card. */
4647
char *zUser; /* Name of the user from the U card. */
4748
char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */
4849
char *zWiki; /* Text of the wiki page. W card. */
4950
char *zWikiTitle; /* Name of the wiki page. L card. */
51
+ double rEventDate; /* Date of an event. E card. */
52
+ char *zEventId; /* UUID for an event. E card. */
5053
char *zTicketUuid; /* UUID for a ticket. K card. */
5154
char *zAttachName; /* Filename of an attachment. A card. */
5255
char *zAttachSrc; /* UUID of document being attached. A card. */
5356
char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */
5457
int nFile; /* Number of F cards */
@@ -230,10 +233,35 @@
230233
if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
231234
zDate = blob_terminate(&a1);
232235
p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate);
233236
break;
234237
}
238
+
239
+ /*
240
+ ** E <timestamp> <uuid>
241
+ **
242
+ ** An "event" card that contains the timestamp of the event in the
243
+ ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event.
244
+ ** The event timestamp is distinct from the D timestamp. The D
245
+ ** timestamp is when the artifact was created whereas the E timestamp
246
+ ** is when the specific event is said to occur.
247
+ */
248
+ case 'E': {
249
+ char *zEDate;
250
+ md5sum_step_text(blob_buffer(&line), blob_size(&line));
251
+ if( p->rEventDate!=0.0 ) goto manifest_syntax_error;
252
+ if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
253
+ if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
254
+ if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
255
+ zEDate = blob_terminate(&a1);
256
+ p->rEventDate = db_double(0.0, "SELECT julianday(%Q)", zEDate);
257
+ if( p->rEventDate<=0.0 ) goto manifest_syntax_error;
258
+ if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
259
+ p->zEventId = blob_terminate(&a2);
260
+ if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error;
261
+ break;
262
+ }
235263
236264
/*
237265
** F <filename> <uuid> ?<permissions>? ?<old-name>?
238266
**
239267
** Identifies a file in a manifest. Multiple F lines are
@@ -563,15 +591,16 @@
563591
}
564592
if( !seenHeader ) goto manifest_syntax_error;
565593
566594
if( p->nFile>0 || p->zRepoCksum!=0 ){
567595
if( p->nCChild>0 ) goto manifest_syntax_error;
568
- if( p->rDate==0.0 ) goto manifest_syntax_error;
596
+ if( p->rDate<=0.0 ) goto manifest_syntax_error;
569597
if( p->nField>0 ) goto manifest_syntax_error;
570598
if( p->zTicketUuid ) goto manifest_syntax_error;
571599
if( p->zWiki ) goto manifest_syntax_error;
572600
if( p->zWikiTitle ) goto manifest_syntax_error;
601
+ if( p->zEventId ) goto manifest_syntax_error;
573602
if( p->zTicketUuid ) goto manifest_syntax_error;
574603
if( p->zAttachName ) goto manifest_syntax_error;
575604
p->type = CFTYPE_MANIFEST;
576605
}else if( p->nCChild>0 ){
577606
if( p->rDate>0.0 ) goto manifest_syntax_error;
@@ -581,26 +610,41 @@
581610
if( p->nParent>0 ) goto manifest_syntax_error;
582611
if( p->nField>0 ) goto manifest_syntax_error;
583612
if( p->zTicketUuid ) goto manifest_syntax_error;
584613
if( p->zWiki ) goto manifest_syntax_error;
585614
if( p->zWikiTitle ) goto manifest_syntax_error;
615
+ if( p->zEventId ) goto manifest_syntax_error;
586616
if( p->zAttachName ) goto manifest_syntax_error;
587617
if( !seenZ ) goto manifest_syntax_error;
588618
p->type = CFTYPE_CLUSTER;
589619
}else if( p->nField>0 ){
590
- if( p->rDate==0.0 ) goto manifest_syntax_error;
620
+ if( p->rDate<=0.0 ) goto manifest_syntax_error;
591621
if( p->zWiki ) goto manifest_syntax_error;
592622
if( p->zWikiTitle ) goto manifest_syntax_error;
623
+ if( p->zEventId ) goto manifest_syntax_error;
593624
if( p->nCChild>0 ) goto manifest_syntax_error;
594625
if( p->nTag>0 ) goto manifest_syntax_error;
595626
if( p->zTicketUuid==0 ) goto manifest_syntax_error;
596627
if( p->zUser==0 ) goto manifest_syntax_error;
597628
if( p->zAttachName ) goto manifest_syntax_error;
598629
if( !seenZ ) goto manifest_syntax_error;
599630
p->type = CFTYPE_TICKET;
631
+ }else if( p->zEventId ){
632
+ if( p->rDate<=0.0 ) goto manifest_syntax_error;
633
+ if( p->nCChild>0 ) goto manifest_syntax_error;
634
+ if( p->zTicketUuid!=0 ) goto manifest_syntax_error;
635
+ if( p->zWikiTitle!=0 ) goto manifest_syntax_error;
636
+ if( p->zWiki==0 ) goto manifest_syntax_error;
637
+ if( p->zAttachName ) goto manifest_syntax_error;
638
+ for(i=0; i<p->nTag; i++){
639
+ if( p->aTag[i].zName[0]!='+' ) goto manifest_syntax_error;
640
+ if( p->aTag[i].zUuid!=0 ) goto manifest_syntax_error;
641
+ }
642
+ if( !seenZ ) goto manifest_syntax_error;
643
+ p->type = CFTYPE_EVENT;
600644
}else if( p->zWiki!=0 ){
601
- if( p->rDate==0.0 ) goto manifest_syntax_error;
645
+ if( p->rDate<=0.0 ) goto manifest_syntax_error;
602646
if( p->nCChild>0 ) goto manifest_syntax_error;
603647
if( p->nTag>0 ) goto manifest_syntax_error;
604648
if( p->zTicketUuid!=0 ) goto manifest_syntax_error;
605649
if( p->zWikiTitle==0 ) goto manifest_syntax_error;
606650
if( p->zAttachName ) goto manifest_syntax_error;
@@ -614,11 +658,11 @@
614658
if( p->zAttachName ) goto manifest_syntax_error;
615659
if( !seenZ ) goto manifest_syntax_error;
616660
p->type = CFTYPE_CONTROL;
617661
}else if( p->zAttachName ){
618662
if( p->nCChild>0 ) goto manifest_syntax_error;
619
- if( p->rDate==0.0 ) goto manifest_syntax_error;
663
+ if( p->rDate<=0.0 ) goto manifest_syntax_error;
620664
if( p->zTicketUuid ) goto manifest_syntax_error;
621665
if( p->zWikiTitle ) goto manifest_syntax_error;
622666
if( !seenZ ) goto manifest_syntax_error;
623667
p->type = CFTYPE_ATTACHMENT;
624668
}else{
@@ -625,14 +669,12 @@
625669
if( p->nCChild>0 ) goto manifest_syntax_error;
626670
if( p->rDate<=0.0 ) goto manifest_syntax_error;
627671
if( p->nParent>0 ) goto manifest_syntax_error;
628672
if( p->nField>0 ) goto manifest_syntax_error;
629673
if( p->zTicketUuid ) goto manifest_syntax_error;
630
- if( p->zWiki ) goto manifest_syntax_error;
631674
if( p->zWikiTitle ) goto manifest_syntax_error;
632675
if( p->zTicketUuid ) goto manifest_syntax_error;
633
- if( p->zAttachName ) goto manifest_syntax_error;
634676
p->type = CFTYPE_MANIFEST;
635677
}
636678
md5sum_init();
637679
return 1;
638680
@@ -964,10 +1006,12 @@
9641006
** * Manifest
9651007
** * Control
9661008
** * Wiki Page
9671009
** * Ticket Change
9681010
** * Cluster
1011
+** * Attachment
1012
+** * Event
9691013
**
9701014
** If the input is a control artifact, then make appropriate entries
9711015
** in the auxiliary tables of the database in order to crosslink the
9721016
** artifact.
9731017
**
@@ -1043,11 +1087,14 @@
10431087
if( mid>0 ){
10441088
db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid);
10451089
}
10461090
}
10471091
}
1048
- if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){
1092
+ if( m.type==CFTYPE_CONTROL
1093
+ || m.type==CFTYPE_MANIFEST
1094
+ || m.type==CFTYPE_EVENT
1095
+ ){
10491096
for(i=0; i<m.nTag; i++){
10501097
int tid;
10511098
int type;
10521099
if( m.aTag[i].zUuid ){
10531100
tid = uuid_to_rid(m.aTag[i].zUuid, 1);
@@ -1109,10 +1156,55 @@
11091156
TAG_BGCOLOR, rid,
11101157
TAG_USER, rid,
11111158
TAG_COMMENT, rid
11121159
);
11131160
free(zComment);
1161
+ }
1162
+ if( m.type==CFTYPE_EVENT ){
1163
+ char *zTag = mprintf("event-%s", m.zEventId);
1164
+ int tagid = tag_findid(zTag, 1);
1165
+ int prior, subsequent;
1166
+ int nWiki;
1167
+ char zLength[40];
1168
+ while( isspace(m.zWiki[0]) ) m.zWiki++;
1169
+ nWiki = strlen(m.zWiki);
1170
+ sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
1171
+ tag_insert(zTag, 1, zLength, rid, m.rDate, rid);
1172
+ free(zTag);
1173
+ prior = db_int(0,
1174
+ "SELECT rid FROM tagxref"
1175
+ " WHERE tagid=%d AND mtime<%.17g"
1176
+ " ORDER BY mtime DESC",
1177
+ tagid, m.rDate
1178
+ );
1179
+ if( prior ){
1180
+ content_deltify(prior, rid, 0);
1181
+ db_multi_exec(
1182
+ "DELETE FROM event"
1183
+ " WHERE type='e'"
1184
+ " AND tagid=%d"
1185
+ " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)",
1186
+ tagid, tagid
1187
+ );
1188
+ }
1189
+ subsequent = db_int(0,
1190
+ "SELECT rid FROM tagxref"
1191
+ " WHERE tagid=%d AND mtime>%.17g"
1192
+ " ORDER BY mtime",
1193
+ tagid, m.rDate
1194
+ );
1195
+ if( subsequent ){
1196
+ content_deltify(rid, subsequent, 0);
1197
+ }else{
1198
+ db_multi_exec(
1199
+ "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
1200
+ "VALUES('e',%.17g,%d,%d,%Q,%Q,"
1201
+ " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1202
+ m.rEventDate, rid, tagid, m.zUser, m.zComment,
1203
+ TAG_BGCOLOR, rid
1204
+ );
1205
+ }
11141206
}
11151207
if( m.type==CFTYPE_TICKET ){
11161208
char *zTag;
11171209
11181210
assert( manifest_crosslink_busy==1 );
11191211
--- src/manifest.c
+++ src/manifest.c
@@ -32,10 +32,11 @@
32 #define CFTYPE_CLUSTER 2
33 #define CFTYPE_CONTROL 3
34 #define CFTYPE_WIKI 4
35 #define CFTYPE_TICKET 5
36 #define CFTYPE_ATTACHMENT 6
 
37
38 /*
39 ** A parsed manifest or cluster.
40 */
41 struct Manifest {
@@ -45,10 +46,12 @@
45 double rDate; /* Date and time from D card. 0.0 if no D card. */
46 char *zUser; /* Name of the user from the U card. */
47 char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */
48 char *zWiki; /* Text of the wiki page. W card. */
49 char *zWikiTitle; /* Name of the wiki page. L card. */
 
 
50 char *zTicketUuid; /* UUID for a ticket. K card. */
51 char *zAttachName; /* Filename of an attachment. A card. */
52 char *zAttachSrc; /* UUID of document being attached. A card. */
53 char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */
54 int nFile; /* Number of F cards */
@@ -230,10 +233,35 @@
230 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
231 zDate = blob_terminate(&a1);
232 p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate);
233 break;
234 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
236 /*
237 ** F <filename> <uuid> ?<permissions>? ?<old-name>?
238 **
239 ** Identifies a file in a manifest. Multiple F lines are
@@ -563,15 +591,16 @@
563 }
564 if( !seenHeader ) goto manifest_syntax_error;
565
566 if( p->nFile>0 || p->zRepoCksum!=0 ){
567 if( p->nCChild>0 ) goto manifest_syntax_error;
568 if( p->rDate==0.0 ) goto manifest_syntax_error;
569 if( p->nField>0 ) goto manifest_syntax_error;
570 if( p->zTicketUuid ) goto manifest_syntax_error;
571 if( p->zWiki ) goto manifest_syntax_error;
572 if( p->zWikiTitle ) goto manifest_syntax_error;
 
573 if( p->zTicketUuid ) goto manifest_syntax_error;
574 if( p->zAttachName ) goto manifest_syntax_error;
575 p->type = CFTYPE_MANIFEST;
576 }else if( p->nCChild>0 ){
577 if( p->rDate>0.0 ) goto manifest_syntax_error;
@@ -581,26 +610,41 @@
581 if( p->nParent>0 ) goto manifest_syntax_error;
582 if( p->nField>0 ) goto manifest_syntax_error;
583 if( p->zTicketUuid ) goto manifest_syntax_error;
584 if( p->zWiki ) goto manifest_syntax_error;
585 if( p->zWikiTitle ) goto manifest_syntax_error;
 
586 if( p->zAttachName ) goto manifest_syntax_error;
587 if( !seenZ ) goto manifest_syntax_error;
588 p->type = CFTYPE_CLUSTER;
589 }else if( p->nField>0 ){
590 if( p->rDate==0.0 ) goto manifest_syntax_error;
591 if( p->zWiki ) goto manifest_syntax_error;
592 if( p->zWikiTitle ) goto manifest_syntax_error;
 
593 if( p->nCChild>0 ) goto manifest_syntax_error;
594 if( p->nTag>0 ) goto manifest_syntax_error;
595 if( p->zTicketUuid==0 ) goto manifest_syntax_error;
596 if( p->zUser==0 ) goto manifest_syntax_error;
597 if( p->zAttachName ) goto manifest_syntax_error;
598 if( !seenZ ) goto manifest_syntax_error;
599 p->type = CFTYPE_TICKET;
 
 
 
 
 
 
 
 
 
 
 
 
 
600 }else if( p->zWiki!=0 ){
601 if( p->rDate==0.0 ) goto manifest_syntax_error;
602 if( p->nCChild>0 ) goto manifest_syntax_error;
603 if( p->nTag>0 ) goto manifest_syntax_error;
604 if( p->zTicketUuid!=0 ) goto manifest_syntax_error;
605 if( p->zWikiTitle==0 ) goto manifest_syntax_error;
606 if( p->zAttachName ) goto manifest_syntax_error;
@@ -614,11 +658,11 @@
614 if( p->zAttachName ) goto manifest_syntax_error;
615 if( !seenZ ) goto manifest_syntax_error;
616 p->type = CFTYPE_CONTROL;
617 }else if( p->zAttachName ){
618 if( p->nCChild>0 ) goto manifest_syntax_error;
619 if( p->rDate==0.0 ) goto manifest_syntax_error;
620 if( p->zTicketUuid ) goto manifest_syntax_error;
621 if( p->zWikiTitle ) goto manifest_syntax_error;
622 if( !seenZ ) goto manifest_syntax_error;
623 p->type = CFTYPE_ATTACHMENT;
624 }else{
@@ -625,14 +669,12 @@
625 if( p->nCChild>0 ) goto manifest_syntax_error;
626 if( p->rDate<=0.0 ) goto manifest_syntax_error;
627 if( p->nParent>0 ) goto manifest_syntax_error;
628 if( p->nField>0 ) goto manifest_syntax_error;
629 if( p->zTicketUuid ) goto manifest_syntax_error;
630 if( p->zWiki ) goto manifest_syntax_error;
631 if( p->zWikiTitle ) goto manifest_syntax_error;
632 if( p->zTicketUuid ) goto manifest_syntax_error;
633 if( p->zAttachName ) goto manifest_syntax_error;
634 p->type = CFTYPE_MANIFEST;
635 }
636 md5sum_init();
637 return 1;
638
@@ -964,10 +1006,12 @@
964 ** * Manifest
965 ** * Control
966 ** * Wiki Page
967 ** * Ticket Change
968 ** * Cluster
 
 
969 **
970 ** If the input is a control artifact, then make appropriate entries
971 ** in the auxiliary tables of the database in order to crosslink the
972 ** artifact.
973 **
@@ -1043,11 +1087,14 @@
1043 if( mid>0 ){
1044 db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid);
1045 }
1046 }
1047 }
1048 if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){
 
 
 
1049 for(i=0; i<m.nTag; i++){
1050 int tid;
1051 int type;
1052 if( m.aTag[i].zUuid ){
1053 tid = uuid_to_rid(m.aTag[i].zUuid, 1);
@@ -1109,10 +1156,55 @@
1109 TAG_BGCOLOR, rid,
1110 TAG_USER, rid,
1111 TAG_COMMENT, rid
1112 );
1113 free(zComment);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1114 }
1115 if( m.type==CFTYPE_TICKET ){
1116 char *zTag;
1117
1118 assert( manifest_crosslink_busy==1 );
1119
--- src/manifest.c
+++ src/manifest.c
@@ -32,10 +32,11 @@
32 #define CFTYPE_CLUSTER 2
33 #define CFTYPE_CONTROL 3
34 #define CFTYPE_WIKI 4
35 #define CFTYPE_TICKET 5
36 #define CFTYPE_ATTACHMENT 6
37 #define CFTYPE_EVENT 7
38
39 /*
40 ** A parsed manifest or cluster.
41 */
42 struct Manifest {
@@ -45,10 +46,12 @@
46 double rDate; /* Date and time from D card. 0.0 if no D card. */
47 char *zUser; /* Name of the user from the U card. */
48 char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */
49 char *zWiki; /* Text of the wiki page. W card. */
50 char *zWikiTitle; /* Name of the wiki page. L card. */
51 double rEventDate; /* Date of an event. E card. */
52 char *zEventId; /* UUID for an event. E card. */
53 char *zTicketUuid; /* UUID for a ticket. K card. */
54 char *zAttachName; /* Filename of an attachment. A card. */
55 char *zAttachSrc; /* UUID of document being attached. A card. */
56 char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */
57 int nFile; /* Number of F cards */
@@ -230,10 +233,35 @@
233 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
234 zDate = blob_terminate(&a1);
235 p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate);
236 break;
237 }
238
239 /*
240 ** E <timestamp> <uuid>
241 **
242 ** An "event" card that contains the timestamp of the event in the
243 ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event.
244 ** The event timestamp is distinct from the D timestamp. The D
245 ** timestamp is when the artifact was created whereas the E timestamp
246 ** is when the specific event is said to occur.
247 */
248 case 'E': {
249 char *zEDate;
250 md5sum_step_text(blob_buffer(&line), blob_size(&line));
251 if( p->rEventDate!=0.0 ) goto manifest_syntax_error;
252 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
253 if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
254 if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error;
255 zEDate = blob_terminate(&a1);
256 p->rEventDate = db_double(0.0, "SELECT julianday(%Q)", zEDate);
257 if( p->rEventDate<=0.0 ) goto manifest_syntax_error;
258 if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error;
259 p->zEventId = blob_terminate(&a2);
260 if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error;
261 break;
262 }
263
264 /*
265 ** F <filename> <uuid> ?<permissions>? ?<old-name>?
266 **
267 ** Identifies a file in a manifest. Multiple F lines are
@@ -563,15 +591,16 @@
591 }
592 if( !seenHeader ) goto manifest_syntax_error;
593
594 if( p->nFile>0 || p->zRepoCksum!=0 ){
595 if( p->nCChild>0 ) goto manifest_syntax_error;
596 if( p->rDate<=0.0 ) goto manifest_syntax_error;
597 if( p->nField>0 ) goto manifest_syntax_error;
598 if( p->zTicketUuid ) goto manifest_syntax_error;
599 if( p->zWiki ) goto manifest_syntax_error;
600 if( p->zWikiTitle ) goto manifest_syntax_error;
601 if( p->zEventId ) goto manifest_syntax_error;
602 if( p->zTicketUuid ) goto manifest_syntax_error;
603 if( p->zAttachName ) goto manifest_syntax_error;
604 p->type = CFTYPE_MANIFEST;
605 }else if( p->nCChild>0 ){
606 if( p->rDate>0.0 ) goto manifest_syntax_error;
@@ -581,26 +610,41 @@
610 if( p->nParent>0 ) goto manifest_syntax_error;
611 if( p->nField>0 ) goto manifest_syntax_error;
612 if( p->zTicketUuid ) goto manifest_syntax_error;
613 if( p->zWiki ) goto manifest_syntax_error;
614 if( p->zWikiTitle ) goto manifest_syntax_error;
615 if( p->zEventId ) goto manifest_syntax_error;
616 if( p->zAttachName ) goto manifest_syntax_error;
617 if( !seenZ ) goto manifest_syntax_error;
618 p->type = CFTYPE_CLUSTER;
619 }else if( p->nField>0 ){
620 if( p->rDate<=0.0 ) goto manifest_syntax_error;
621 if( p->zWiki ) goto manifest_syntax_error;
622 if( p->zWikiTitle ) goto manifest_syntax_error;
623 if( p->zEventId ) goto manifest_syntax_error;
624 if( p->nCChild>0 ) goto manifest_syntax_error;
625 if( p->nTag>0 ) goto manifest_syntax_error;
626 if( p->zTicketUuid==0 ) goto manifest_syntax_error;
627 if( p->zUser==0 ) goto manifest_syntax_error;
628 if( p->zAttachName ) goto manifest_syntax_error;
629 if( !seenZ ) goto manifest_syntax_error;
630 p->type = CFTYPE_TICKET;
631 }else if( p->zEventId ){
632 if( p->rDate<=0.0 ) goto manifest_syntax_error;
633 if( p->nCChild>0 ) goto manifest_syntax_error;
634 if( p->zTicketUuid!=0 ) goto manifest_syntax_error;
635 if( p->zWikiTitle!=0 ) goto manifest_syntax_error;
636 if( p->zWiki==0 ) goto manifest_syntax_error;
637 if( p->zAttachName ) goto manifest_syntax_error;
638 for(i=0; i<p->nTag; i++){
639 if( p->aTag[i].zName[0]!='+' ) goto manifest_syntax_error;
640 if( p->aTag[i].zUuid!=0 ) goto manifest_syntax_error;
641 }
642 if( !seenZ ) goto manifest_syntax_error;
643 p->type = CFTYPE_EVENT;
644 }else if( p->zWiki!=0 ){
645 if( p->rDate<=0.0 ) goto manifest_syntax_error;
646 if( p->nCChild>0 ) goto manifest_syntax_error;
647 if( p->nTag>0 ) goto manifest_syntax_error;
648 if( p->zTicketUuid!=0 ) goto manifest_syntax_error;
649 if( p->zWikiTitle==0 ) goto manifest_syntax_error;
650 if( p->zAttachName ) goto manifest_syntax_error;
@@ -614,11 +658,11 @@
658 if( p->zAttachName ) goto manifest_syntax_error;
659 if( !seenZ ) goto manifest_syntax_error;
660 p->type = CFTYPE_CONTROL;
661 }else if( p->zAttachName ){
662 if( p->nCChild>0 ) goto manifest_syntax_error;
663 if( p->rDate<=0.0 ) goto manifest_syntax_error;
664 if( p->zTicketUuid ) goto manifest_syntax_error;
665 if( p->zWikiTitle ) goto manifest_syntax_error;
666 if( !seenZ ) goto manifest_syntax_error;
667 p->type = CFTYPE_ATTACHMENT;
668 }else{
@@ -625,14 +669,12 @@
669 if( p->nCChild>0 ) goto manifest_syntax_error;
670 if( p->rDate<=0.0 ) goto manifest_syntax_error;
671 if( p->nParent>0 ) goto manifest_syntax_error;
672 if( p->nField>0 ) goto manifest_syntax_error;
673 if( p->zTicketUuid ) goto manifest_syntax_error;
 
674 if( p->zWikiTitle ) goto manifest_syntax_error;
675 if( p->zTicketUuid ) goto manifest_syntax_error;
 
676 p->type = CFTYPE_MANIFEST;
677 }
678 md5sum_init();
679 return 1;
680
@@ -964,10 +1006,12 @@
1006 ** * Manifest
1007 ** * Control
1008 ** * Wiki Page
1009 ** * Ticket Change
1010 ** * Cluster
1011 ** * Attachment
1012 ** * Event
1013 **
1014 ** If the input is a control artifact, then make appropriate entries
1015 ** in the auxiliary tables of the database in order to crosslink the
1016 ** artifact.
1017 **
@@ -1043,11 +1087,14 @@
1087 if( mid>0 ){
1088 db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid);
1089 }
1090 }
1091 }
1092 if( m.type==CFTYPE_CONTROL
1093 || m.type==CFTYPE_MANIFEST
1094 || m.type==CFTYPE_EVENT
1095 ){
1096 for(i=0; i<m.nTag; i++){
1097 int tid;
1098 int type;
1099 if( m.aTag[i].zUuid ){
1100 tid = uuid_to_rid(m.aTag[i].zUuid, 1);
@@ -1109,10 +1156,55 @@
1156 TAG_BGCOLOR, rid,
1157 TAG_USER, rid,
1158 TAG_COMMENT, rid
1159 );
1160 free(zComment);
1161 }
1162 if( m.type==CFTYPE_EVENT ){
1163 char *zTag = mprintf("event-%s", m.zEventId);
1164 int tagid = tag_findid(zTag, 1);
1165 int prior, subsequent;
1166 int nWiki;
1167 char zLength[40];
1168 while( isspace(m.zWiki[0]) ) m.zWiki++;
1169 nWiki = strlen(m.zWiki);
1170 sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
1171 tag_insert(zTag, 1, zLength, rid, m.rDate, rid);
1172 free(zTag);
1173 prior = db_int(0,
1174 "SELECT rid FROM tagxref"
1175 " WHERE tagid=%d AND mtime<%.17g"
1176 " ORDER BY mtime DESC",
1177 tagid, m.rDate
1178 );
1179 if( prior ){
1180 content_deltify(prior, rid, 0);
1181 db_multi_exec(
1182 "DELETE FROM event"
1183 " WHERE type='e'"
1184 " AND tagid=%d"
1185 " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)",
1186 tagid, tagid
1187 );
1188 }
1189 subsequent = db_int(0,
1190 "SELECT rid FROM tagxref"
1191 " WHERE tagid=%d AND mtime>%.17g"
1192 " ORDER BY mtime",
1193 tagid, m.rDate
1194 );
1195 if( subsequent ){
1196 content_deltify(rid, subsequent, 0);
1197 }else{
1198 db_multi_exec(
1199 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
1200 "VALUES('e',%.17g,%d,%d,%Q,%Q,"
1201 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1202 m.rEventDate, rid, tagid, m.zUser, m.zComment,
1203 TAG_BGCOLOR, rid
1204 );
1205 }
1206 }
1207 if( m.type==CFTYPE_TICKET ){
1208 char *zTag;
1209
1210 assert( manifest_crosslink_busy==1 );
1211
+3 -3
--- src/printf.c
+++ src/printf.c
@@ -44,13 +44,13 @@
4444
#define etHTMLIZE 16 /* Make text safe for HTML */
4545
#define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */
4646
#define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */
4747
#define etFOSSILIZE 19 /* The fossil header encoding format. */
4848
#define etPATH 20 /* Path type */
49
-#define etWIKISTR 21 /* Wiki text rendered from a char* */
50
-#define etWIKIBLOB 22 /* Wiki text rendered from a Blob* */
51
-#define etSTRINGID 23 /* String with length limit for a UUID prefix */
49
+#define etWIKISTR 21 /* Wiki text rendered from a char*: %w */
50
+#define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */
51
+#define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
5252
5353
5454
/*
5555
** An "etByte" is an 8-bit unsigned value.
5656
*/
5757
--- src/printf.c
+++ src/printf.c
@@ -44,13 +44,13 @@
44 #define etHTMLIZE 16 /* Make text safe for HTML */
45 #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */
46 #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */
47 #define etFOSSILIZE 19 /* The fossil header encoding format. */
48 #define etPATH 20 /* Path type */
49 #define etWIKISTR 21 /* Wiki text rendered from a char* */
50 #define etWIKIBLOB 22 /* Wiki text rendered from a Blob* */
51 #define etSTRINGID 23 /* String with length limit for a UUID prefix */
52
53
54 /*
55 ** An "etByte" is an 8-bit unsigned value.
56 */
57
--- src/printf.c
+++ src/printf.c
@@ -44,13 +44,13 @@
44 #define etHTMLIZE 16 /* Make text safe for HTML */
45 #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */
46 #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */
47 #define etFOSSILIZE 19 /* The fossil header encoding format. */
48 #define etPATH 20 /* Path type */
49 #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */
50 #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */
51 #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
52
53
54 /*
55 ** An "etByte" is an 8-bit unsigned value.
56 */
57
+72 -66
--- src/rebuild.c
+++ src/rebuild.c
@@ -121,76 +121,82 @@
121121
Bag children;
122122
Blob copy;
123123
Blob *pUse;
124124
int nChild, i, cid;
125125
126
- /* Fix up the "blob.size" field if needed. */
127
- if( size!=blob_size(pBase) ){
128
- db_multi_exec(
129
- "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid
130
- );
131
- }
132
-
133
- /* Find all children of artifact rid */
134
- db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid");
135
- db_bind_int(&q1, ":rid", rid);
136
- bag_init(&children);
137
- while( db_step(&q1)==SQLITE_ROW ){
138
- int cid = db_column_int(&q1, 0);
139
- if( !bag_find(&bagDone, cid) ){
140
- bag_insert(&children, cid);
141
- }
142
- }
143
- nChild = bag_count(&children);
144
- db_reset(&q1);
145
-
146
- /* Crosslink the artifact */
147
- if( nChild==0 ){
148
- pUse = pBase;
149
- }else{
150
- blob_copy(&copy, pBase);
151
- pUse = &copy;
152
- }
153
- if( zFNameFormat==0 ){
154
- /* We are doing "fossil rebuild" */
155
- manifest_crosslink(rid, pUse);
156
- }else{
157
- /* We are doing "fossil deconstruct" */
158
- char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
159
- char *zFile = mprintf(zFNameFormat, zUuid, zUuid+prefixLength);
160
- blob_write_to_file(pUse,zFile);
161
- free(zFile);
162
- free(zUuid);
163
- }
164
- blob_reset(pUse);
165
- rebuild_step_done(rid);
166
-
167
- /* Call all children recursively */
168
- for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){
169
- Stmt q2;
170
- int sz;
171
- if( nChild==i ){
172
- pUse = pBase;
173
- }else{
174
- blob_copy(&copy, pBase);
175
- pUse = &copy;
176
- }
177
- db_prepare(&q2, "SELECT content, size FROM blob WHERE rid=%d", cid);
178
- if( db_step(&q2)==SQLITE_ROW && (sz = db_column_int(&q2,1))>=0 ){
179
- Blob delta;
180
- db_ephemeral_blob(&q2, 0, &delta);
181
- blob_uncompress(&delta, &delta);
182
- blob_delta_apply(pUse, &delta, pUse);
183
- blob_reset(&delta);
184
- db_finalize(&q2);
185
- rebuild_step(cid, sz, pUse);
186
- }else{
187
- db_finalize(&q2);
188
- blob_reset(pUse);
189
- }
190
- }
191
- bag_clear(&children);
126
+ while( rid>0 ){
127
+
128
+ /* Fix up the "blob.size" field if needed. */
129
+ if( size!=blob_size(pBase) ){
130
+ db_multi_exec(
131
+ "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid
132
+ );
133
+ }
134
+
135
+ /* Find all children of artifact rid */
136
+ db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid");
137
+ db_bind_int(&q1, ":rid", rid);
138
+ bag_init(&children);
139
+ while( db_step(&q1)==SQLITE_ROW ){
140
+ int cid = db_column_int(&q1, 0);
141
+ if( !bag_find(&bagDone, cid) ){
142
+ bag_insert(&children, cid);
143
+ }
144
+ }
145
+ nChild = bag_count(&children);
146
+ db_reset(&q1);
147
+
148
+ /* Crosslink the artifact */
149
+ if( nChild==0 ){
150
+ pUse = pBase;
151
+ }else{
152
+ blob_copy(&copy, pBase);
153
+ pUse = &copy;
154
+ }
155
+ if( zFNameFormat==0 ){
156
+ /* We are doing "fossil rebuild" */
157
+ manifest_crosslink(rid, pUse);
158
+ }else{
159
+ /* We are doing "fossil deconstruct" */
160
+ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
161
+ char *zFile = mprintf(zFNameFormat, zUuid, zUuid+prefixLength);
162
+ blob_write_to_file(pUse,zFile);
163
+ free(zFile);
164
+ free(zUuid);
165
+ }
166
+ blob_reset(pUse);
167
+ rebuild_step_done(rid);
168
+
169
+ /* Call all children recursively */
170
+ rid = 0;
171
+ for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){
172
+ Stmt q2;
173
+ int sz;
174
+ db_prepare(&q2, "SELECT content, size FROM blob WHERE rid=%d", cid);
175
+ if( db_step(&q2)==SQLITE_ROW && (sz = db_column_int(&q2,1))>=0 ){
176
+ Blob delta, next;
177
+ db_ephemeral_blob(&q2, 0, &delta);
178
+ blob_uncompress(&delta, &delta);
179
+ blob_delta_apply(pBase, &delta, &next);
180
+ blob_reset(&delta);
181
+ db_finalize(&q2);
182
+ if( i<nChild ){
183
+ rebuild_step(cid, sz, &next);
184
+ }else{
185
+ /* Tail recursion */
186
+ rid = cid;
187
+ size = sz;
188
+ blob_reset(pBase);
189
+ *pBase = next;
190
+ }
191
+ }else{
192
+ db_finalize(&q2);
193
+ blob_reset(pBase);
194
+ }
195
+ }
196
+ bag_clear(&children);
197
+ }
192198
}
193199
194200
/*
195201
** Check to see if the "sym-trunk" tag exists. If not, create it
196202
** and attach it to the very first check-in.
197203
--- src/rebuild.c
+++ src/rebuild.c
@@ -121,76 +121,82 @@
121 Bag children;
122 Blob copy;
123 Blob *pUse;
124 int nChild, i, cid;
125
126 /* Fix up the "blob.size" field if needed. */
127 if( size!=blob_size(pBase) ){
128 db_multi_exec(
129 "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid
130 );
131 }
132
133 /* Find all children of artifact rid */
134 db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid");
135 db_bind_int(&q1, ":rid", rid);
136 bag_init(&children);
137 while( db_step(&q1)==SQLITE_ROW ){
138 int cid = db_column_int(&q1, 0);
139 if( !bag_find(&bagDone, cid) ){
140 bag_insert(&children, cid);
141 }
142 }
143 nChild = bag_count(&children);
144 db_reset(&q1);
145
146 /* Crosslink the artifact */
147 if( nChild==0 ){
148 pUse = pBase;
149 }else{
150 blob_copy(&copy, pBase);
151 pUse = &copy;
152 }
153 if( zFNameFormat==0 ){
154 /* We are doing "fossil rebuild" */
155 manifest_crosslink(rid, pUse);
156 }else{
157 /* We are doing "fossil deconstruct" */
158 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
159 char *zFile = mprintf(zFNameFormat, zUuid, zUuid+prefixLength);
160 blob_write_to_file(pUse,zFile);
161 free(zFile);
162 free(zUuid);
163 }
164 blob_reset(pUse);
165 rebuild_step_done(rid);
166
167 /* Call all children recursively */
168 for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){
169 Stmt q2;
170 int sz;
171 if( nChild==i ){
172 pUse = pBase;
173 }else{
174 blob_copy(&copy, pBase);
175 pUse = &copy;
176 }
177 db_prepare(&q2, "SELECT content, size FROM blob WHERE rid=%d", cid);
178 if( db_step(&q2)==SQLITE_ROW && (sz = db_column_int(&q2,1))>=0 ){
179 Blob delta;
180 db_ephemeral_blob(&q2, 0, &delta);
181 blob_uncompress(&delta, &delta);
182 blob_delta_apply(pUse, &delta, pUse);
183 blob_reset(&delta);
184 db_finalize(&q2);
185 rebuild_step(cid, sz, pUse);
186 }else{
187 db_finalize(&q2);
188 blob_reset(pUse);
189 }
190 }
191 bag_clear(&children);
 
 
 
 
 
 
192 }
193
194 /*
195 ** Check to see if the "sym-trunk" tag exists. If not, create it
196 ** and attach it to the very first check-in.
197
--- src/rebuild.c
+++ src/rebuild.c
@@ -121,76 +121,82 @@
121 Bag children;
122 Blob copy;
123 Blob *pUse;
124 int nChild, i, cid;
125
126 while( rid>0 ){
127
128 /* Fix up the "blob.size" field if needed. */
129 if( size!=blob_size(pBase) ){
130 db_multi_exec(
131 "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid
132 );
133 }
134
135 /* Find all children of artifact rid */
136 db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid");
137 db_bind_int(&q1, ":rid", rid);
138 bag_init(&children);
139 while( db_step(&q1)==SQLITE_ROW ){
140 int cid = db_column_int(&q1, 0);
141 if( !bag_find(&bagDone, cid) ){
142 bag_insert(&children, cid);
143 }
144 }
145 nChild = bag_count(&children);
146 db_reset(&q1);
147
148 /* Crosslink the artifact */
149 if( nChild==0 ){
150 pUse = pBase;
151 }else{
152 blob_copy(&copy, pBase);
153 pUse = &copy;
154 }
155 if( zFNameFormat==0 ){
156 /* We are doing "fossil rebuild" */
157 manifest_crosslink(rid, pUse);
158 }else{
159 /* We are doing "fossil deconstruct" */
160 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
161 char *zFile = mprintf(zFNameFormat, zUuid, zUuid+prefixLength);
162 blob_write_to_file(pUse,zFile);
163 free(zFile);
164 free(zUuid);
165 }
166 blob_reset(pUse);
167 rebuild_step_done(rid);
168
169 /* Call all children recursively */
170 rid = 0;
171 for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){
172 Stmt q2;
173 int sz;
174 db_prepare(&q2, "SELECT content, size FROM blob WHERE rid=%d", cid);
175 if( db_step(&q2)==SQLITE_ROW && (sz = db_column_int(&q2,1))>=0 ){
176 Blob delta, next;
177 db_ephemeral_blob(&q2, 0, &delta);
178 blob_uncompress(&delta, &delta);
179 blob_delta_apply(pBase, &delta, &next);
180 blob_reset(&delta);
181 db_finalize(&q2);
182 if( i<nChild ){
183 rebuild_step(cid, sz, &next);
184 }else{
185 /* Tail recursion */
186 rid = cid;
187 size = sz;
188 blob_reset(pBase);
189 *pBase = next;
190 }
191 }else{
192 db_finalize(&q2);
193 blob_reset(pBase);
194 }
195 }
196 bag_clear(&children);
197 }
198 }
199
200 /*
201 ** Check to see if the "sym-trunk" tag exists. If not, create it
202 ** and attach it to the very first check-in.
203
+223 -268
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -650,11 +650,11 @@
650650
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651651
** [sqlite_version()] and [sqlite_source_id()].
652652
*/
653653
#define SQLITE_VERSION "3.7.3"
654654
#define SQLITE_VERSION_NUMBER 3007003
655
-#define SQLITE_SOURCE_ID "2010-09-29 23:09:23 1ef0dc9328f47506cb2dcd142150e96cb4755216"
655
+#define SQLITE_SOURCE_ID "2010-10-04 23:55:51 ece641eb8951c6314cedbdb3243f91cb199c3239"
656656
657657
/*
658658
** CAPI3REF: Run-Time Library Version Numbers
659659
** KEYWORDS: sqlite3_version, sqlite3_sourceid
660660
**
@@ -10570,11 +10570,10 @@
1057010570
1057110571
/*
1057210572
** Internal function prototypes
1057310573
*/
1057410574
SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *);
10575
-SQLITE_PRIVATE int sqlite3IsNumber(const char*, int*, u8);
1057610575
SQLITE_PRIVATE int sqlite3Strlen30(const char*);
1057710576
#define sqlite3StrNICmp sqlite3_strnicmp
1057810577
1057910578
SQLITE_PRIVATE int sqlite3MallocInit(void);
1058010579
SQLITE_PRIVATE void sqlite3MallocEnd(void);
@@ -10890,13 +10889,12 @@
1089010889
SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
1089110890
SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
1089210891
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
1089310892
SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
1089410893
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
10895
-SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*);
10894
+SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
1089610895
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
10897
-SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *, int);
1089810896
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
1089910897
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
1090010898
SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**);
1090110899
1090210900
/*
@@ -10938,11 +10936,11 @@
1093810936
SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *);
1093910937
SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *);
1094010938
SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
1094110939
SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
1094210940
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
10943
-SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*);
10941
+SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
1094410942
SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
1094510943
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
1094610944
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
1094710945
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
1094810946
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
@@ -12637,16 +12635,10 @@
1263712635
end_getDigits:
1263812636
va_end(ap);
1263912637
return cnt;
1264012638
}
1264112639
12642
-/*
12643
-** Read text from z[] and convert into a floating point number. Return
12644
-** the number of digits converted.
12645
-*/
12646
-#define getValue sqlite3AtoF
12647
-
1264812640
/*
1264912641
** Parse a timezone extension on the end of a date-time.
1265012642
** The extension is of the form:
1265112643
**
1265212644
** (+/-)HH:MM
@@ -12844,21 +12836,19 @@
1284412836
static int parseDateOrTime(
1284512837
sqlite3_context *context,
1284612838
const char *zDate,
1284712839
DateTime *p
1284812840
){
12849
- int isRealNum; /* Return from sqlite3IsNumber(). Not used */
12841
+ double r;
1285012842
if( parseYyyyMmDd(zDate,p)==0 ){
1285112843
return 0;
1285212844
}else if( parseHhMmSs(zDate, p)==0 ){
1285312845
return 0;
1285412846
}else if( sqlite3StrICmp(zDate,"now")==0){
1285512847
setDateTimeToCurrent(context, p);
1285612848
return 0;
12857
- }else if( sqlite3IsNumber(zDate, &isRealNum, SQLITE_UTF8) ){
12858
- double r;
12859
- getValue(zDate, &r);
12849
+ }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
1286012850
p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
1286112851
p->validJD = 1;
1286212852
return 0;
1286312853
}
1286412854
return 1;
@@ -13075,12 +13065,13 @@
1307513065
**
1307613066
** Move the date to the same time on the next occurrence of
1307713067
** weekday N where 0==Sunday, 1==Monday, and so forth. If the
1307813068
** date is already on the appropriate weekday, this is a no-op.
1307913069
*/
13080
- if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
13081
- && (n=(int)r)==r && n>=0 && r<7 ){
13070
+ if( strncmp(z, "weekday ", 8)==0
13071
+ && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
13072
+ && (n=(int)r)==r && n>=0 && r<7 ){
1308213073
sqlite3_int64 Z;
1308313074
computeYMD_HMS(p);
1308413075
p->validTZ = 0;
1308513076
p->validJD = 0;
1308613077
computeJD(p);
@@ -13131,12 +13122,15 @@
1313113122
case '6':
1313213123
case '7':
1313313124
case '8':
1313413125
case '9': {
1313513126
double rRounder;
13136
- n = getValue(z, &r);
13137
- assert( n>=1 );
13127
+ for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
13128
+ if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
13129
+ rc = 1;
13130
+ break;
13131
+ }
1313813132
if( z[n]==':' ){
1313913133
/* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
1314013134
** specified number of hours, minutes, seconds, and fractional seconds
1314113135
** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
1314213136
** omitted.
@@ -17502,11 +17496,11 @@
1750217496
sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n);
1750317497
}else{
1750417498
sqlite3MemoryAlarm(0, 0, 0);
1750517499
}
1750617500
excess = sqlite3_memory_used() - n;
17507
- if( excess>0 ) sqlite3_release_memory(excess & 0x7fffffff);
17501
+ if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
1750817502
return priorLimit;
1750917503
}
1751017504
SQLITE_API void sqlite3_soft_heap_limit(int n){
1751117505
if( n<0 ) n = 0;
1751217506
sqlite3_soft_heap_limit64(n);
@@ -20096,125 +20090,115 @@
2009620090
while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
2009720091
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
2009820092
}
2009920093
2010020094
/*
20101
-** Return TRUE if z is a pure numeric string. Return FALSE and leave
20102
-** *realnum unchanged if the string contains any character which is not
20103
-** part of a number.
20104
-**
20105
-** If the string is pure numeric, set *realnum to TRUE if the string
20106
-** contains the '.' character or an "E+000" style exponentiation suffix.
20107
-** Otherwise set *realnum to FALSE. Note that just becaue *realnum is
20108
-** false does not mean that the number can be successfully converted into
20109
-** an integer - it might be too big.
20110
-**
20111
-** An empty string is considered non-numeric.
20112
-*/
20113
-SQLITE_PRIVATE int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
20095
+** The string z[] is an text representation of a real number.
20096
+** Convert this string to a double and write it into *pResult.
20097
+**
20098
+** The string z[] is length bytes in length (bytes, not characters) and
20099
+** uses the encoding enc. The string is not necessarily zero-terminated.
20100
+**
20101
+** Return TRUE if the result is a valid real number (or integer) and FALSE
20102
+** if the string is empty or contains extraneous text. Valid numbers
20103
+** are in one of these formats:
20104
+**
20105
+** [+-]digits[E[+-]digits]
20106
+** [+-]digits.[digits][E[+-]digits]
20107
+** [+-].digits[E[+-]digits]
20108
+**
20109
+** Leading and trailing whitespace is ignored for the purpose of determining
20110
+** validity.
20111
+**
20112
+** If some prefix of the input string is a valid number, this routine
20113
+** returns FALSE but it still converts the prefix and writes the result
20114
+** into *pResult.
20115
+*/
20116
+SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
20117
+#ifndef SQLITE_OMIT_FLOATING_POINT
2011420118
int incr = (enc==SQLITE_UTF8?1:2);
20115
- if( enc==SQLITE_UTF16BE ) z++;
20116
- if( *z=='-' || *z=='+' ) z += incr;
20117
- if( !sqlite3Isdigit(*z) ){
20118
- return 0;
20119
- }
20120
- z += incr;
20121
- *realnum = 0;
20122
- while( sqlite3Isdigit(*z) ){ z += incr; }
20123
-#ifndef SQLITE_OMIT_FLOATING_POINT
20124
- if( *z=='.' ){
20125
- z += incr;
20126
- if( !sqlite3Isdigit(*z) ) return 0;
20127
- while( sqlite3Isdigit(*z) ){ z += incr; }
20128
- *realnum = 1;
20129
- }
20130
- if( *z=='e' || *z=='E' ){
20131
- z += incr;
20132
- if( *z=='+' || *z=='-' ) z += incr;
20133
- if( !sqlite3Isdigit(*z) ) return 0;
20134
- while( sqlite3Isdigit(*z) ){ z += incr; }
20135
- *realnum = 1;
20136
- }
20137
-#endif
20138
- return *z==0;
20139
-}
20140
-
20141
-/*
20142
-** The string z[] is an ASCII representation of a real number.
20143
-** Convert this string to a double.
20144
-**
20145
-** This routine assumes that z[] really is a valid number. If it
20146
-** is not, the result is undefined.
20147
-**
20148
-** This routine is used instead of the library atof() function because
20149
-** the library atof() might want to use "," as the decimal point instead
20150
-** of "." depending on how locale is set. But that would cause problems
20151
-** for SQL. So this routine always uses "." regardless of locale.
20152
-*/
20153
-SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){
20154
-#ifndef SQLITE_OMIT_FLOATING_POINT
20155
- const char *zBegin = z;
20119
+ const char *zEnd = z + length;
2015620120
/* sign * significand * (10 ^ (esign * exponent)) */
20157
- int sign = 1; /* sign of significand */
20158
- i64 s = 0; /* significand */
20159
- int d = 0; /* adjust exponent for shifting decimal point */
20160
- int esign = 1; /* sign of exponent */
20161
- int e = 0; /* exponent */
20121
+ int sign = 1; /* sign of significand */
20122
+ i64 s = 0; /* significand */
20123
+ int d = 0; /* adjust exponent for shifting decimal point */
20124
+ int esign = 1; /* sign of exponent */
20125
+ int e = 0; /* exponent */
20126
+ int eValid = 1; /* True exponent is either not used or is well-formed */
2016220127
double result;
2016320128
int nDigits = 0;
2016420129
20130
+ *pResult = 0.0; /* Default return value, in case of an error */
20131
+
20132
+ if( enc==SQLITE_UTF16BE ) z++;
20133
+
2016520134
/* skip leading spaces */
20166
- while( sqlite3Isspace(*z) ) z++;
20135
+ while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
20136
+ if( z>=zEnd ) return 0;
20137
+
2016720138
/* get sign of significand */
2016820139
if( *z=='-' ){
2016920140
sign = -1;
20170
- z++;
20141
+ z+=incr;
2017120142
}else if( *z=='+' ){
20172
- z++;
20143
+ z+=incr;
2017320144
}
20145
+
2017420146
/* skip leading zeroes */
20175
- while( z[0]=='0' ) z++, nDigits++;
20147
+ while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
2017620148
2017720149
/* copy max significant digits to significand */
20178
- while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
20150
+ while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
2017920151
s = s*10 + (*z - '0');
20180
- z++, nDigits++;
20152
+ z+=incr, nDigits++;
2018120153
}
20154
+
2018220155
/* skip non-significant significand digits
2018320156
** (increase exponent by d to shift decimal left) */
20184
- while( sqlite3Isdigit(*z) ) z++, nDigits++, d++;
20157
+ while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
20158
+ if( z>=zEnd ) goto do_atof_calc;
2018520159
2018620160
/* if decimal point is present */
2018720161
if( *z=='.' ){
20188
- z++;
20162
+ z+=incr;
2018920163
/* copy digits from after decimal to significand
2019020164
** (decrease exponent by d to shift decimal right) */
20191
- while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
20165
+ while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
2019220166
s = s*10 + (*z - '0');
20193
- z++, nDigits++, d--;
20167
+ z+=incr, nDigits++, d--;
2019420168
}
2019520169
/* skip non-significant digits */
20196
- while( sqlite3Isdigit(*z) ) z++, nDigits++;
20170
+ while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
2019720171
}
20172
+ if( z>=zEnd ) goto do_atof_calc;
2019820173
2019920174
/* if exponent is present */
2020020175
if( *z=='e' || *z=='E' ){
20201
- z++;
20176
+ z+=incr;
20177
+ eValid = 0;
20178
+ if( z>=zEnd ) goto do_atof_calc;
2020220179
/* get sign of exponent */
2020320180
if( *z=='-' ){
2020420181
esign = -1;
20205
- z++;
20182
+ z+=incr;
2020620183
}else if( *z=='+' ){
20207
- z++;
20184
+ z+=incr;
2020820185
}
2020920186
/* copy digits to exponent */
20210
- while( sqlite3Isdigit(*z) ){
20187
+ while( z<zEnd && sqlite3Isdigit(*z) ){
2021120188
e = e*10 + (*z - '0');
20212
- z++;
20189
+ z+=incr;
20190
+ eValid = 1;
2021320191
}
2021420192
}
2021520193
20194
+ /* skip trailing spaces */
20195
+ if( nDigits && eValid ){
20196
+ while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
20197
+ }
20198
+
20199
+do_atof_calc:
2021620200
/* adjust exponent by d, and update sign */
2021720201
e = (e*esign) + d;
2021820202
if( e<0 ) {
2021920203
esign = -1;
2022020204
e *= -1;
@@ -20269,132 +20253,104 @@
2026920253
}
2027020254
2027120255
/* store the result */
2027220256
*pResult = result;
2027320257
20274
- /* return number of characters used */
20275
- return (int)(z - zBegin);
20258
+ /* return true if number and no extra non-whitespace chracters after */
20259
+ return z>=zEnd && nDigits>0 && eValid;
2027620260
#else
20277
- return sqlite3Atoi64(z, pResult);
20261
+ return !sqlite3Atoi64(z, pResult, length, enc);
2027820262
#endif /* SQLITE_OMIT_FLOATING_POINT */
2027920263
}
2028020264
2028120265
/*
2028220266
** Compare the 19-character string zNum against the text representation
2028320267
** value 2^63: 9223372036854775808. Return negative, zero, or positive
2028420268
** if zNum is less than, equal to, or greater than the string.
20269
+** Note that zNum must contain exactly 19 characters.
2028520270
**
2028620271
** Unlike memcmp() this routine is guaranteed to return the difference
2028720272
** in the values of the last digit if the only difference is in the
2028820273
** last digit. So, for example,
2028920274
**
20290
-** compare2pow63("9223372036854775800")
20275
+** compare2pow63("9223372036854775800", 1)
2029120276
**
2029220277
** will return -8.
2029320278
*/
20294
-static int compare2pow63(const char *zNum){
20295
- int c;
20296
- c = memcmp(zNum,"922337203685477580",18)*10;
20279
+static int compare2pow63(const char *zNum, int incr){
20280
+ int c = 0;
20281
+ int i;
20282
+ /* 012345678901234567 */
20283
+ const char *pow63 = "922337203685477580";
20284
+ for(i=0; c==0 && i<18; i++){
20285
+ c = (zNum[i*incr]-pow63[i])*10;
20286
+ }
2029720287
if( c==0 ){
20298
- c = zNum[18] - '8';
20288
+ c = zNum[18*incr] - '8';
2029920289
testcase( c==(-1) );
2030020290
testcase( c==0 );
2030120291
testcase( c==(+1) );
2030220292
}
2030320293
return c;
2030420294
}
2030520295
2030620296
2030720297
/*
20308
-** Return TRUE if zNum is a 64-bit signed integer and write
20309
-** the value of the integer into *pNum. If zNum is not an integer
20310
-** or is an integer that is too large to be expressed with 64 bits,
20311
-** then return false.
20298
+** Convert zNum to a 64-bit signed integer and write
20299
+** the value of the integer into *pNum.
20300
+** If zNum is exactly 9223372036854665808, return 2.
20301
+** This is a special case as the context will determine
20302
+** if it is too big (used as a negative).
20303
+** If zNum is not an integer or is an integer that
20304
+** is too large to be expressed with 64 bits,
20305
+** then return 1. Otherwise return 0.
2031220306
**
20313
-** When this routine was originally written it dealt with only
20314
-** 32-bit numbers. At that time, it was much faster than the
20315
-** atoi() library routine in RedHat 7.2.
20307
+** length is the number of bytes in the string (bytes, not characters).
20308
+** The string is not necessarily zero-terminated. The encoding is
20309
+** given by enc.
2031620310
*/
20317
-SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum){
20311
+SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
20312
+ int incr = (enc==SQLITE_UTF8?1:2);
2031820313
i64 v = 0;
20319
- int neg;
20320
- int i, c;
20314
+ int neg = 0; /* assume positive */
20315
+ int i;
20316
+ int c = 0;
2032120317
const char *zStart;
20322
- while( sqlite3Isspace(*zNum) ) zNum++;
20318
+ const char *zEnd = zNum + length;
20319
+ if( enc==SQLITE_UTF16BE ) zNum++;
20320
+ while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
20321
+ if( zNum>=zEnd ) goto do_atoi_calc;
2032320322
if( *zNum=='-' ){
2032420323
neg = 1;
20325
- zNum++;
20324
+ zNum+=incr;
2032620325
}else if( *zNum=='+' ){
20327
- neg = 0;
20328
- zNum++;
20329
- }else{
20330
- neg = 0;
20326
+ zNum+=incr;
2033120327
}
20328
+do_atoi_calc:
2033220329
zStart = zNum;
20333
- while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */
20334
- for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
20330
+ while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
20331
+ for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
2033520332
v = v*10 + c - '0';
2033620333
}
2033720334
*pNum = neg ? -v : v;
2033820335
testcase( i==18 );
2033920336
testcase( i==19 );
2034020337
testcase( i==20 );
20341
- if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
20338
+ if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){
2034220339
/* zNum is empty or contains non-numeric text or is longer
20343
- ** than 19 digits (thus guaranting that it is too large) */
20344
- return 0;
20345
- }else if( i<19 ){
20340
+ ** than 19 digits (thus guaranteeing that it is too large) */
20341
+ return 1;
20342
+ }else if( i<19*incr ){
2034620343
/* Less than 19 digits, so we know that it fits in 64 bits */
20347
- return 1;
20344
+ return 0;
2034820345
}else{
2034920346
/* 19-digit numbers must be no larger than 9223372036854775807 if positive
2035020347
** or 9223372036854775808 if negative. Note that 9223372036854665808
20351
- ** is 2^63. */
20352
- return compare2pow63(zNum)<neg;
20353
- }
20354
-}
20355
-
20356
-/*
20357
-** The string zNum represents an unsigned integer. The zNum string
20358
-** consists of one or more digit characters and is terminated by
20359
-** a zero character. Any stray characters in zNum result in undefined
20360
-** behavior.
20361
-**
20362
-** If the unsigned integer that zNum represents will fit in a
20363
-** 64-bit signed integer, return TRUE. Otherwise return FALSE.
20364
-**
20365
-** If the negFlag parameter is true, that means that zNum really represents
20366
-** a negative number. (The leading "-" is omitted from zNum.) This
20367
-** parameter is needed to determine a boundary case. A string
20368
-** of "9223373036854775808" returns false if negFlag is false or true
20369
-** if negFlag is true.
20370
-**
20371
-** Leading zeros are ignored.
20372
-*/
20373
-SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *zNum, int negFlag){
20374
- int i;
20375
- int neg = 0;
20376
-
20377
- assert( zNum[0]>='0' && zNum[0]<='9' ); /* zNum is an unsigned number */
20378
-
20379
- if( negFlag ) neg = 1-neg;
20380
- while( *zNum=='0' ){
20381
- zNum++; /* Skip leading zeros. Ticket #2454 */
20382
- }
20383
- for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
20384
- testcase( i==18 );
20385
- testcase( i==19 );
20386
- testcase( i==20 );
20387
- if( i<19 ){
20388
- /* Guaranteed to fit if less than 19 digits */
20389
- return 1;
20390
- }else if( i>19 ){
20391
- /* Guaranteed to be too big if greater than 19 digits */
20392
- return 0;
20393
- }else{
20394
- /* Compare against 2^63. */
20395
- return compare2pow63(zNum)<neg;
20348
+ ** is 2^63. Return 1 if to large */
20349
+ c=compare2pow63(zNum, incr);
20350
+ if( c==0 && neg==0 ) return 2; /* too big, exactly 9223372036854665808 */
20351
+ return c<neg ? 0 : 1;
2039620352
}
2039720353
}
2039820354
2039920355
/*
2040020356
** If zNum represents an integer that will fit in 32-bits, then set
@@ -54149,17 +54105,13 @@
5414954105
return pMem->u.i;
5415054106
}else if( flags & MEM_Real ){
5415154107
return doubleToInt64(pMem->r);
5415254108
}else if( flags & (MEM_Str|MEM_Blob) ){
5415354109
i64 value;
54154
- pMem->flags |= MEM_Str;
54155
- if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
54156
- || sqlite3VdbeMemNulTerminate(pMem) ){
54157
- return 0;
54158
- }
54159
- assert( pMem->z );
54160
- sqlite3Atoi64(pMem->z, &value);
54110
+ assert( pMem->z || pMem->n==0 );
54111
+ testcase( pMem->z==0 );
54112
+ sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
5416154113
return value;
5416254114
}else{
5416354115
return 0;
5416454116
}
5416554117
}
@@ -54185,11 +54137,11 @@
5418554137
|| sqlite3VdbeMemNulTerminate(pMem) ){
5418654138
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
5418754139
return (double)0;
5418854140
}
5418954141
assert( pMem->z );
54190
- sqlite3AtoF(pMem->z, &val);
54142
+ sqlite3AtoF(pMem->z, &val, pMem->n, SQLITE_UTF8);
5419154143
return val;
5419254144
}else{
5419354145
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
5419454146
return (double)0;
5419554147
}
@@ -54258,25 +54210,23 @@
5425854210
** Every effort is made to force the conversion, even if the input
5425954211
** is a string that does not look completely like a number. Convert
5426054212
** as much of the string as we can and ignore the rest.
5426154213
*/
5426254214
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
54263
- int rc;
54264
- assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
54265
- assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
54266
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
54267
- rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8);
54268
- if( rc ) return rc;
54269
- rc = sqlite3VdbeMemNulTerminate(pMem);
54270
- if( rc ) return rc;
54271
- if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){
54272
- MemSetTypeFlag(pMem, MEM_Int);
54273
- }else{
54274
- pMem->r = sqlite3VdbeRealValue(pMem);
54275
- MemSetTypeFlag(pMem, MEM_Real);
54276
- sqlite3VdbeIntegerAffinity(pMem);
54277
- }
54215
+ if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
54216
+ assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
54217
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
54218
+ if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){
54219
+ MemSetTypeFlag(pMem, MEM_Int);
54220
+ }else{
54221
+ pMem->r = sqlite3VdbeRealValue(pMem);
54222
+ MemSetTypeFlag(pMem, MEM_Real);
54223
+ sqlite3VdbeIntegerAffinity(pMem);
54224
+ }
54225
+ }
54226
+ assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
54227
+ pMem->flags &= ~(MEM_Str|MEM_Blob);
5427854228
return SQLITE_OK;
5427954229
}
5428054230
5428154231
/*
5428254232
** Delete any previous value and set the value stored in *pMem to NULL.
@@ -54815,10 +54765,12 @@
5481554765
sqlite3_value **ppVal /* Write the new value here */
5481654766
){
5481754767
int op;
5481854768
char *zVal = 0;
5481954769
sqlite3_value *pVal = 0;
54770
+ int negInt = 1;
54771
+ const char *zNeg = "";
5482054772
5482154773
if( !pExpr ){
5482254774
*ppVal = 0;
5482354775
return SQLITE_OK;
5482454776
}
@@ -54831,35 +54783,50 @@
5483154783
#ifdef SQLITE_ENABLE_STAT2
5483254784
if( op==TK_REGISTER ) op = pExpr->op2;
5483354785
#else
5483454786
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
5483554787
#endif
54788
+
54789
+ /* Handle negative integers in a single step. This is needed in the
54790
+ ** case when the value is -9223372036854775808.
54791
+ */
54792
+ if( op==TK_UMINUS
54793
+ && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
54794
+ pExpr = pExpr->pLeft;
54795
+ op = pExpr->op;
54796
+ negInt = -1;
54797
+ zNeg = "-";
54798
+ }
5483654799
5483754800
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
5483854801
pVal = sqlite3ValueNew(db);
5483954802
if( pVal==0 ) goto no_mem;
5484054803
if( ExprHasProperty(pExpr, EP_IntValue) ){
54841
- sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue);
54804
+ sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
5484254805
}else{
54843
- zVal = sqlite3DbStrDup(db, pExpr->u.zToken);
54806
+ zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
5484454807
if( zVal==0 ) goto no_mem;
5484554808
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
5484654809
if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
5484754810
}
5484854811
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
5484954812
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
5485054813
}else{
5485154814
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
5485254815
}
54816
+ if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
5485354817
if( enc!=SQLITE_UTF8 ){
5485454818
sqlite3VdbeChangeEncoding(pVal, enc);
5485554819
}
5485654820
}else if( op==TK_UMINUS ) {
54821
+ /* This branch happens for multiple negative signs. Ex: -(-5) */
5485754822
if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
54823
+ sqlite3VdbeMemNumerify(pVal);
5485854824
pVal->u.i = -1 * pVal->u.i;
5485954825
/* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */
5486054826
pVal->r = (double)-1 * pVal->r;
54827
+ sqlite3ValueApplyAffinity(pVal, affinity, enc);
5486154828
}
5486254829
}
5486354830
#ifndef SQLITE_OMIT_BLOB_LITERAL
5486454831
else if( op==TK_BLOB ){
5486554832
int nVal;
@@ -59770,35 +59737,21 @@
5977059737
** looks like a number, convert it into a number. If it does not
5977159738
** look like a number, leave it alone.
5977259739
*/
5977359740
static void applyNumericAffinity(Mem *pRec){
5977459741
if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
59775
- int realnum;
59742
+ double rValue;
59743
+ i64 iValue;
5977659744
u8 enc = pRec->enc;
59777
- sqlite3VdbeMemNulTerminate(pRec);
59778
- if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){
59779
- i64 value;
59780
- char *zUtf8 = pRec->z;
59781
-#ifndef SQLITE_OMIT_UTF16
59782
- if( enc!=SQLITE_UTF8 ){
59783
- assert( pRec->db );
59784
- zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc);
59785
- if( !zUtf8 ) return;
59786
- }
59787
-#endif
59788
- if( !realnum && sqlite3Atoi64(zUtf8, &value) ){
59789
- pRec->u.i = value;
59790
- MemSetTypeFlag(pRec, MEM_Int);
59791
- }else{
59792
- sqlite3AtoF(zUtf8, &pRec->r);
59793
- MemSetTypeFlag(pRec, MEM_Real);
59794
- }
59795
-#ifndef SQLITE_OMIT_UTF16
59796
- if( enc!=SQLITE_UTF8 ){
59797
- sqlite3DbFree(pRec->db, zUtf8);
59798
- }
59799
-#endif
59745
+ if( (pRec->flags&MEM_Str)==0 ) return;
59746
+ if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
59747
+ if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
59748
+ pRec->u.i = iValue;
59749
+ pRec->flags |= MEM_Int;
59750
+ }else{
59751
+ pRec->r = rValue;
59752
+ pRec->flags |= MEM_Real;
5980059753
}
5980159754
}
5980259755
}
5980359756
5980459757
/*
@@ -61580,11 +61533,10 @@
6158061533
** integers, for space efficiency, but after extraction we want them
6158161534
** to have only a real value.
6158261535
*/
6158361536
case OP_RealAffinity: { /* in1 */
6158461537
pIn1 = &aMem[pOp->p1];
61585
- memAboutToChange(p, pIn1);
6158661538
if( pIn1->flags & MEM_Int ){
6158761539
sqlite3VdbeMemRealify(pIn1);
6158861540
}
6158961541
break;
6159061542
}
@@ -61623,11 +61575,10 @@
6162361575
**
6162461576
** A NULL value is not changed by this routine. It remains NULL.
6162561577
*/
6162661578
case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
6162761579
pIn1 = &aMem[pOp->p1];
61628
- memAboutToChange(p, pIn1);
6162961580
if( pIn1->flags & MEM_Null ) break;
6163061581
if( (pIn1->flags & MEM_Blob)==0 ){
6163161582
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
6163261583
assert( pIn1->flags & MEM_Str || db->mallocFailed );
6163361584
MemSetTypeFlag(pIn1, MEM_Blob);
@@ -61648,14 +61599,11 @@
6164861599
**
6164961600
** A NULL value is not changed by this routine. It remains NULL.
6165061601
*/
6165161602
case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
6165261603
pIn1 = &aMem[pOp->p1];
61653
- memAboutToChange(p, pIn1);
61654
- if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){
61655
- sqlite3VdbeMemNumerify(pIn1);
61656
- }
61604
+ sqlite3VdbeMemNumerify(pIn1);
6165761605
break;
6165861606
}
6165961607
#endif /* SQLITE_OMIT_CAST */
6166061608
6166161609
/* Opcode: ToInt P1 * * * *
@@ -61667,11 +61615,10 @@
6166761615
**
6166861616
** A NULL value is not changed by this routine. It remains NULL.
6166961617
*/
6167061618
case OP_ToInt: { /* same as TK_TO_INT, in1 */
6167161619
pIn1 = &aMem[pOp->p1];
61672
- memAboutToChange(p, pIn1);
6167361620
if( (pIn1->flags & MEM_Null)==0 ){
6167461621
sqlite3VdbeMemIntegerify(pIn1);
6167561622
}
6167661623
break;
6167761624
}
@@ -61781,12 +61728,10 @@
6178161728
u16 flags3; /* Copy of initial value of pIn3->flags */
6178261729
#endif /* local variables moved into u.ai */
6178361730
6178461731
pIn1 = &aMem[pOp->p1];
6178561732
pIn3 = &aMem[pOp->p3];
61786
- memAboutToChange(p, pIn1);
61787
- memAboutToChange(p, pIn3);
6178861733
u.ai.flags1 = pIn1->flags;
6178961734
u.ai.flags3 = pIn3->flags;
6179061735
if( (pIn1->flags | pIn3->flags)&MEM_Null ){
6179161736
/* One or both operands are NULL */
6179261737
if( pOp->p5 & SQLITE_NULLEQ ){
@@ -62415,11 +62360,10 @@
6241562360
assert( u.an.zAffinity[pOp->p2]==0 );
6241662361
pIn1 = &aMem[pOp->p1];
6241762362
while( (u.an.cAff = *(u.an.zAffinity++))!=0 ){
6241862363
assert( pIn1 <= &p->aMem[p->nMem] );
6241962364
assert( memIsValid(pIn1) );
62420
- memAboutToChange(p, pIn1);
6242162365
ExpandBlob(pIn1);
6242262366
applyAffinity(pIn1, u.an.cAff, encoding);
6242362367
pIn1++;
6242462368
}
6242562369
break;
@@ -62495,11 +62439,10 @@
6249562439
** out how much space is required for the new record.
6249662440
*/
6249762441
for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){
6249862442
assert( memIsValid(u.ao.pRec) );
6249962443
if( u.ao.zAffinity ){
62500
- memAboutToChange(p, u.ao.pRec);
6250162444
applyAffinity(u.ao.pRec, u.ao.zAffinity[u.ao.pRec-u.ao.pData0], encoding);
6250262445
}
6250362446
if( u.ao.pRec->flags&MEM_Zero && u.ao.pRec->n>0 ){
6250462447
sqlite3VdbeMemExpandBlob(u.ao.pRec);
6250562448
}
@@ -68880,11 +68823,11 @@
6888068823
pExpr->iColumn = (ynVar)(++pParse->nVar);
6888168824
}else if( z[0]=='?' ){
6888268825
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
6888368826
** use it as the variable number */
6888468827
i64 i;
68885
- int bOk = sqlite3Atoi64(&z[1], &i);
68828
+ int bOk = 0==sqlite3Atoi64(&z[1], &i, sqlite3Strlen30(&z[1]), SQLITE_UTF8);
6888668829
pExpr->iColumn = (ynVar)i;
6888768830
testcase( i==0 );
6888868831
testcase( i==1 );
6888968832
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
6889068833
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
@@ -70243,11 +70186,11 @@
7024370186
*/
7024470187
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
7024570188
if( ALWAYS(z!=0) ){
7024670189
double value;
7024770190
char *zV;
70248
- sqlite3AtoF(z, &value);
70191
+ sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
7024970192
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
7025070193
if( negateFlag ) value = -value;
7025170194
zV = dup8bytes(v, (char*)&value);
7025270195
sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
7025370196
}
@@ -70257,28 +70200,27 @@
7025770200
7025870201
/*
7025970202
** Generate an instruction that will put the integer describe by
7026070203
** text z[0..n-1] into register iMem.
7026170204
**
70262
-** The z[] string will probably not be zero-terminated. But the
70263
-** z[n] character is guaranteed to be something that does not look
70264
-** like the continuation of the number.
70205
+** Expr.u.zToken is always UTF8 and zero-terminated.
7026570206
*/
7026670207
static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
7026770208
Vdbe *v = pParse->pVdbe;
7026870209
if( pExpr->flags & EP_IntValue ){
7026970210
int i = pExpr->u.iValue;
7027070211
if( negFlag ) i = -i;
7027170212
sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
7027270213
}else{
70214
+ int c;
70215
+ i64 value;
7027370216
const char *z = pExpr->u.zToken;
7027470217
assert( z!=0 );
70275
- if( sqlite3FitsIn64Bits(z, negFlag) ){
70276
- i64 value;
70218
+ c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
70219
+ if( c==0 || (c==2 && negFlag) ){
7027770220
char *zV;
70278
- sqlite3Atoi64(z, &value);
70279
- if( negFlag ) value = -value;
70221
+ if( negFlag ){ value = -value; }
7028070222
zV = dup8bytes(v, (char*)&value);
7028170223
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
7028270224
}else{
7028370225
#ifdef SQLITE_OMIT_FLOATING_POINT
7028470226
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
@@ -79414,11 +79356,11 @@
7941479356
zBuf = sqlite3_mprintf("%.*f",n,r);
7941579357
if( zBuf==0 ){
7941679358
sqlite3_result_error_nomem(context);
7941779359
return;
7941879360
}
79419
- sqlite3AtoF(zBuf, &r);
79361
+ sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
7942079362
sqlite3_free(zBuf);
7942179363
}
7942279364
sqlite3_result_double(context, r);
7942379365
}
7942479366
#endif
@@ -85472,11 +85414,11 @@
8547285414
*/
8547385415
if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){
8547485416
Pager *pPager = sqlite3BtreePager(pDb->pBt);
8547585417
i64 iLimit = -2;
8547685418
if( zRight ){
85477
- sqlite3Atoi64(zRight, &iLimit);
85419
+ sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8);
8547885420
if( iLimit<-1 ) iLimit = -1;
8547985421
}
8548085422
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
8548185423
returnSingleInt(pParse, "journal_size_limit", iLimit);
8548285424
}else
@@ -96380,11 +96322,12 @@
9638096322
9638196323
/*
9638296324
** Required because bestIndex() is called by bestOrClauseIndex()
9638396325
*/
9638496326
static void bestIndex(
96385
- Parse*, WhereClause*, struct SrcList_item*, Bitmask, ExprList*, WhereCost*);
96327
+ Parse*, WhereClause*, struct SrcList_item*,
96328
+ Bitmask, Bitmask, ExprList*, WhereCost*);
9638696329
9638796330
/*
9638896331
** This routine attempts to find an scanning strategy that can be used
9638996332
** to optimize an 'OR' expression that is part of a WHERE clause.
9639096333
**
@@ -96393,11 +96336,12 @@
9639396336
*/
9639496337
static void bestOrClauseIndex(
9639596338
Parse *pParse, /* The parsing context */
9639696339
WhereClause *pWC, /* The WHERE clause */
9639796340
struct SrcList_item *pSrc, /* The FROM clause term to search */
96398
- Bitmask notReady, /* Mask of cursors that are not available */
96341
+ Bitmask notReady, /* Mask of cursors not available for indexing */
96342
+ Bitmask notValid, /* Cursors not available for any purpose */
9639996343
ExprList *pOrderBy, /* The ORDER BY clause */
9640096344
WhereCost *pCost /* Lowest cost query plan */
9640196345
){
9640296346
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
9640396347
const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
@@ -96429,19 +96373,19 @@
9642996373
WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
9643096374
(pOrTerm - pOrWC->a), (pTerm - pWC->a)
9643196375
));
9643296376
if( pOrTerm->eOperator==WO_AND ){
9643396377
WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
96434
- bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost);
96378
+ bestIndex(pParse, pAndWC, pSrc, notReady, notValid, 0, &sTermCost);
9643596379
}else if( pOrTerm->leftCursor==iCur ){
9643696380
WhereClause tempWC;
9643796381
tempWC.pParse = pWC->pParse;
9643896382
tempWC.pMaskSet = pWC->pMaskSet;
9643996383
tempWC.op = TK_AND;
9644096384
tempWC.a = pOrTerm;
9644196385
tempWC.nTerm = 1;
96442
- bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost);
96386
+ bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost);
9644396387
}else{
9644496388
continue;
9644596389
}
9644696390
rTotal += sTermCost.rCost;
9644796391
nRow += sTermCost.nRow;
@@ -96884,11 +96828,12 @@
9688496828
*/
9688596829
static void bestVirtualIndex(
9688696830
Parse *pParse, /* The parsing context */
9688796831
WhereClause *pWC, /* The WHERE clause */
9688896832
struct SrcList_item *pSrc, /* The FROM clause term to search */
96889
- Bitmask notReady, /* Mask of cursors that are not available */
96833
+ Bitmask notReady, /* Mask of cursors not available for index */
96834
+ Bitmask notValid, /* Cursors not valid for any purpose */
9689096835
ExprList *pOrderBy, /* The order by clause */
9689196836
WhereCost *pCost, /* Lowest cost query plan */
9689296837
sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
9689396838
){
9689496839
Table *pTab = pSrc->pTab;
@@ -97014,11 +96959,11 @@
9701496959
pIdxInfo->nOrderBy = nOrderBy;
9701596960
9701696961
/* Try to find a more efficient access pattern by using multiple indexes
9701796962
** to optimize an OR expression within the WHERE clause.
9701896963
*/
97019
- bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
96964
+ bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
9702096965
}
9702196966
#endif /* SQLITE_OMIT_VIRTUALTABLE */
9702296967
9702396968
/*
9702496969
** Argument pIdx is a pointer to an index structure that has an array of
@@ -97295,11 +97240,12 @@
9729597240
*/
9729697241
static void bestBtreeIndex(
9729797242
Parse *pParse, /* The parsing context */
9729897243
WhereClause *pWC, /* The WHERE clause */
9729997244
struct SrcList_item *pSrc, /* The FROM clause term to search */
97300
- Bitmask notReady, /* Mask of cursors that are not available */
97245
+ Bitmask notReady, /* Mask of cursors not available for indexing */
97246
+ Bitmask notValid, /* Cursors not available for any purpose */
9730197247
ExprList *pOrderBy, /* The ORDER BY clause */
9730297248
WhereCost *pCost /* Lowest cost query plan */
9730397249
){
9730497250
int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
9730597251
Index *pProbe; /* An index we are evaluating */
@@ -97557,29 +97503,29 @@
9755797503
** of output rows, adjust the nRow value accordingly. This only
9755897504
** matters if the current index is the least costly, so do not bother
9755997505
** with this step if we already know this index will not be chosen.
9756097506
** Also, never reduce the output row count below 2 using this step.
9756197507
**
97562
- ** Do not reduce the output row count if pSrc is the only table that
97563
- ** is notReady; if notReady is a power of two. This will be the case
97564
- ** when the main sqlite3WhereBegin() loop is scanning for a table with
97565
- ** and "optimal" index, and on such a scan the output row count
97566
- ** reduction is not valid because it does not update the "pCost->used"
97567
- ** bitmap. The notReady bitmap will also be a power of two when we
97568
- ** are scanning for the last table in a 64-way join. We are willing
97569
- ** to bypass this optimization in that corner case.
97508
+ ** It is critical that the notValid mask be used here instead of
97509
+ ** the notReady mask. When computing an "optimal" index, the notReady
97510
+ ** mask will only have one bit set - the bit for the current table.
97511
+ ** The notValid mask, on the other hand, always has all bits set for
97512
+ ** tables that are not in outer loops. If notReady is used here instead
97513
+ ** of notValid, then a optimal index that depends on inner joins loops
97514
+ ** might be selected even when there exists an optimal index that has
97515
+ ** no such dependency.
9757097516
*/
97571
- if( nRow>2 && cost<=pCost->rCost && (notReady & (notReady-1))!=0 ){
97517
+ if( nRow>2 && cost<=pCost->rCost ){
9757297518
int k; /* Loop counter */
9757397519
int nSkipEq = nEq; /* Number of == constraints to skip */
9757497520
int nSkipRange = nBound; /* Number of < constraints to skip */
9757597521
Bitmask thisTab; /* Bitmap for pSrc */
9757697522
9757797523
thisTab = getMask(pWC->pMaskSet, iCur);
9757897524
for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){
9757997525
if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
97580
- if( (pTerm->prereqAll & notReady)!=thisTab ) continue;
97526
+ if( (pTerm->prereqAll & notValid)!=thisTab ) continue;
9758197527
if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
9758297528
if( nSkipEq ){
9758397529
/* Ignore the first nEq equality matches since the index
9758497530
** has already accounted for these */
9758597531
nSkipEq--;
@@ -97657,11 +97603,11 @@
9765797603
WHERETRACE(("best index is: %s\n",
9765897604
((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" :
9765997605
pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
9766097606
));
9766197607
97662
- bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
97608
+ bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
9766397609
bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost);
9766497610
pCost->plan.wsFlags |= eqTermMask;
9766597611
}
9766697612
9766797613
/*
@@ -97672,26 +97618,27 @@
9767297618
*/
9767397619
static void bestIndex(
9767497620
Parse *pParse, /* The parsing context */
9767597621
WhereClause *pWC, /* The WHERE clause */
9767697622
struct SrcList_item *pSrc, /* The FROM clause term to search */
97677
- Bitmask notReady, /* Mask of cursors that are not available */
97623
+ Bitmask notReady, /* Mask of cursors not available for indexing */
97624
+ Bitmask notValid, /* Cursors not available for any purpose */
9767897625
ExprList *pOrderBy, /* The ORDER BY clause */
9767997626
WhereCost *pCost /* Lowest cost query plan */
9768097627
){
9768197628
#ifndef SQLITE_OMIT_VIRTUALTABLE
9768297629
if( IsVirtual(pSrc->pTab) ){
9768397630
sqlite3_index_info *p = 0;
97684
- bestVirtualIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost, &p);
97631
+ bestVirtualIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost,&p);
9768597632
if( p->needToFreeIdxStr ){
9768697633
sqlite3_free(p->idxStr);
9768797634
}
9768897635
sqlite3DbFree(pParse->db, p);
9768997636
}else
9769097637
#endif
9769197638
{
97692
- bestBtreeIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
97639
+ bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
9769397640
}
9769497641
}
9769597642
9769697643
/*
9769797644
** Disable a term in the WHERE clause. Except, do not disable the term
@@ -98902,14 +98849,20 @@
9890298849
** by waiting for other tables to run first. This "optimal" test works
9890398850
** by first assuming that the FROM clause is on the inner loop and finding
9890498851
** its query plan, then checking to see if that query plan uses any
9890598852
** other FROM clause terms that are notReady. If no notReady terms are
9890698853
** used then the "optimal" query plan works.
98854
+ **
98855
+ ** Note that the WhereCost.nRow parameter for an optimal scan might
98856
+ ** not be as small as it would be if the table really were the innermost
98857
+ ** join. The nRow value can be reduced by WHERE clause constraints
98858
+ ** that do not use indices. But this nRow reduction only happens if the
98859
+ ** table really is the innermost join.
9890798860
**
9890898861
** The second loop iteration is only performed if no optimal scan
98909
- ** strategies were found by the first loop. This 2nd iteration is used to
98910
- ** search for the lowest cost scan overall.
98862
+ ** strategies were found by the first iteration. This second iteration
98863
+ ** is used to search for the lowest cost scan overall.
9891198864
**
9891298865
** Previous versions of SQLite performed only the second iteration -
9891398866
** the next outermost loop was always that with the lowest overall
9891498867
** cost. However, this meant that SQLite could select the wrong plan
9891598868
** for scripts such as the following:
@@ -98925,11 +98878,11 @@
9892598878
** algorithm may choose to use t2 for the outer loop, which is a much
9892698879
** costlier approach.
9892798880
*/
9892898881
nUnconstrained = 0;
9892998882
notIndexed = 0;
98930
- for(isOptimal=(iFrom<nTabList-1); isOptimal>=0; isOptimal--){
98883
+ for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
9893198884
Bitmask mask; /* Mask of tables not yet ready */
9893298885
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
9893398886
int doNotReorder; /* True if this table should not be reordered */
9893498887
WhereCost sCost; /* Cost information from best[Virtual]Index() */
9893598888
ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
@@ -98947,15 +98900,17 @@
9894798900
9894898901
assert( pTabItem->pTab );
9894998902
#ifndef SQLITE_OMIT_VIRTUALTABLE
9895098903
if( IsVirtual(pTabItem->pTab) ){
9895198904
sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
98952
- bestVirtualIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost, pp);
98905
+ bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
98906
+ &sCost, pp);
9895398907
}else
9895498908
#endif
9895598909
{
98956
- bestBtreeIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost);
98910
+ bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
98911
+ &sCost);
9895798912
}
9895898913
assert( isOptimal || (sCost.used&notReady)==0 );
9895998914
9896098915
/* If an INDEXED BY clause is present, then the plan must use that
9896198916
** index if it uses any index at all */
9896298917
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -650,11 +650,11 @@
650 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651 ** [sqlite_version()] and [sqlite_source_id()].
652 */
653 #define SQLITE_VERSION "3.7.3"
654 #define SQLITE_VERSION_NUMBER 3007003
655 #define SQLITE_SOURCE_ID "2010-09-29 23:09:23 1ef0dc9328f47506cb2dcd142150e96cb4755216"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -10570,11 +10570,10 @@
10570
10571 /*
10572 ** Internal function prototypes
10573 */
10574 SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *);
10575 SQLITE_PRIVATE int sqlite3IsNumber(const char*, int*, u8);
10576 SQLITE_PRIVATE int sqlite3Strlen30(const char*);
10577 #define sqlite3StrNICmp sqlite3_strnicmp
10578
10579 SQLITE_PRIVATE int sqlite3MallocInit(void);
10580 SQLITE_PRIVATE void sqlite3MallocEnd(void);
@@ -10890,13 +10889,12 @@
10890 SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
10891 SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
10892 SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
10893 SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
10894 SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
10895 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*);
10896 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
10897 SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *, int);
10898 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
10899 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
10900 SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**);
10901
10902 /*
@@ -10938,11 +10936,11 @@
10938 SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *);
10939 SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *);
10940 SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
10941 SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
10942 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
10943 SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*);
10944 SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
10945 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
10946 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
10947 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
10948 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
@@ -12637,16 +12635,10 @@
12637 end_getDigits:
12638 va_end(ap);
12639 return cnt;
12640 }
12641
12642 /*
12643 ** Read text from z[] and convert into a floating point number. Return
12644 ** the number of digits converted.
12645 */
12646 #define getValue sqlite3AtoF
12647
12648 /*
12649 ** Parse a timezone extension on the end of a date-time.
12650 ** The extension is of the form:
12651 **
12652 ** (+/-)HH:MM
@@ -12844,21 +12836,19 @@
12844 static int parseDateOrTime(
12845 sqlite3_context *context,
12846 const char *zDate,
12847 DateTime *p
12848 ){
12849 int isRealNum; /* Return from sqlite3IsNumber(). Not used */
12850 if( parseYyyyMmDd(zDate,p)==0 ){
12851 return 0;
12852 }else if( parseHhMmSs(zDate, p)==0 ){
12853 return 0;
12854 }else if( sqlite3StrICmp(zDate,"now")==0){
12855 setDateTimeToCurrent(context, p);
12856 return 0;
12857 }else if( sqlite3IsNumber(zDate, &isRealNum, SQLITE_UTF8) ){
12858 double r;
12859 getValue(zDate, &r);
12860 p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
12861 p->validJD = 1;
12862 return 0;
12863 }
12864 return 1;
@@ -13075,12 +13065,13 @@
13075 **
13076 ** Move the date to the same time on the next occurrence of
13077 ** weekday N where 0==Sunday, 1==Monday, and so forth. If the
13078 ** date is already on the appropriate weekday, this is a no-op.
13079 */
13080 if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
13081 && (n=(int)r)==r && n>=0 && r<7 ){
 
13082 sqlite3_int64 Z;
13083 computeYMD_HMS(p);
13084 p->validTZ = 0;
13085 p->validJD = 0;
13086 computeJD(p);
@@ -13131,12 +13122,15 @@
13131 case '6':
13132 case '7':
13133 case '8':
13134 case '9': {
13135 double rRounder;
13136 n = getValue(z, &r);
13137 assert( n>=1 );
 
 
 
13138 if( z[n]==':' ){
13139 /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
13140 ** specified number of hours, minutes, seconds, and fractional seconds
13141 ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
13142 ** omitted.
@@ -17502,11 +17496,11 @@
17502 sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n);
17503 }else{
17504 sqlite3MemoryAlarm(0, 0, 0);
17505 }
17506 excess = sqlite3_memory_used() - n;
17507 if( excess>0 ) sqlite3_release_memory(excess & 0x7fffffff);
17508 return priorLimit;
17509 }
17510 SQLITE_API void sqlite3_soft_heap_limit(int n){
17511 if( n<0 ) n = 0;
17512 sqlite3_soft_heap_limit64(n);
@@ -20096,125 +20090,115 @@
20096 while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
20097 return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
20098 }
20099
20100 /*
20101 ** Return TRUE if z is a pure numeric string. Return FALSE and leave
20102 ** *realnum unchanged if the string contains any character which is not
20103 ** part of a number.
20104 **
20105 ** If the string is pure numeric, set *realnum to TRUE if the string
20106 ** contains the '.' character or an "E+000" style exponentiation suffix.
20107 ** Otherwise set *realnum to FALSE. Note that just becaue *realnum is
20108 ** false does not mean that the number can be successfully converted into
20109 ** an integer - it might be too big.
20110 **
20111 ** An empty string is considered non-numeric.
20112 */
20113 SQLITE_PRIVATE int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
 
 
 
 
 
 
 
 
 
 
20114 int incr = (enc==SQLITE_UTF8?1:2);
20115 if( enc==SQLITE_UTF16BE ) z++;
20116 if( *z=='-' || *z=='+' ) z += incr;
20117 if( !sqlite3Isdigit(*z) ){
20118 return 0;
20119 }
20120 z += incr;
20121 *realnum = 0;
20122 while( sqlite3Isdigit(*z) ){ z += incr; }
20123 #ifndef SQLITE_OMIT_FLOATING_POINT
20124 if( *z=='.' ){
20125 z += incr;
20126 if( !sqlite3Isdigit(*z) ) return 0;
20127 while( sqlite3Isdigit(*z) ){ z += incr; }
20128 *realnum = 1;
20129 }
20130 if( *z=='e' || *z=='E' ){
20131 z += incr;
20132 if( *z=='+' || *z=='-' ) z += incr;
20133 if( !sqlite3Isdigit(*z) ) return 0;
20134 while( sqlite3Isdigit(*z) ){ z += incr; }
20135 *realnum = 1;
20136 }
20137 #endif
20138 return *z==0;
20139 }
20140
20141 /*
20142 ** The string z[] is an ASCII representation of a real number.
20143 ** Convert this string to a double.
20144 **
20145 ** This routine assumes that z[] really is a valid number. If it
20146 ** is not, the result is undefined.
20147 **
20148 ** This routine is used instead of the library atof() function because
20149 ** the library atof() might want to use "," as the decimal point instead
20150 ** of "." depending on how locale is set. But that would cause problems
20151 ** for SQL. So this routine always uses "." regardless of locale.
20152 */
20153 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){
20154 #ifndef SQLITE_OMIT_FLOATING_POINT
20155 const char *zBegin = z;
20156 /* sign * significand * (10 ^ (esign * exponent)) */
20157 int sign = 1; /* sign of significand */
20158 i64 s = 0; /* significand */
20159 int d = 0; /* adjust exponent for shifting decimal point */
20160 int esign = 1; /* sign of exponent */
20161 int e = 0; /* exponent */
 
20162 double result;
20163 int nDigits = 0;
20164
 
 
 
 
20165 /* skip leading spaces */
20166 while( sqlite3Isspace(*z) ) z++;
 
 
20167 /* get sign of significand */
20168 if( *z=='-' ){
20169 sign = -1;
20170 z++;
20171 }else if( *z=='+' ){
20172 z++;
20173 }
 
20174 /* skip leading zeroes */
20175 while( z[0]=='0' ) z++, nDigits++;
20176
20177 /* copy max significant digits to significand */
20178 while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
20179 s = s*10 + (*z - '0');
20180 z++, nDigits++;
20181 }
 
20182 /* skip non-significant significand digits
20183 ** (increase exponent by d to shift decimal left) */
20184 while( sqlite3Isdigit(*z) ) z++, nDigits++, d++;
 
20185
20186 /* if decimal point is present */
20187 if( *z=='.' ){
20188 z++;
20189 /* copy digits from after decimal to significand
20190 ** (decrease exponent by d to shift decimal right) */
20191 while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
20192 s = s*10 + (*z - '0');
20193 z++, nDigits++, d--;
20194 }
20195 /* skip non-significant digits */
20196 while( sqlite3Isdigit(*z) ) z++, nDigits++;
20197 }
 
20198
20199 /* if exponent is present */
20200 if( *z=='e' || *z=='E' ){
20201 z++;
 
 
20202 /* get sign of exponent */
20203 if( *z=='-' ){
20204 esign = -1;
20205 z++;
20206 }else if( *z=='+' ){
20207 z++;
20208 }
20209 /* copy digits to exponent */
20210 while( sqlite3Isdigit(*z) ){
20211 e = e*10 + (*z - '0');
20212 z++;
 
20213 }
20214 }
20215
 
 
 
 
 
 
20216 /* adjust exponent by d, and update sign */
20217 e = (e*esign) + d;
20218 if( e<0 ) {
20219 esign = -1;
20220 e *= -1;
@@ -20269,132 +20253,104 @@
20269 }
20270
20271 /* store the result */
20272 *pResult = result;
20273
20274 /* return number of characters used */
20275 return (int)(z - zBegin);
20276 #else
20277 return sqlite3Atoi64(z, pResult);
20278 #endif /* SQLITE_OMIT_FLOATING_POINT */
20279 }
20280
20281 /*
20282 ** Compare the 19-character string zNum against the text representation
20283 ** value 2^63: 9223372036854775808. Return negative, zero, or positive
20284 ** if zNum is less than, equal to, or greater than the string.
 
20285 **
20286 ** Unlike memcmp() this routine is guaranteed to return the difference
20287 ** in the values of the last digit if the only difference is in the
20288 ** last digit. So, for example,
20289 **
20290 ** compare2pow63("9223372036854775800")
20291 **
20292 ** will return -8.
20293 */
20294 static int compare2pow63(const char *zNum){
20295 int c;
20296 c = memcmp(zNum,"922337203685477580",18)*10;
 
 
 
 
 
20297 if( c==0 ){
20298 c = zNum[18] - '8';
20299 testcase( c==(-1) );
20300 testcase( c==0 );
20301 testcase( c==(+1) );
20302 }
20303 return c;
20304 }
20305
20306
20307 /*
20308 ** Return TRUE if zNum is a 64-bit signed integer and write
20309 ** the value of the integer into *pNum. If zNum is not an integer
20310 ** or is an integer that is too large to be expressed with 64 bits,
20311 ** then return false.
 
 
 
 
20312 **
20313 ** When this routine was originally written it dealt with only
20314 ** 32-bit numbers. At that time, it was much faster than the
20315 ** atoi() library routine in RedHat 7.2.
20316 */
20317 SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum){
 
20318 i64 v = 0;
20319 int neg;
20320 int i, c;
 
20321 const char *zStart;
20322 while( sqlite3Isspace(*zNum) ) zNum++;
 
 
 
20323 if( *zNum=='-' ){
20324 neg = 1;
20325 zNum++;
20326 }else if( *zNum=='+' ){
20327 neg = 0;
20328 zNum++;
20329 }else{
20330 neg = 0;
20331 }
 
20332 zStart = zNum;
20333 while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */
20334 for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
20335 v = v*10 + c - '0';
20336 }
20337 *pNum = neg ? -v : v;
20338 testcase( i==18 );
20339 testcase( i==19 );
20340 testcase( i==20 );
20341 if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
20342 /* zNum is empty or contains non-numeric text or is longer
20343 ** than 19 digits (thus guaranting that it is too large) */
20344 return 0;
20345 }else if( i<19 ){
20346 /* Less than 19 digits, so we know that it fits in 64 bits */
20347 return 1;
20348 }else{
20349 /* 19-digit numbers must be no larger than 9223372036854775807 if positive
20350 ** or 9223372036854775808 if negative. Note that 9223372036854665808
20351 ** is 2^63. */
20352 return compare2pow63(zNum)<neg;
20353 }
20354 }
20355
20356 /*
20357 ** The string zNum represents an unsigned integer. The zNum string
20358 ** consists of one or more digit characters and is terminated by
20359 ** a zero character. Any stray characters in zNum result in undefined
20360 ** behavior.
20361 **
20362 ** If the unsigned integer that zNum represents will fit in a
20363 ** 64-bit signed integer, return TRUE. Otherwise return FALSE.
20364 **
20365 ** If the negFlag parameter is true, that means that zNum really represents
20366 ** a negative number. (The leading "-" is omitted from zNum.) This
20367 ** parameter is needed to determine a boundary case. A string
20368 ** of "9223373036854775808" returns false if negFlag is false or true
20369 ** if negFlag is true.
20370 **
20371 ** Leading zeros are ignored.
20372 */
20373 SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *zNum, int negFlag){
20374 int i;
20375 int neg = 0;
20376
20377 assert( zNum[0]>='0' && zNum[0]<='9' ); /* zNum is an unsigned number */
20378
20379 if( negFlag ) neg = 1-neg;
20380 while( *zNum=='0' ){
20381 zNum++; /* Skip leading zeros. Ticket #2454 */
20382 }
20383 for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
20384 testcase( i==18 );
20385 testcase( i==19 );
20386 testcase( i==20 );
20387 if( i<19 ){
20388 /* Guaranteed to fit if less than 19 digits */
20389 return 1;
20390 }else if( i>19 ){
20391 /* Guaranteed to be too big if greater than 19 digits */
20392 return 0;
20393 }else{
20394 /* Compare against 2^63. */
20395 return compare2pow63(zNum)<neg;
20396 }
20397 }
20398
20399 /*
20400 ** If zNum represents an integer that will fit in 32-bits, then set
@@ -54149,17 +54105,13 @@
54149 return pMem->u.i;
54150 }else if( flags & MEM_Real ){
54151 return doubleToInt64(pMem->r);
54152 }else if( flags & (MEM_Str|MEM_Blob) ){
54153 i64 value;
54154 pMem->flags |= MEM_Str;
54155 if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
54156 || sqlite3VdbeMemNulTerminate(pMem) ){
54157 return 0;
54158 }
54159 assert( pMem->z );
54160 sqlite3Atoi64(pMem->z, &value);
54161 return value;
54162 }else{
54163 return 0;
54164 }
54165 }
@@ -54185,11 +54137,11 @@
54185 || sqlite3VdbeMemNulTerminate(pMem) ){
54186 /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
54187 return (double)0;
54188 }
54189 assert( pMem->z );
54190 sqlite3AtoF(pMem->z, &val);
54191 return val;
54192 }else{
54193 /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
54194 return (double)0;
54195 }
@@ -54258,25 +54210,23 @@
54258 ** Every effort is made to force the conversion, even if the input
54259 ** is a string that does not look completely like a number. Convert
54260 ** as much of the string as we can and ignore the rest.
54261 */
54262 SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
54263 int rc;
54264 assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
54265 assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
54266 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
54267 rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8);
54268 if( rc ) return rc;
54269 rc = sqlite3VdbeMemNulTerminate(pMem);
54270 if( rc ) return rc;
54271 if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){
54272 MemSetTypeFlag(pMem, MEM_Int);
54273 }else{
54274 pMem->r = sqlite3VdbeRealValue(pMem);
54275 MemSetTypeFlag(pMem, MEM_Real);
54276 sqlite3VdbeIntegerAffinity(pMem);
54277 }
54278 return SQLITE_OK;
54279 }
54280
54281 /*
54282 ** Delete any previous value and set the value stored in *pMem to NULL.
@@ -54815,10 +54765,12 @@
54815 sqlite3_value **ppVal /* Write the new value here */
54816 ){
54817 int op;
54818 char *zVal = 0;
54819 sqlite3_value *pVal = 0;
 
 
54820
54821 if( !pExpr ){
54822 *ppVal = 0;
54823 return SQLITE_OK;
54824 }
@@ -54831,35 +54783,50 @@
54831 #ifdef SQLITE_ENABLE_STAT2
54832 if( op==TK_REGISTER ) op = pExpr->op2;
54833 #else
54834 if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
54835 #endif
 
 
 
 
 
 
 
 
 
 
 
54836
54837 if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
54838 pVal = sqlite3ValueNew(db);
54839 if( pVal==0 ) goto no_mem;
54840 if( ExprHasProperty(pExpr, EP_IntValue) ){
54841 sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue);
54842 }else{
54843 zVal = sqlite3DbStrDup(db, pExpr->u.zToken);
54844 if( zVal==0 ) goto no_mem;
54845 sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
54846 if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
54847 }
54848 if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
54849 sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
54850 }else{
54851 sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
54852 }
 
54853 if( enc!=SQLITE_UTF8 ){
54854 sqlite3VdbeChangeEncoding(pVal, enc);
54855 }
54856 }else if( op==TK_UMINUS ) {
 
54857 if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
 
54858 pVal->u.i = -1 * pVal->u.i;
54859 /* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */
54860 pVal->r = (double)-1 * pVal->r;
 
54861 }
54862 }
54863 #ifndef SQLITE_OMIT_BLOB_LITERAL
54864 else if( op==TK_BLOB ){
54865 int nVal;
@@ -59770,35 +59737,21 @@
59770 ** looks like a number, convert it into a number. If it does not
59771 ** look like a number, leave it alone.
59772 */
59773 static void applyNumericAffinity(Mem *pRec){
59774 if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
59775 int realnum;
 
59776 u8 enc = pRec->enc;
59777 sqlite3VdbeMemNulTerminate(pRec);
59778 if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){
59779 i64 value;
59780 char *zUtf8 = pRec->z;
59781 #ifndef SQLITE_OMIT_UTF16
59782 if( enc!=SQLITE_UTF8 ){
59783 assert( pRec->db );
59784 zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc);
59785 if( !zUtf8 ) return;
59786 }
59787 #endif
59788 if( !realnum && sqlite3Atoi64(zUtf8, &value) ){
59789 pRec->u.i = value;
59790 MemSetTypeFlag(pRec, MEM_Int);
59791 }else{
59792 sqlite3AtoF(zUtf8, &pRec->r);
59793 MemSetTypeFlag(pRec, MEM_Real);
59794 }
59795 #ifndef SQLITE_OMIT_UTF16
59796 if( enc!=SQLITE_UTF8 ){
59797 sqlite3DbFree(pRec->db, zUtf8);
59798 }
59799 #endif
59800 }
59801 }
59802 }
59803
59804 /*
@@ -61580,11 +61533,10 @@
61580 ** integers, for space efficiency, but after extraction we want them
61581 ** to have only a real value.
61582 */
61583 case OP_RealAffinity: { /* in1 */
61584 pIn1 = &aMem[pOp->p1];
61585 memAboutToChange(p, pIn1);
61586 if( pIn1->flags & MEM_Int ){
61587 sqlite3VdbeMemRealify(pIn1);
61588 }
61589 break;
61590 }
@@ -61623,11 +61575,10 @@
61623 **
61624 ** A NULL value is not changed by this routine. It remains NULL.
61625 */
61626 case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
61627 pIn1 = &aMem[pOp->p1];
61628 memAboutToChange(p, pIn1);
61629 if( pIn1->flags & MEM_Null ) break;
61630 if( (pIn1->flags & MEM_Blob)==0 ){
61631 applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
61632 assert( pIn1->flags & MEM_Str || db->mallocFailed );
61633 MemSetTypeFlag(pIn1, MEM_Blob);
@@ -61648,14 +61599,11 @@
61648 **
61649 ** A NULL value is not changed by this routine. It remains NULL.
61650 */
61651 case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
61652 pIn1 = &aMem[pOp->p1];
61653 memAboutToChange(p, pIn1);
61654 if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){
61655 sqlite3VdbeMemNumerify(pIn1);
61656 }
61657 break;
61658 }
61659 #endif /* SQLITE_OMIT_CAST */
61660
61661 /* Opcode: ToInt P1 * * * *
@@ -61667,11 +61615,10 @@
61667 **
61668 ** A NULL value is not changed by this routine. It remains NULL.
61669 */
61670 case OP_ToInt: { /* same as TK_TO_INT, in1 */
61671 pIn1 = &aMem[pOp->p1];
61672 memAboutToChange(p, pIn1);
61673 if( (pIn1->flags & MEM_Null)==0 ){
61674 sqlite3VdbeMemIntegerify(pIn1);
61675 }
61676 break;
61677 }
@@ -61781,12 +61728,10 @@
61781 u16 flags3; /* Copy of initial value of pIn3->flags */
61782 #endif /* local variables moved into u.ai */
61783
61784 pIn1 = &aMem[pOp->p1];
61785 pIn3 = &aMem[pOp->p3];
61786 memAboutToChange(p, pIn1);
61787 memAboutToChange(p, pIn3);
61788 u.ai.flags1 = pIn1->flags;
61789 u.ai.flags3 = pIn3->flags;
61790 if( (pIn1->flags | pIn3->flags)&MEM_Null ){
61791 /* One or both operands are NULL */
61792 if( pOp->p5 & SQLITE_NULLEQ ){
@@ -62415,11 +62360,10 @@
62415 assert( u.an.zAffinity[pOp->p2]==0 );
62416 pIn1 = &aMem[pOp->p1];
62417 while( (u.an.cAff = *(u.an.zAffinity++))!=0 ){
62418 assert( pIn1 <= &p->aMem[p->nMem] );
62419 assert( memIsValid(pIn1) );
62420 memAboutToChange(p, pIn1);
62421 ExpandBlob(pIn1);
62422 applyAffinity(pIn1, u.an.cAff, encoding);
62423 pIn1++;
62424 }
62425 break;
@@ -62495,11 +62439,10 @@
62495 ** out how much space is required for the new record.
62496 */
62497 for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){
62498 assert( memIsValid(u.ao.pRec) );
62499 if( u.ao.zAffinity ){
62500 memAboutToChange(p, u.ao.pRec);
62501 applyAffinity(u.ao.pRec, u.ao.zAffinity[u.ao.pRec-u.ao.pData0], encoding);
62502 }
62503 if( u.ao.pRec->flags&MEM_Zero && u.ao.pRec->n>0 ){
62504 sqlite3VdbeMemExpandBlob(u.ao.pRec);
62505 }
@@ -68880,11 +68823,11 @@
68880 pExpr->iColumn = (ynVar)(++pParse->nVar);
68881 }else if( z[0]=='?' ){
68882 /* Wildcard of the form "?nnn". Convert "nnn" to an integer and
68883 ** use it as the variable number */
68884 i64 i;
68885 int bOk = sqlite3Atoi64(&z[1], &i);
68886 pExpr->iColumn = (ynVar)i;
68887 testcase( i==0 );
68888 testcase( i==1 );
68889 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
68890 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
@@ -70243,11 +70186,11 @@
70243 */
70244 static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
70245 if( ALWAYS(z!=0) ){
70246 double value;
70247 char *zV;
70248 sqlite3AtoF(z, &value);
70249 assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
70250 if( negateFlag ) value = -value;
70251 zV = dup8bytes(v, (char*)&value);
70252 sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
70253 }
@@ -70257,28 +70200,27 @@
70257
70258 /*
70259 ** Generate an instruction that will put the integer describe by
70260 ** text z[0..n-1] into register iMem.
70261 **
70262 ** The z[] string will probably not be zero-terminated. But the
70263 ** z[n] character is guaranteed to be something that does not look
70264 ** like the continuation of the number.
70265 */
70266 static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
70267 Vdbe *v = pParse->pVdbe;
70268 if( pExpr->flags & EP_IntValue ){
70269 int i = pExpr->u.iValue;
70270 if( negFlag ) i = -i;
70271 sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
70272 }else{
 
 
70273 const char *z = pExpr->u.zToken;
70274 assert( z!=0 );
70275 if( sqlite3FitsIn64Bits(z, negFlag) ){
70276 i64 value;
70277 char *zV;
70278 sqlite3Atoi64(z, &value);
70279 if( negFlag ) value = -value;
70280 zV = dup8bytes(v, (char*)&value);
70281 sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
70282 }else{
70283 #ifdef SQLITE_OMIT_FLOATING_POINT
70284 sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
@@ -79414,11 +79356,11 @@
79414 zBuf = sqlite3_mprintf("%.*f",n,r);
79415 if( zBuf==0 ){
79416 sqlite3_result_error_nomem(context);
79417 return;
79418 }
79419 sqlite3AtoF(zBuf, &r);
79420 sqlite3_free(zBuf);
79421 }
79422 sqlite3_result_double(context, r);
79423 }
79424 #endif
@@ -85472,11 +85414,11 @@
85472 */
85473 if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){
85474 Pager *pPager = sqlite3BtreePager(pDb->pBt);
85475 i64 iLimit = -2;
85476 if( zRight ){
85477 sqlite3Atoi64(zRight, &iLimit);
85478 if( iLimit<-1 ) iLimit = -1;
85479 }
85480 iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
85481 returnSingleInt(pParse, "journal_size_limit", iLimit);
85482 }else
@@ -96380,11 +96322,12 @@
96380
96381 /*
96382 ** Required because bestIndex() is called by bestOrClauseIndex()
96383 */
96384 static void bestIndex(
96385 Parse*, WhereClause*, struct SrcList_item*, Bitmask, ExprList*, WhereCost*);
 
96386
96387 /*
96388 ** This routine attempts to find an scanning strategy that can be used
96389 ** to optimize an 'OR' expression that is part of a WHERE clause.
96390 **
@@ -96393,11 +96336,12 @@
96393 */
96394 static void bestOrClauseIndex(
96395 Parse *pParse, /* The parsing context */
96396 WhereClause *pWC, /* The WHERE clause */
96397 struct SrcList_item *pSrc, /* The FROM clause term to search */
96398 Bitmask notReady, /* Mask of cursors that are not available */
 
96399 ExprList *pOrderBy, /* The ORDER BY clause */
96400 WhereCost *pCost /* Lowest cost query plan */
96401 ){
96402 #ifndef SQLITE_OMIT_OR_OPTIMIZATION
96403 const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
@@ -96429,19 +96373,19 @@
96429 WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
96430 (pOrTerm - pOrWC->a), (pTerm - pWC->a)
96431 ));
96432 if( pOrTerm->eOperator==WO_AND ){
96433 WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
96434 bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost);
96435 }else if( pOrTerm->leftCursor==iCur ){
96436 WhereClause tempWC;
96437 tempWC.pParse = pWC->pParse;
96438 tempWC.pMaskSet = pWC->pMaskSet;
96439 tempWC.op = TK_AND;
96440 tempWC.a = pOrTerm;
96441 tempWC.nTerm = 1;
96442 bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost);
96443 }else{
96444 continue;
96445 }
96446 rTotal += sTermCost.rCost;
96447 nRow += sTermCost.nRow;
@@ -96884,11 +96828,12 @@
96884 */
96885 static void bestVirtualIndex(
96886 Parse *pParse, /* The parsing context */
96887 WhereClause *pWC, /* The WHERE clause */
96888 struct SrcList_item *pSrc, /* The FROM clause term to search */
96889 Bitmask notReady, /* Mask of cursors that are not available */
 
96890 ExprList *pOrderBy, /* The order by clause */
96891 WhereCost *pCost, /* Lowest cost query plan */
96892 sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
96893 ){
96894 Table *pTab = pSrc->pTab;
@@ -97014,11 +96959,11 @@
97014 pIdxInfo->nOrderBy = nOrderBy;
97015
97016 /* Try to find a more efficient access pattern by using multiple indexes
97017 ** to optimize an OR expression within the WHERE clause.
97018 */
97019 bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
97020 }
97021 #endif /* SQLITE_OMIT_VIRTUALTABLE */
97022
97023 /*
97024 ** Argument pIdx is a pointer to an index structure that has an array of
@@ -97295,11 +97240,12 @@
97295 */
97296 static void bestBtreeIndex(
97297 Parse *pParse, /* The parsing context */
97298 WhereClause *pWC, /* The WHERE clause */
97299 struct SrcList_item *pSrc, /* The FROM clause term to search */
97300 Bitmask notReady, /* Mask of cursors that are not available */
 
97301 ExprList *pOrderBy, /* The ORDER BY clause */
97302 WhereCost *pCost /* Lowest cost query plan */
97303 ){
97304 int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
97305 Index *pProbe; /* An index we are evaluating */
@@ -97557,29 +97503,29 @@
97557 ** of output rows, adjust the nRow value accordingly. This only
97558 ** matters if the current index is the least costly, so do not bother
97559 ** with this step if we already know this index will not be chosen.
97560 ** Also, never reduce the output row count below 2 using this step.
97561 **
97562 ** Do not reduce the output row count if pSrc is the only table that
97563 ** is notReady; if notReady is a power of two. This will be the case
97564 ** when the main sqlite3WhereBegin() loop is scanning for a table with
97565 ** and "optimal" index, and on such a scan the output row count
97566 ** reduction is not valid because it does not update the "pCost->used"
97567 ** bitmap. The notReady bitmap will also be a power of two when we
97568 ** are scanning for the last table in a 64-way join. We are willing
97569 ** to bypass this optimization in that corner case.
97570 */
97571 if( nRow>2 && cost<=pCost->rCost && (notReady & (notReady-1))!=0 ){
97572 int k; /* Loop counter */
97573 int nSkipEq = nEq; /* Number of == constraints to skip */
97574 int nSkipRange = nBound; /* Number of < constraints to skip */
97575 Bitmask thisTab; /* Bitmap for pSrc */
97576
97577 thisTab = getMask(pWC->pMaskSet, iCur);
97578 for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){
97579 if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
97580 if( (pTerm->prereqAll & notReady)!=thisTab ) continue;
97581 if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
97582 if( nSkipEq ){
97583 /* Ignore the first nEq equality matches since the index
97584 ** has already accounted for these */
97585 nSkipEq--;
@@ -97657,11 +97603,11 @@
97657 WHERETRACE(("best index is: %s\n",
97658 ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" :
97659 pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
97660 ));
97661
97662 bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
97663 bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost);
97664 pCost->plan.wsFlags |= eqTermMask;
97665 }
97666
97667 /*
@@ -97672,26 +97618,27 @@
97672 */
97673 static void bestIndex(
97674 Parse *pParse, /* The parsing context */
97675 WhereClause *pWC, /* The WHERE clause */
97676 struct SrcList_item *pSrc, /* The FROM clause term to search */
97677 Bitmask notReady, /* Mask of cursors that are not available */
 
97678 ExprList *pOrderBy, /* The ORDER BY clause */
97679 WhereCost *pCost /* Lowest cost query plan */
97680 ){
97681 #ifndef SQLITE_OMIT_VIRTUALTABLE
97682 if( IsVirtual(pSrc->pTab) ){
97683 sqlite3_index_info *p = 0;
97684 bestVirtualIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost, &p);
97685 if( p->needToFreeIdxStr ){
97686 sqlite3_free(p->idxStr);
97687 }
97688 sqlite3DbFree(pParse->db, p);
97689 }else
97690 #endif
97691 {
97692 bestBtreeIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
97693 }
97694 }
97695
97696 /*
97697 ** Disable a term in the WHERE clause. Except, do not disable the term
@@ -98902,14 +98849,20 @@
98902 ** by waiting for other tables to run first. This "optimal" test works
98903 ** by first assuming that the FROM clause is on the inner loop and finding
98904 ** its query plan, then checking to see if that query plan uses any
98905 ** other FROM clause terms that are notReady. If no notReady terms are
98906 ** used then the "optimal" query plan works.
 
 
 
 
 
 
98907 **
98908 ** The second loop iteration is only performed if no optimal scan
98909 ** strategies were found by the first loop. This 2nd iteration is used to
98910 ** search for the lowest cost scan overall.
98911 **
98912 ** Previous versions of SQLite performed only the second iteration -
98913 ** the next outermost loop was always that with the lowest overall
98914 ** cost. However, this meant that SQLite could select the wrong plan
98915 ** for scripts such as the following:
@@ -98925,11 +98878,11 @@
98925 ** algorithm may choose to use t2 for the outer loop, which is a much
98926 ** costlier approach.
98927 */
98928 nUnconstrained = 0;
98929 notIndexed = 0;
98930 for(isOptimal=(iFrom<nTabList-1); isOptimal>=0; isOptimal--){
98931 Bitmask mask; /* Mask of tables not yet ready */
98932 for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
98933 int doNotReorder; /* True if this table should not be reordered */
98934 WhereCost sCost; /* Cost information from best[Virtual]Index() */
98935 ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
@@ -98947,15 +98900,17 @@
98947
98948 assert( pTabItem->pTab );
98949 #ifndef SQLITE_OMIT_VIRTUALTABLE
98950 if( IsVirtual(pTabItem->pTab) ){
98951 sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
98952 bestVirtualIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost, pp);
 
98953 }else
98954 #endif
98955 {
98956 bestBtreeIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost);
 
98957 }
98958 assert( isOptimal || (sCost.used&notReady)==0 );
98959
98960 /* If an INDEXED BY clause is present, then the plan must use that
98961 ** index if it uses any index at all */
98962
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -650,11 +650,11 @@
650 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651 ** [sqlite_version()] and [sqlite_source_id()].
652 */
653 #define SQLITE_VERSION "3.7.3"
654 #define SQLITE_VERSION_NUMBER 3007003
655 #define SQLITE_SOURCE_ID "2010-10-04 23:55:51 ece641eb8951c6314cedbdb3243f91cb199c3239"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -10570,11 +10570,10 @@
10570
10571 /*
10572 ** Internal function prototypes
10573 */
10574 SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *);
 
10575 SQLITE_PRIVATE int sqlite3Strlen30(const char*);
10576 #define sqlite3StrNICmp sqlite3_strnicmp
10577
10578 SQLITE_PRIVATE int sqlite3MallocInit(void);
10579 SQLITE_PRIVATE void sqlite3MallocEnd(void);
@@ -10890,13 +10889,12 @@
10889 SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
10890 SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
10891 SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
10892 SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
10893 SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
10894 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
10895 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
 
10896 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
10897 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
10898 SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**);
10899
10900 /*
@@ -10938,11 +10936,11 @@
10936 SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *);
10937 SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *);
10938 SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
10939 SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
10940 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
10941 SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
10942 SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
10943 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
10944 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
10945 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
10946 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
@@ -12637,16 +12635,10 @@
12635 end_getDigits:
12636 va_end(ap);
12637 return cnt;
12638 }
12639
 
 
 
 
 
 
12640 /*
12641 ** Parse a timezone extension on the end of a date-time.
12642 ** The extension is of the form:
12643 **
12644 ** (+/-)HH:MM
@@ -12844,21 +12836,19 @@
12836 static int parseDateOrTime(
12837 sqlite3_context *context,
12838 const char *zDate,
12839 DateTime *p
12840 ){
12841 double r;
12842 if( parseYyyyMmDd(zDate,p)==0 ){
12843 return 0;
12844 }else if( parseHhMmSs(zDate, p)==0 ){
12845 return 0;
12846 }else if( sqlite3StrICmp(zDate,"now")==0){
12847 setDateTimeToCurrent(context, p);
12848 return 0;
12849 }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
 
 
12850 p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
12851 p->validJD = 1;
12852 return 0;
12853 }
12854 return 1;
@@ -13075,12 +13065,13 @@
13065 **
13066 ** Move the date to the same time on the next occurrence of
13067 ** weekday N where 0==Sunday, 1==Monday, and so forth. If the
13068 ** date is already on the appropriate weekday, this is a no-op.
13069 */
13070 if( strncmp(z, "weekday ", 8)==0
13071 && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
13072 && (n=(int)r)==r && n>=0 && r<7 ){
13073 sqlite3_int64 Z;
13074 computeYMD_HMS(p);
13075 p->validTZ = 0;
13076 p->validJD = 0;
13077 computeJD(p);
@@ -13131,12 +13122,15 @@
13122 case '6':
13123 case '7':
13124 case '8':
13125 case '9': {
13126 double rRounder;
13127 for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
13128 if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
13129 rc = 1;
13130 break;
13131 }
13132 if( z[n]==':' ){
13133 /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
13134 ** specified number of hours, minutes, seconds, and fractional seconds
13135 ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
13136 ** omitted.
@@ -17502,11 +17496,11 @@
17496 sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n);
17497 }else{
17498 sqlite3MemoryAlarm(0, 0, 0);
17499 }
17500 excess = sqlite3_memory_used() - n;
17501 if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
17502 return priorLimit;
17503 }
17504 SQLITE_API void sqlite3_soft_heap_limit(int n){
17505 if( n<0 ) n = 0;
17506 sqlite3_soft_heap_limit64(n);
@@ -20096,125 +20090,115 @@
20090 while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
20091 return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
20092 }
20093
20094 /*
20095 ** The string z[] is an text representation of a real number.
20096 ** Convert this string to a double and write it into *pResult.
20097 **
20098 ** The string z[] is length bytes in length (bytes, not characters) and
20099 ** uses the encoding enc. The string is not necessarily zero-terminated.
20100 **
20101 ** Return TRUE if the result is a valid real number (or integer) and FALSE
20102 ** if the string is empty or contains extraneous text. Valid numbers
20103 ** are in one of these formats:
20104 **
20105 ** [+-]digits[E[+-]digits]
20106 ** [+-]digits.[digits][E[+-]digits]
20107 ** [+-].digits[E[+-]digits]
20108 **
20109 ** Leading and trailing whitespace is ignored for the purpose of determining
20110 ** validity.
20111 **
20112 ** If some prefix of the input string is a valid number, this routine
20113 ** returns FALSE but it still converts the prefix and writes the result
20114 ** into *pResult.
20115 */
20116 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
20117 #ifndef SQLITE_OMIT_FLOATING_POINT
20118 int incr = (enc==SQLITE_UTF8?1:2);
20119 const char *zEnd = z + length;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20120 /* sign * significand * (10 ^ (esign * exponent)) */
20121 int sign = 1; /* sign of significand */
20122 i64 s = 0; /* significand */
20123 int d = 0; /* adjust exponent for shifting decimal point */
20124 int esign = 1; /* sign of exponent */
20125 int e = 0; /* exponent */
20126 int eValid = 1; /* True exponent is either not used or is well-formed */
20127 double result;
20128 int nDigits = 0;
20129
20130 *pResult = 0.0; /* Default return value, in case of an error */
20131
20132 if( enc==SQLITE_UTF16BE ) z++;
20133
20134 /* skip leading spaces */
20135 while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
20136 if( z>=zEnd ) return 0;
20137
20138 /* get sign of significand */
20139 if( *z=='-' ){
20140 sign = -1;
20141 z+=incr;
20142 }else if( *z=='+' ){
20143 z+=incr;
20144 }
20145
20146 /* skip leading zeroes */
20147 while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
20148
20149 /* copy max significant digits to significand */
20150 while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
20151 s = s*10 + (*z - '0');
20152 z+=incr, nDigits++;
20153 }
20154
20155 /* skip non-significant significand digits
20156 ** (increase exponent by d to shift decimal left) */
20157 while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
20158 if( z>=zEnd ) goto do_atof_calc;
20159
20160 /* if decimal point is present */
20161 if( *z=='.' ){
20162 z+=incr;
20163 /* copy digits from after decimal to significand
20164 ** (decrease exponent by d to shift decimal right) */
20165 while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
20166 s = s*10 + (*z - '0');
20167 z+=incr, nDigits++, d--;
20168 }
20169 /* skip non-significant digits */
20170 while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
20171 }
20172 if( z>=zEnd ) goto do_atof_calc;
20173
20174 /* if exponent is present */
20175 if( *z=='e' || *z=='E' ){
20176 z+=incr;
20177 eValid = 0;
20178 if( z>=zEnd ) goto do_atof_calc;
20179 /* get sign of exponent */
20180 if( *z=='-' ){
20181 esign = -1;
20182 z+=incr;
20183 }else if( *z=='+' ){
20184 z+=incr;
20185 }
20186 /* copy digits to exponent */
20187 while( z<zEnd && sqlite3Isdigit(*z) ){
20188 e = e*10 + (*z - '0');
20189 z+=incr;
20190 eValid = 1;
20191 }
20192 }
20193
20194 /* skip trailing spaces */
20195 if( nDigits && eValid ){
20196 while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
20197 }
20198
20199 do_atof_calc:
20200 /* adjust exponent by d, and update sign */
20201 e = (e*esign) + d;
20202 if( e<0 ) {
20203 esign = -1;
20204 e *= -1;
@@ -20269,132 +20253,104 @@
20253 }
20254
20255 /* store the result */
20256 *pResult = result;
20257
20258 /* return true if number and no extra non-whitespace chracters after */
20259 return z>=zEnd && nDigits>0 && eValid;
20260 #else
20261 return !sqlite3Atoi64(z, pResult, length, enc);
20262 #endif /* SQLITE_OMIT_FLOATING_POINT */
20263 }
20264
20265 /*
20266 ** Compare the 19-character string zNum against the text representation
20267 ** value 2^63: 9223372036854775808. Return negative, zero, or positive
20268 ** if zNum is less than, equal to, or greater than the string.
20269 ** Note that zNum must contain exactly 19 characters.
20270 **
20271 ** Unlike memcmp() this routine is guaranteed to return the difference
20272 ** in the values of the last digit if the only difference is in the
20273 ** last digit. So, for example,
20274 **
20275 ** compare2pow63("9223372036854775800", 1)
20276 **
20277 ** will return -8.
20278 */
20279 static int compare2pow63(const char *zNum, int incr){
20280 int c = 0;
20281 int i;
20282 /* 012345678901234567 */
20283 const char *pow63 = "922337203685477580";
20284 for(i=0; c==0 && i<18; i++){
20285 c = (zNum[i*incr]-pow63[i])*10;
20286 }
20287 if( c==0 ){
20288 c = zNum[18*incr] - '8';
20289 testcase( c==(-1) );
20290 testcase( c==0 );
20291 testcase( c==(+1) );
20292 }
20293 return c;
20294 }
20295
20296
20297 /*
20298 ** Convert zNum to a 64-bit signed integer and write
20299 ** the value of the integer into *pNum.
20300 ** If zNum is exactly 9223372036854665808, return 2.
20301 ** This is a special case as the context will determine
20302 ** if it is too big (used as a negative).
20303 ** If zNum is not an integer or is an integer that
20304 ** is too large to be expressed with 64 bits,
20305 ** then return 1. Otherwise return 0.
20306 **
20307 ** length is the number of bytes in the string (bytes, not characters).
20308 ** The string is not necessarily zero-terminated. The encoding is
20309 ** given by enc.
20310 */
20311 SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
20312 int incr = (enc==SQLITE_UTF8?1:2);
20313 i64 v = 0;
20314 int neg = 0; /* assume positive */
20315 int i;
20316 int c = 0;
20317 const char *zStart;
20318 const char *zEnd = zNum + length;
20319 if( enc==SQLITE_UTF16BE ) zNum++;
20320 while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
20321 if( zNum>=zEnd ) goto do_atoi_calc;
20322 if( *zNum=='-' ){
20323 neg = 1;
20324 zNum+=incr;
20325 }else if( *zNum=='+' ){
20326 zNum+=incr;
 
 
 
20327 }
20328 do_atoi_calc:
20329 zStart = zNum;
20330 while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
20331 for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
20332 v = v*10 + c - '0';
20333 }
20334 *pNum = neg ? -v : v;
20335 testcase( i==18 );
20336 testcase( i==19 );
20337 testcase( i==20 );
20338 if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){
20339 /* zNum is empty or contains non-numeric text or is longer
20340 ** than 19 digits (thus guaranteeing that it is too large) */
20341 return 1;
20342 }else if( i<19*incr ){
20343 /* Less than 19 digits, so we know that it fits in 64 bits */
20344 return 0;
20345 }else{
20346 /* 19-digit numbers must be no larger than 9223372036854775807 if positive
20347 ** or 9223372036854775808 if negative. Note that 9223372036854665808
20348 ** is 2^63. Return 1 if to large */
20349 c=compare2pow63(zNum, incr);
20350 if( c==0 && neg==0 ) return 2; /* too big, exactly 9223372036854665808 */
20351 return c<neg ? 0 : 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20352 }
20353 }
20354
20355 /*
20356 ** If zNum represents an integer that will fit in 32-bits, then set
@@ -54149,17 +54105,13 @@
54105 return pMem->u.i;
54106 }else if( flags & MEM_Real ){
54107 return doubleToInt64(pMem->r);
54108 }else if( flags & (MEM_Str|MEM_Blob) ){
54109 i64 value;
54110 assert( pMem->z || pMem->n==0 );
54111 testcase( pMem->z==0 );
54112 sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
 
 
 
 
54113 return value;
54114 }else{
54115 return 0;
54116 }
54117 }
@@ -54185,11 +54137,11 @@
54137 || sqlite3VdbeMemNulTerminate(pMem) ){
54138 /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
54139 return (double)0;
54140 }
54141 assert( pMem->z );
54142 sqlite3AtoF(pMem->z, &val, pMem->n, SQLITE_UTF8);
54143 return val;
54144 }else{
54145 /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
54146 return (double)0;
54147 }
@@ -54258,25 +54210,23 @@
54210 ** Every effort is made to force the conversion, even if the input
54211 ** is a string that does not look completely like a number. Convert
54212 ** as much of the string as we can and ignore the rest.
54213 */
54214 SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
54215 if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
54216 assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
54217 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
54218 if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){
54219 MemSetTypeFlag(pMem, MEM_Int);
54220 }else{
54221 pMem->r = sqlite3VdbeRealValue(pMem);
54222 MemSetTypeFlag(pMem, MEM_Real);
54223 sqlite3VdbeIntegerAffinity(pMem);
54224 }
54225 }
54226 assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
54227 pMem->flags &= ~(MEM_Str|MEM_Blob);
 
 
54228 return SQLITE_OK;
54229 }
54230
54231 /*
54232 ** Delete any previous value and set the value stored in *pMem to NULL.
@@ -54815,10 +54765,12 @@
54765 sqlite3_value **ppVal /* Write the new value here */
54766 ){
54767 int op;
54768 char *zVal = 0;
54769 sqlite3_value *pVal = 0;
54770 int negInt = 1;
54771 const char *zNeg = "";
54772
54773 if( !pExpr ){
54774 *ppVal = 0;
54775 return SQLITE_OK;
54776 }
@@ -54831,35 +54783,50 @@
54783 #ifdef SQLITE_ENABLE_STAT2
54784 if( op==TK_REGISTER ) op = pExpr->op2;
54785 #else
54786 if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
54787 #endif
54788
54789 /* Handle negative integers in a single step. This is needed in the
54790 ** case when the value is -9223372036854775808.
54791 */
54792 if( op==TK_UMINUS
54793 && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
54794 pExpr = pExpr->pLeft;
54795 op = pExpr->op;
54796 negInt = -1;
54797 zNeg = "-";
54798 }
54799
54800 if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
54801 pVal = sqlite3ValueNew(db);
54802 if( pVal==0 ) goto no_mem;
54803 if( ExprHasProperty(pExpr, EP_IntValue) ){
54804 sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
54805 }else{
54806 zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
54807 if( zVal==0 ) goto no_mem;
54808 sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
54809 if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
54810 }
54811 if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
54812 sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
54813 }else{
54814 sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
54815 }
54816 if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
54817 if( enc!=SQLITE_UTF8 ){
54818 sqlite3VdbeChangeEncoding(pVal, enc);
54819 }
54820 }else if( op==TK_UMINUS ) {
54821 /* This branch happens for multiple negative signs. Ex: -(-5) */
54822 if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
54823 sqlite3VdbeMemNumerify(pVal);
54824 pVal->u.i = -1 * pVal->u.i;
54825 /* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */
54826 pVal->r = (double)-1 * pVal->r;
54827 sqlite3ValueApplyAffinity(pVal, affinity, enc);
54828 }
54829 }
54830 #ifndef SQLITE_OMIT_BLOB_LITERAL
54831 else if( op==TK_BLOB ){
54832 int nVal;
@@ -59770,35 +59737,21 @@
59737 ** looks like a number, convert it into a number. If it does not
59738 ** look like a number, leave it alone.
59739 */
59740 static void applyNumericAffinity(Mem *pRec){
59741 if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
59742 double rValue;
59743 i64 iValue;
59744 u8 enc = pRec->enc;
59745 if( (pRec->flags&MEM_Str)==0 ) return;
59746 if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
59747 if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
59748 pRec->u.i = iValue;
59749 pRec->flags |= MEM_Int;
59750 }else{
59751 pRec->r = rValue;
59752 pRec->flags |= MEM_Real;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59753 }
59754 }
59755 }
59756
59757 /*
@@ -61580,11 +61533,10 @@
61533 ** integers, for space efficiency, but after extraction we want them
61534 ** to have only a real value.
61535 */
61536 case OP_RealAffinity: { /* in1 */
61537 pIn1 = &aMem[pOp->p1];
 
61538 if( pIn1->flags & MEM_Int ){
61539 sqlite3VdbeMemRealify(pIn1);
61540 }
61541 break;
61542 }
@@ -61623,11 +61575,10 @@
61575 **
61576 ** A NULL value is not changed by this routine. It remains NULL.
61577 */
61578 case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
61579 pIn1 = &aMem[pOp->p1];
 
61580 if( pIn1->flags & MEM_Null ) break;
61581 if( (pIn1->flags & MEM_Blob)==0 ){
61582 applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
61583 assert( pIn1->flags & MEM_Str || db->mallocFailed );
61584 MemSetTypeFlag(pIn1, MEM_Blob);
@@ -61648,14 +61599,11 @@
61599 **
61600 ** A NULL value is not changed by this routine. It remains NULL.
61601 */
61602 case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
61603 pIn1 = &aMem[pOp->p1];
61604 sqlite3VdbeMemNumerify(pIn1);
 
 
 
61605 break;
61606 }
61607 #endif /* SQLITE_OMIT_CAST */
61608
61609 /* Opcode: ToInt P1 * * * *
@@ -61667,11 +61615,10 @@
61615 **
61616 ** A NULL value is not changed by this routine. It remains NULL.
61617 */
61618 case OP_ToInt: { /* same as TK_TO_INT, in1 */
61619 pIn1 = &aMem[pOp->p1];
 
61620 if( (pIn1->flags & MEM_Null)==0 ){
61621 sqlite3VdbeMemIntegerify(pIn1);
61622 }
61623 break;
61624 }
@@ -61781,12 +61728,10 @@
61728 u16 flags3; /* Copy of initial value of pIn3->flags */
61729 #endif /* local variables moved into u.ai */
61730
61731 pIn1 = &aMem[pOp->p1];
61732 pIn3 = &aMem[pOp->p3];
 
 
61733 u.ai.flags1 = pIn1->flags;
61734 u.ai.flags3 = pIn3->flags;
61735 if( (pIn1->flags | pIn3->flags)&MEM_Null ){
61736 /* One or both operands are NULL */
61737 if( pOp->p5 & SQLITE_NULLEQ ){
@@ -62415,11 +62360,10 @@
62360 assert( u.an.zAffinity[pOp->p2]==0 );
62361 pIn1 = &aMem[pOp->p1];
62362 while( (u.an.cAff = *(u.an.zAffinity++))!=0 ){
62363 assert( pIn1 <= &p->aMem[p->nMem] );
62364 assert( memIsValid(pIn1) );
 
62365 ExpandBlob(pIn1);
62366 applyAffinity(pIn1, u.an.cAff, encoding);
62367 pIn1++;
62368 }
62369 break;
@@ -62495,11 +62439,10 @@
62439 ** out how much space is required for the new record.
62440 */
62441 for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){
62442 assert( memIsValid(u.ao.pRec) );
62443 if( u.ao.zAffinity ){
 
62444 applyAffinity(u.ao.pRec, u.ao.zAffinity[u.ao.pRec-u.ao.pData0], encoding);
62445 }
62446 if( u.ao.pRec->flags&MEM_Zero && u.ao.pRec->n>0 ){
62447 sqlite3VdbeMemExpandBlob(u.ao.pRec);
62448 }
@@ -68880,11 +68823,11 @@
68823 pExpr->iColumn = (ynVar)(++pParse->nVar);
68824 }else if( z[0]=='?' ){
68825 /* Wildcard of the form "?nnn". Convert "nnn" to an integer and
68826 ** use it as the variable number */
68827 i64 i;
68828 int bOk = 0==sqlite3Atoi64(&z[1], &i, sqlite3Strlen30(&z[1]), SQLITE_UTF8);
68829 pExpr->iColumn = (ynVar)i;
68830 testcase( i==0 );
68831 testcase( i==1 );
68832 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
68833 testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
@@ -70243,11 +70186,11 @@
70186 */
70187 static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
70188 if( ALWAYS(z!=0) ){
70189 double value;
70190 char *zV;
70191 sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
70192 assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
70193 if( negateFlag ) value = -value;
70194 zV = dup8bytes(v, (char*)&value);
70195 sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
70196 }
@@ -70257,28 +70200,27 @@
70200
70201 /*
70202 ** Generate an instruction that will put the integer describe by
70203 ** text z[0..n-1] into register iMem.
70204 **
70205 ** Expr.u.zToken is always UTF8 and zero-terminated.
 
 
70206 */
70207 static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
70208 Vdbe *v = pParse->pVdbe;
70209 if( pExpr->flags & EP_IntValue ){
70210 int i = pExpr->u.iValue;
70211 if( negFlag ) i = -i;
70212 sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
70213 }else{
70214 int c;
70215 i64 value;
70216 const char *z = pExpr->u.zToken;
70217 assert( z!=0 );
70218 c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
70219 if( c==0 || (c==2 && negFlag) ){
70220 char *zV;
70221 if( negFlag ){ value = -value; }
 
70222 zV = dup8bytes(v, (char*)&value);
70223 sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
70224 }else{
70225 #ifdef SQLITE_OMIT_FLOATING_POINT
70226 sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
@@ -79414,11 +79356,11 @@
79356 zBuf = sqlite3_mprintf("%.*f",n,r);
79357 if( zBuf==0 ){
79358 sqlite3_result_error_nomem(context);
79359 return;
79360 }
79361 sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
79362 sqlite3_free(zBuf);
79363 }
79364 sqlite3_result_double(context, r);
79365 }
79366 #endif
@@ -85472,11 +85414,11 @@
85414 */
85415 if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){
85416 Pager *pPager = sqlite3BtreePager(pDb->pBt);
85417 i64 iLimit = -2;
85418 if( zRight ){
85419 sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8);
85420 if( iLimit<-1 ) iLimit = -1;
85421 }
85422 iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
85423 returnSingleInt(pParse, "journal_size_limit", iLimit);
85424 }else
@@ -96380,11 +96322,12 @@
96322
96323 /*
96324 ** Required because bestIndex() is called by bestOrClauseIndex()
96325 */
96326 static void bestIndex(
96327 Parse*, WhereClause*, struct SrcList_item*,
96328 Bitmask, Bitmask, ExprList*, WhereCost*);
96329
96330 /*
96331 ** This routine attempts to find an scanning strategy that can be used
96332 ** to optimize an 'OR' expression that is part of a WHERE clause.
96333 **
@@ -96393,11 +96336,12 @@
96336 */
96337 static void bestOrClauseIndex(
96338 Parse *pParse, /* The parsing context */
96339 WhereClause *pWC, /* The WHERE clause */
96340 struct SrcList_item *pSrc, /* The FROM clause term to search */
96341 Bitmask notReady, /* Mask of cursors not available for indexing */
96342 Bitmask notValid, /* Cursors not available for any purpose */
96343 ExprList *pOrderBy, /* The ORDER BY clause */
96344 WhereCost *pCost /* Lowest cost query plan */
96345 ){
96346 #ifndef SQLITE_OMIT_OR_OPTIMIZATION
96347 const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
@@ -96429,19 +96373,19 @@
96373 WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
96374 (pOrTerm - pOrWC->a), (pTerm - pWC->a)
96375 ));
96376 if( pOrTerm->eOperator==WO_AND ){
96377 WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
96378 bestIndex(pParse, pAndWC, pSrc, notReady, notValid, 0, &sTermCost);
96379 }else if( pOrTerm->leftCursor==iCur ){
96380 WhereClause tempWC;
96381 tempWC.pParse = pWC->pParse;
96382 tempWC.pMaskSet = pWC->pMaskSet;
96383 tempWC.op = TK_AND;
96384 tempWC.a = pOrTerm;
96385 tempWC.nTerm = 1;
96386 bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost);
96387 }else{
96388 continue;
96389 }
96390 rTotal += sTermCost.rCost;
96391 nRow += sTermCost.nRow;
@@ -96884,11 +96828,12 @@
96828 */
96829 static void bestVirtualIndex(
96830 Parse *pParse, /* The parsing context */
96831 WhereClause *pWC, /* The WHERE clause */
96832 struct SrcList_item *pSrc, /* The FROM clause term to search */
96833 Bitmask notReady, /* Mask of cursors not available for index */
96834 Bitmask notValid, /* Cursors not valid for any purpose */
96835 ExprList *pOrderBy, /* The order by clause */
96836 WhereCost *pCost, /* Lowest cost query plan */
96837 sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
96838 ){
96839 Table *pTab = pSrc->pTab;
@@ -97014,11 +96959,11 @@
96959 pIdxInfo->nOrderBy = nOrderBy;
96960
96961 /* Try to find a more efficient access pattern by using multiple indexes
96962 ** to optimize an OR expression within the WHERE clause.
96963 */
96964 bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
96965 }
96966 #endif /* SQLITE_OMIT_VIRTUALTABLE */
96967
96968 /*
96969 ** Argument pIdx is a pointer to an index structure that has an array of
@@ -97295,11 +97240,12 @@
97240 */
97241 static void bestBtreeIndex(
97242 Parse *pParse, /* The parsing context */
97243 WhereClause *pWC, /* The WHERE clause */
97244 struct SrcList_item *pSrc, /* The FROM clause term to search */
97245 Bitmask notReady, /* Mask of cursors not available for indexing */
97246 Bitmask notValid, /* Cursors not available for any purpose */
97247 ExprList *pOrderBy, /* The ORDER BY clause */
97248 WhereCost *pCost /* Lowest cost query plan */
97249 ){
97250 int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
97251 Index *pProbe; /* An index we are evaluating */
@@ -97557,29 +97503,29 @@
97503 ** of output rows, adjust the nRow value accordingly. This only
97504 ** matters if the current index is the least costly, so do not bother
97505 ** with this step if we already know this index will not be chosen.
97506 ** Also, never reduce the output row count below 2 using this step.
97507 **
97508 ** It is critical that the notValid mask be used here instead of
97509 ** the notReady mask. When computing an "optimal" index, the notReady
97510 ** mask will only have one bit set - the bit for the current table.
97511 ** The notValid mask, on the other hand, always has all bits set for
97512 ** tables that are not in outer loops. If notReady is used here instead
97513 ** of notValid, then a optimal index that depends on inner joins loops
97514 ** might be selected even when there exists an optimal index that has
97515 ** no such dependency.
97516 */
97517 if( nRow>2 && cost<=pCost->rCost ){
97518 int k; /* Loop counter */
97519 int nSkipEq = nEq; /* Number of == constraints to skip */
97520 int nSkipRange = nBound; /* Number of < constraints to skip */
97521 Bitmask thisTab; /* Bitmap for pSrc */
97522
97523 thisTab = getMask(pWC->pMaskSet, iCur);
97524 for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){
97525 if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
97526 if( (pTerm->prereqAll & notValid)!=thisTab ) continue;
97527 if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
97528 if( nSkipEq ){
97529 /* Ignore the first nEq equality matches since the index
97530 ** has already accounted for these */
97531 nSkipEq--;
@@ -97657,11 +97603,11 @@
97603 WHERETRACE(("best index is: %s\n",
97604 ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" :
97605 pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
97606 ));
97607
97608 bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
97609 bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost);
97610 pCost->plan.wsFlags |= eqTermMask;
97611 }
97612
97613 /*
@@ -97672,26 +97618,27 @@
97618 */
97619 static void bestIndex(
97620 Parse *pParse, /* The parsing context */
97621 WhereClause *pWC, /* The WHERE clause */
97622 struct SrcList_item *pSrc, /* The FROM clause term to search */
97623 Bitmask notReady, /* Mask of cursors not available for indexing */
97624 Bitmask notValid, /* Cursors not available for any purpose */
97625 ExprList *pOrderBy, /* The ORDER BY clause */
97626 WhereCost *pCost /* Lowest cost query plan */
97627 ){
97628 #ifndef SQLITE_OMIT_VIRTUALTABLE
97629 if( IsVirtual(pSrc->pTab) ){
97630 sqlite3_index_info *p = 0;
97631 bestVirtualIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost,&p);
97632 if( p->needToFreeIdxStr ){
97633 sqlite3_free(p->idxStr);
97634 }
97635 sqlite3DbFree(pParse->db, p);
97636 }else
97637 #endif
97638 {
97639 bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
97640 }
97641 }
97642
97643 /*
97644 ** Disable a term in the WHERE clause. Except, do not disable the term
@@ -98902,14 +98849,20 @@
98849 ** by waiting for other tables to run first. This "optimal" test works
98850 ** by first assuming that the FROM clause is on the inner loop and finding
98851 ** its query plan, then checking to see if that query plan uses any
98852 ** other FROM clause terms that are notReady. If no notReady terms are
98853 ** used then the "optimal" query plan works.
98854 **
98855 ** Note that the WhereCost.nRow parameter for an optimal scan might
98856 ** not be as small as it would be if the table really were the innermost
98857 ** join. The nRow value can be reduced by WHERE clause constraints
98858 ** that do not use indices. But this nRow reduction only happens if the
98859 ** table really is the innermost join.
98860 **
98861 ** The second loop iteration is only performed if no optimal scan
98862 ** strategies were found by the first iteration. This second iteration
98863 ** is used to search for the lowest cost scan overall.
98864 **
98865 ** Previous versions of SQLite performed only the second iteration -
98866 ** the next outermost loop was always that with the lowest overall
98867 ** cost. However, this meant that SQLite could select the wrong plan
98868 ** for scripts such as the following:
@@ -98925,11 +98878,11 @@
98878 ** algorithm may choose to use t2 for the outer loop, which is a much
98879 ** costlier approach.
98880 */
98881 nUnconstrained = 0;
98882 notIndexed = 0;
98883 for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
98884 Bitmask mask; /* Mask of tables not yet ready */
98885 for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
98886 int doNotReorder; /* True if this table should not be reordered */
98887 WhereCost sCost; /* Cost information from best[Virtual]Index() */
98888 ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
@@ -98947,15 +98900,17 @@
98900
98901 assert( pTabItem->pTab );
98902 #ifndef SQLITE_OMIT_VIRTUALTABLE
98903 if( IsVirtual(pTabItem->pTab) ){
98904 sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
98905 bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
98906 &sCost, pp);
98907 }else
98908 #endif
98909 {
98910 bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
98911 &sCost);
98912 }
98913 assert( isOptimal || (sCost.used&notReady)==0 );
98914
98915 /* If an INDEXED BY clause is present, then the plan must use that
98916 ** index if it uses any index at all */
98917
+1 -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.3"
111111
#define SQLITE_VERSION_NUMBER 3007003
112
-#define SQLITE_SOURCE_ID "2010-09-29 23:09:23 1ef0dc9328f47506cb2dcd142150e96cb4755216"
112
+#define SQLITE_SOURCE_ID "2010-10-04 23:55:51 ece641eb8951c6314cedbdb3243f91cb199c3239"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
118118
--- 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.3"
111 #define SQLITE_VERSION_NUMBER 3007003
112 #define SQLITE_SOURCE_ID "2010-09-29 23:09:23 1ef0dc9328f47506cb2dcd142150e96cb4755216"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
--- 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.3"
111 #define SQLITE_VERSION_NUMBER 3007003
112 #define SQLITE_SOURCE_ID "2010-10-04 23:55:51 ece641eb8951c6314cedbdb3243f91cb199c3239"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
+1 -1
--- src/style.c
+++ src/style.c
@@ -198,11 +198,11 @@
198198
@ media="screen" />
199199
@ </head>
200200
@ <body>
201201
@ <div class="header">
202202
@ <div class="logo">
203
-@ <img src="$baseurl/logo" alt="logo">
203
+@ <img src="$baseurl/logo" alt="logo" />
204204
@ </div>
205205
@ <div class="title"><small>$<project_name></small><br />$<title></div>
206206
@ <div class="status"><th1>
207207
@ if {[info exists login]} {
208208
@ puts "Logged in as $login"
209209
--- src/style.c
+++ src/style.c
@@ -198,11 +198,11 @@
198 @ media="screen" />
199 @ </head>
200 @ <body>
201 @ <div class="header">
202 @ <div class="logo">
203 @ <img src="$baseurl/logo" alt="logo">
204 @ </div>
205 @ <div class="title"><small>$<project_name></small><br />$<title></div>
206 @ <div class="status"><th1>
207 @ if {[info exists login]} {
208 @ puts "Logged in as $login"
209
--- src/style.c
+++ src/style.c
@@ -198,11 +198,11 @@
198 @ media="screen" />
199 @ </head>
200 @ <body>
201 @ <div class="header">
202 @ <div class="logo">
203 @ <img src="$baseurl/logo" alt="logo" />
204 @ </div>
205 @ <div class="title"><small>$<project_name></small><br />$<title></div>
206 @ <div class="status"><th1>
207 @ if {[info exists login]} {
208 @ puts "Logged in as $login"
209
+16 -8
--- src/timeline.c
+++ src/timeline.c
@@ -165,11 +165,11 @@
165165
** 4. User
166166
** 5. True if is a leaf
167167
** 6. background color
168168
** 7. type ("ci", "w", "t")
169169
** 8. list of symbolic tags.
170
-** 9. tagid for ticket or wiki
170
+** 9. tagid for ticket or wiki or event
171171
** 10. Short comment to user for repeated tickets and wiki
172172
*/
173173
void www_print_timeline(
174174
Stmt *pQuery, /* Query to implement the timeline */
175175
int tmFlags, /* Flags controlling display behavior */
@@ -288,10 +288,12 @@
288288
@ <span class="timelineLeaf">Closed-Leaf:</span>
289289
}else{
290290
@ <span class="timelineLeaf">Leaf:</span>
291291
}
292292
}
293
+ }else if( zType[0]=='e' && tagid ){
294
+ hyperlink_to_event_tagid(tagid);
293295
}else if( (tmFlags & TIMELINE_ARTID)!=0 ){
294296
hyperlink_to_uuid(zUuid);
295297
}
296298
db_column_blob(pQuery, commentColumn, &comment);
297299
if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
@@ -639,11 +641,11 @@
639641
** p=RID artifact RID and up to COUNT parents and ancestors
640642
** d=RID artifact RID and up to COUNT descendants
641643
** t=TAGID show only check-ins with the given tagid
642644
** r=TAGID show check-ins related to tagid
643645
** u=USER only if belonging to this user
644
-** y=TYPE 'ci', 'w', 't'
646
+** y=TYPE 'ci', 'w', 't', 'e'
645647
** s=TEXT string search (comment and brief)
646648
** ng Suppress the graph if present
647649
**
648650
** p= and d= can appear individually or together. If either p= or d=
649651
** appear, then u=, y=, a=, and b= are ignored.
@@ -749,22 +751,22 @@
749751
}else{
750752
blob_appendf(&desc, " of check-in [%.10s]", zUuid);
751753
}
752754
}else{
753755
int n;
754
- const char *zEType = "event";
756
+ const char *zEType = "timeline item";
755757
char *zDate;
756758
char *zNEntry = mprintf("%d", nEntry);
757759
url_initialize(&url, "timeline");
758760
url_add_parameter(&url, "n", zNEntry);
759761
if( tagid>0 ){
760
- zType = "ci";
762
+ if( zType[0]!='e' ) zType = "ci";
761763
blob_appendf(&sql,
762764
"AND (EXISTS(SELECT 1 FROM tagxref"
763765
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
764766
765
- if( zBrName ){
767
+ if( zBrName && zType[0]=='c' ){
766768
/* The next two blob_appendf() calls add SQL that causes checkins that
767769
** are not part of the branch which are parents or childen of the branch
768770
** to be included in the report. This related check-ins are useful
769771
** in helping to visualize what has happened on a quiescent branch
770772
** that is infrequently merged with a much more activate branch.
@@ -781,10 +783,11 @@
781783
}
782784
blob_appendf(&sql, ")");
783785
}
784786
if( (zType[0]=='w' && !g.okRdWiki)
785787
|| (zType[0]=='t' && !g.okRdTkt)
788
+ || (zType[0]=='e' && !g.okRdWiki)
786789
|| (zType[0]=='c' && !g.okRead)
787790
){
788791
zType = "all";
789792
}
790793
if( zType[0]=='a' ){
@@ -794,11 +797,11 @@
794797
if( g.okRead ){
795798
blob_appendf(&sql, "%c'ci'", cSep);
796799
cSep = ',';
797800
}
798801
if( g.okRdWiki ){
799
- blob_appendf(&sql, "%c'w'", cSep);
802
+ blob_appendf(&sql, "%c'w','e'", cSep);
800803
cSep = ',';
801804
}
802805
if( g.okRdTkt ){
803806
blob_appendf(&sql, "%c't'", cSep);
804807
cSep = ',';
@@ -812,10 +815,12 @@
812815
zEType = "checkin";
813816
}else if( zType[0]=='w' ){
814817
zEType = "wiki edit";
815818
}else if( zType[0]=='t' ){
816819
zEType = "ticket change";
820
+ }else if( zType[0]=='e' ){
821
+ zEType = "event";
817822
}
818823
}
819824
if( zUser ){
820825
blob_appendf(&sql, " AND event.user=%Q", zUser);
821826
url_add_parameter(&url, "u", zUser);
@@ -926,16 +931,19 @@
926931
timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
927932
}
928933
if( zType[0]!='t' && g.okRdTkt ){
929934
timeline_submenu(&url, "Tickets Only", "y", "t", 0);
930935
}
936
+ if( zType[0]!='e' && g.okRdWiki ){
937
+ timeline_submenu(&url, "Events Only", "y", "e", 0);
938
+ }
931939
}
932940
if( nEntry>20 ){
933
- timeline_submenu(&url, "20 Events", "n", "20", 0);
941
+ timeline_submenu(&url, "20 Entries", "n", "20", 0);
934942
}
935943
if( nEntry<200 ){
936
- timeline_submenu(&url, "200 Events", "n", "200", 0);
944
+ timeline_submenu(&url, "200 Entries", "n", "200", 0);
937945
}
938946
}
939947
}
940948
blob_zero(&sql);
941949
db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC /*scan*/");
942950
--- src/timeline.c
+++ src/timeline.c
@@ -165,11 +165,11 @@
165 ** 4. User
166 ** 5. True if is a leaf
167 ** 6. background color
168 ** 7. type ("ci", "w", "t")
169 ** 8. list of symbolic tags.
170 ** 9. tagid for ticket or wiki
171 ** 10. Short comment to user for repeated tickets and wiki
172 */
173 void www_print_timeline(
174 Stmt *pQuery, /* Query to implement the timeline */
175 int tmFlags, /* Flags controlling display behavior */
@@ -288,10 +288,12 @@
288 @ <span class="timelineLeaf">Closed-Leaf:</span>
289 }else{
290 @ <span class="timelineLeaf">Leaf:</span>
291 }
292 }
 
 
293 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
294 hyperlink_to_uuid(zUuid);
295 }
296 db_column_blob(pQuery, commentColumn, &comment);
297 if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
@@ -639,11 +641,11 @@
639 ** p=RID artifact RID and up to COUNT parents and ancestors
640 ** d=RID artifact RID and up to COUNT descendants
641 ** t=TAGID show only check-ins with the given tagid
642 ** r=TAGID show check-ins related to tagid
643 ** u=USER only if belonging to this user
644 ** y=TYPE 'ci', 'w', 't'
645 ** s=TEXT string search (comment and brief)
646 ** ng Suppress the graph if present
647 **
648 ** p= and d= can appear individually or together. If either p= or d=
649 ** appear, then u=, y=, a=, and b= are ignored.
@@ -749,22 +751,22 @@
749 }else{
750 blob_appendf(&desc, " of check-in [%.10s]", zUuid);
751 }
752 }else{
753 int n;
754 const char *zEType = "event";
755 char *zDate;
756 char *zNEntry = mprintf("%d", nEntry);
757 url_initialize(&url, "timeline");
758 url_add_parameter(&url, "n", zNEntry);
759 if( tagid>0 ){
760 zType = "ci";
761 blob_appendf(&sql,
762 "AND (EXISTS(SELECT 1 FROM tagxref"
763 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
764
765 if( zBrName ){
766 /* The next two blob_appendf() calls add SQL that causes checkins that
767 ** are not part of the branch which are parents or childen of the branch
768 ** to be included in the report. This related check-ins are useful
769 ** in helping to visualize what has happened on a quiescent branch
770 ** that is infrequently merged with a much more activate branch.
@@ -781,10 +783,11 @@
781 }
782 blob_appendf(&sql, ")");
783 }
784 if( (zType[0]=='w' && !g.okRdWiki)
785 || (zType[0]=='t' && !g.okRdTkt)
 
786 || (zType[0]=='c' && !g.okRead)
787 ){
788 zType = "all";
789 }
790 if( zType[0]=='a' ){
@@ -794,11 +797,11 @@
794 if( g.okRead ){
795 blob_appendf(&sql, "%c'ci'", cSep);
796 cSep = ',';
797 }
798 if( g.okRdWiki ){
799 blob_appendf(&sql, "%c'w'", cSep);
800 cSep = ',';
801 }
802 if( g.okRdTkt ){
803 blob_appendf(&sql, "%c't'", cSep);
804 cSep = ',';
@@ -812,10 +815,12 @@
812 zEType = "checkin";
813 }else if( zType[0]=='w' ){
814 zEType = "wiki edit";
815 }else if( zType[0]=='t' ){
816 zEType = "ticket change";
 
 
817 }
818 }
819 if( zUser ){
820 blob_appendf(&sql, " AND event.user=%Q", zUser);
821 url_add_parameter(&url, "u", zUser);
@@ -926,16 +931,19 @@
926 timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
927 }
928 if( zType[0]!='t' && g.okRdTkt ){
929 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
930 }
 
 
 
931 }
932 if( nEntry>20 ){
933 timeline_submenu(&url, "20 Events", "n", "20", 0);
934 }
935 if( nEntry<200 ){
936 timeline_submenu(&url, "200 Events", "n", "200", 0);
937 }
938 }
939 }
940 blob_zero(&sql);
941 db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC /*scan*/");
942
--- src/timeline.c
+++ src/timeline.c
@@ -165,11 +165,11 @@
165 ** 4. User
166 ** 5. True if is a leaf
167 ** 6. background color
168 ** 7. type ("ci", "w", "t")
169 ** 8. list of symbolic tags.
170 ** 9. tagid for ticket or wiki or event
171 ** 10. Short comment to user for repeated tickets and wiki
172 */
173 void www_print_timeline(
174 Stmt *pQuery, /* Query to implement the timeline */
175 int tmFlags, /* Flags controlling display behavior */
@@ -288,10 +288,12 @@
288 @ <span class="timelineLeaf">Closed-Leaf:</span>
289 }else{
290 @ <span class="timelineLeaf">Leaf:</span>
291 }
292 }
293 }else if( zType[0]=='e' && tagid ){
294 hyperlink_to_event_tagid(tagid);
295 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
296 hyperlink_to_uuid(zUuid);
297 }
298 db_column_blob(pQuery, commentColumn, &comment);
299 if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
@@ -639,11 +641,11 @@
641 ** p=RID artifact RID and up to COUNT parents and ancestors
642 ** d=RID artifact RID and up to COUNT descendants
643 ** t=TAGID show only check-ins with the given tagid
644 ** r=TAGID show check-ins related to tagid
645 ** u=USER only if belonging to this user
646 ** y=TYPE 'ci', 'w', 't', 'e'
647 ** s=TEXT string search (comment and brief)
648 ** ng Suppress the graph if present
649 **
650 ** p= and d= can appear individually or together. If either p= or d=
651 ** appear, then u=, y=, a=, and b= are ignored.
@@ -749,22 +751,22 @@
751 }else{
752 blob_appendf(&desc, " of check-in [%.10s]", zUuid);
753 }
754 }else{
755 int n;
756 const char *zEType = "timeline item";
757 char *zDate;
758 char *zNEntry = mprintf("%d", nEntry);
759 url_initialize(&url, "timeline");
760 url_add_parameter(&url, "n", zNEntry);
761 if( tagid>0 ){
762 if( zType[0]!='e' ) zType = "ci";
763 blob_appendf(&sql,
764 "AND (EXISTS(SELECT 1 FROM tagxref"
765 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
766
767 if( zBrName && zType[0]=='c' ){
768 /* The next two blob_appendf() calls add SQL that causes checkins that
769 ** are not part of the branch which are parents or childen of the branch
770 ** to be included in the report. This related check-ins are useful
771 ** in helping to visualize what has happened on a quiescent branch
772 ** that is infrequently merged with a much more activate branch.
@@ -781,10 +783,11 @@
783 }
784 blob_appendf(&sql, ")");
785 }
786 if( (zType[0]=='w' && !g.okRdWiki)
787 || (zType[0]=='t' && !g.okRdTkt)
788 || (zType[0]=='e' && !g.okRdWiki)
789 || (zType[0]=='c' && !g.okRead)
790 ){
791 zType = "all";
792 }
793 if( zType[0]=='a' ){
@@ -794,11 +797,11 @@
797 if( g.okRead ){
798 blob_appendf(&sql, "%c'ci'", cSep);
799 cSep = ',';
800 }
801 if( g.okRdWiki ){
802 blob_appendf(&sql, "%c'w','e'", cSep);
803 cSep = ',';
804 }
805 if( g.okRdTkt ){
806 blob_appendf(&sql, "%c't'", cSep);
807 cSep = ',';
@@ -812,10 +815,12 @@
815 zEType = "checkin";
816 }else if( zType[0]=='w' ){
817 zEType = "wiki edit";
818 }else if( zType[0]=='t' ){
819 zEType = "ticket change";
820 }else if( zType[0]=='e' ){
821 zEType = "event";
822 }
823 }
824 if( zUser ){
825 blob_appendf(&sql, " AND event.user=%Q", zUser);
826 url_add_parameter(&url, "u", zUser);
@@ -926,16 +931,19 @@
931 timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
932 }
933 if( zType[0]!='t' && g.okRdTkt ){
934 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
935 }
936 if( zType[0]!='e' && g.okRdWiki ){
937 timeline_submenu(&url, "Events Only", "y", "e", 0);
938 }
939 }
940 if( nEntry>20 ){
941 timeline_submenu(&url, "20 Entries", "n", "20", 0);
942 }
943 if( nEntry<200 ){
944 timeline_submenu(&url, "200 Entries", "n", "200", 0);
945 }
946 }
947 }
948 blob_zero(&sql);
949 db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC /*scan*/");
950
+7 -3
--- src/wiki.c
+++ src/wiki.c
@@ -106,11 +106,11 @@
106106
@ <p>This is a stub home-page for the project.
107107
@ To fill in this page, first go to
108108
@ <a href="%s(g.zBaseURL)/setup_config">setup/config</a>
109109
@ and establish a "Project Name". Then create a
110110
@ wiki page with that name. The content of that wiki page
111
- @ will be displayed in place of this message.
111
+ @ will be displayed in place of this message.</p>
112112
style_footer();
113113
}
114114
115115
/*
116116
** Return true if the given pagename is the name of the sandbox
@@ -153,10 +153,13 @@
153153
@ wiki.</li>
154154
@ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a>
155155
@ to experiment.</li>
156156
if( g.okNewWiki ){
157157
@ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li>
158
+ if( g.okWrite ){
159
+ @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li>
160
+ }
158161
}
159162
@ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a>
160163
@ available on this server.</li>
161164
@ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div>
162165
@ Search wiki titles: <input type="text" name="title"/>
@@ -223,16 +226,16 @@
223226
while( db_step(&q)==SQLITE_ROW ){
224227
const char *zDate = db_column_text(&q, 0);
225228
const char *zFile = db_column_text(&q, 1);
226229
const char *zUser = db_column_text(&q, 2);
227230
if( cnt==0 ){
228
- @ <hr><h2>Attachments:</h2>
231
+ @ <hr /><h2>Attachments:</h2>
229232
@ <ul>
230233
}
231234
cnt++;
235
+ @ <li>
232236
if( g.okHistory && g.okRead ){
233
- @ <li>
234237
@ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
235238
@ %h(zFile)</a>
236239
}else{
237240
@ <li>%h(zFile)
238241
}
@@ -239,10 +242,11 @@
239242
@ added by %h(zUser) on
240243
hyperlink_to_date(zDate, ".");
241244
if( g.okWrWiki && g.okAttach ){
242245
@ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
243246
}
247
+ @ </li>
244248
}
245249
if( cnt ){
246250
@ </ul>
247251
}
248252
db_finalize(&q);
249253
--- src/wiki.c
+++ src/wiki.c
@@ -106,11 +106,11 @@
106 @ <p>This is a stub home-page for the project.
107 @ To fill in this page, first go to
108 @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a>
109 @ and establish a "Project Name". Then create a
110 @ wiki page with that name. The content of that wiki page
111 @ will be displayed in place of this message.
112 style_footer();
113 }
114
115 /*
116 ** Return true if the given pagename is the name of the sandbox
@@ -153,10 +153,13 @@
153 @ wiki.</li>
154 @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a>
155 @ to experiment.</li>
156 if( g.okNewWiki ){
157 @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li>
 
 
 
158 }
159 @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a>
160 @ available on this server.</li>
161 @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div>
162 @ Search wiki titles: <input type="text" name="title"/>
@@ -223,16 +226,16 @@
223 while( db_step(&q)==SQLITE_ROW ){
224 const char *zDate = db_column_text(&q, 0);
225 const char *zFile = db_column_text(&q, 1);
226 const char *zUser = db_column_text(&q, 2);
227 if( cnt==0 ){
228 @ <hr><h2>Attachments:</h2>
229 @ <ul>
230 }
231 cnt++;
 
232 if( g.okHistory && g.okRead ){
233 @ <li>
234 @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
235 @ %h(zFile)</a>
236 }else{
237 @ <li>%h(zFile)
238 }
@@ -239,10 +242,11 @@
239 @ added by %h(zUser) on
240 hyperlink_to_date(zDate, ".");
241 if( g.okWrWiki && g.okAttach ){
242 @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
243 }
 
244 }
245 if( cnt ){
246 @ </ul>
247 }
248 db_finalize(&q);
249
--- src/wiki.c
+++ src/wiki.c
@@ -106,11 +106,11 @@
106 @ <p>This is a stub home-page for the project.
107 @ To fill in this page, first go to
108 @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a>
109 @ and establish a "Project Name". Then create a
110 @ wiki page with that name. The content of that wiki page
111 @ will be displayed in place of this message.</p>
112 style_footer();
113 }
114
115 /*
116 ** Return true if the given pagename is the name of the sandbox
@@ -153,10 +153,13 @@
153 @ wiki.</li>
154 @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a>
155 @ to experiment.</li>
156 if( g.okNewWiki ){
157 @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li>
158 if( g.okWrite ){
159 @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li>
160 }
161 }
162 @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a>
163 @ available on this server.</li>
164 @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div>
165 @ Search wiki titles: <input type="text" name="title"/>
@@ -223,16 +226,16 @@
226 while( db_step(&q)==SQLITE_ROW ){
227 const char *zDate = db_column_text(&q, 0);
228 const char *zFile = db_column_text(&q, 1);
229 const char *zUser = db_column_text(&q, 2);
230 if( cnt==0 ){
231 @ <hr /><h2>Attachments:</h2>
232 @ <ul>
233 }
234 cnt++;
235 @ <li>
236 if( g.okHistory && g.okRead ){
 
237 @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
238 @ %h(zFile)</a>
239 }else{
240 @ <li>%h(zFile)
241 }
@@ -239,10 +242,11 @@
242 @ added by %h(zUser) on
243 hyperlink_to_date(zDate, ".");
244 if( g.okWrWiki && g.okAttach ){
245 @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
246 }
247 @ </li>
248 }
249 if( cnt ){
250 @ </ul>
251 }
252 db_finalize(&q);
253
+4 -2
--- src/xfer.c
+++ src/xfer.c
@@ -119,22 +119,24 @@
119119
if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
120120
/* Ignore files that have been shunned */
121121
return;
122122
}
123123
if( pXfer->nToken==4 ){
124
- Blob src;
124
+ Blob src, next;
125125
srcid = rid_from_uuid(&pXfer->aToken[2], 1);
126126
if( content_get(srcid, &src)==0 ){
127127
rid = content_put(&content, blob_str(&pXfer->aToken[1]), srcid);
128128
pXfer->nDanglingFile++;
129129
db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
130130
content_make_public(rid);
131131
return;
132132
}
133133
pXfer->nDeltaRcvd++;
134
- blob_delta_apply(&src, &content, &content);
134
+ blob_delta_apply(&src, &content, &next);
135135
blob_reset(&src);
136
+ blob_reset(&content);
137
+ content = next;
136138
}else{
137139
pXfer->nFileRcvd++;
138140
}
139141
sha1sum_blob(&content, &hash);
140142
if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){
141143
--- src/xfer.c
+++ src/xfer.c
@@ -119,22 +119,24 @@
119 if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
120 /* Ignore files that have been shunned */
121 return;
122 }
123 if( pXfer->nToken==4 ){
124 Blob src;
125 srcid = rid_from_uuid(&pXfer->aToken[2], 1);
126 if( content_get(srcid, &src)==0 ){
127 rid = content_put(&content, blob_str(&pXfer->aToken[1]), srcid);
128 pXfer->nDanglingFile++;
129 db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
130 content_make_public(rid);
131 return;
132 }
133 pXfer->nDeltaRcvd++;
134 blob_delta_apply(&src, &content, &content);
135 blob_reset(&src);
 
 
136 }else{
137 pXfer->nFileRcvd++;
138 }
139 sha1sum_blob(&content, &hash);
140 if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){
141
--- src/xfer.c
+++ src/xfer.c
@@ -119,22 +119,24 @@
119 if( uuid_is_shunned(blob_str(&pXfer->aToken[1])) ){
120 /* Ignore files that have been shunned */
121 return;
122 }
123 if( pXfer->nToken==4 ){
124 Blob src, next;
125 srcid = rid_from_uuid(&pXfer->aToken[2], 1);
126 if( content_get(srcid, &src)==0 ){
127 rid = content_put(&content, blob_str(&pXfer->aToken[1]), srcid);
128 pXfer->nDanglingFile++;
129 db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
130 content_make_public(rid);
131 return;
132 }
133 pXfer->nDeltaRcvd++;
134 blob_delta_apply(&src, &content, &next);
135 blob_reset(&src);
136 blob_reset(&content);
137 content = next;
138 }else{
139 pXfer->nFileRcvd++;
140 }
141 sha1sum_blob(&content, &hash);
142 if( !blob_eq_str(&pXfer->aToken[1], blob_str(&hash), -1) ){
143
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -60,11 +60,11 @@
6060
INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
6161
6262
UTILS=translate.exe mkindex.exe makeheaders.exe
6363
UTILS_OBJ=$(UTILS:.exe=.obj)
6464
65
-SRC=add.c allrepo.c attach.c bag.c blob.c branch.c browse.c captcha.c cgi.c checkin.c checkout.c clearsign.c clone.c comformat.c configure.c content.c db.c delta.c deltacmd.c descendants.c diff.c diffcmd.c doc.c encode.c file.c finfo.c graph.c http.c http_socket.c http_ssl.c http_transport.c info.c login.c main.c manifest.c md5.c merge.c merge3.c name.c pivot.c popen.c pqueue.c printf.c rebuild.c report.c rss.c schema.c search.c setup.c sha1.c shun.c skins.c stat.c style.c sync.c tag.c th_main.c timeline.c tkt.c tktsetup.c undo.c update.c url.c user.c verify.c vfile.c wiki.c wikiformat.c winhttp.c xfer.c zip.c
65
+SRC=add.c allrepo.c attach.c bag.c blob.c branch.c browse.c captcha.c cgi.c checkin.c checkout.c clearsign.c clone.c comformat.c configure.c content.c db.c delta.c deltacmd.c descendants.c diff.c diffcmd.c doc.c encode.c event.c file.c finfo.c graph.c http.c http_socket.c http_ssl.c http_transport.c info.c login.c main.c manifest.c md5.c merge.c merge3.c name.c pivot.c popen.c pqueue.c printf.c rebuild.c report.c rss.c schema.c search.c setup.c sha1.c shun.c skins.c stat.c style.c sync.c tag.c th_main.c timeline.c tkt.c tktsetup.c undo.c update.c url.c user.c verify.c vfile.c wiki.c wikiformat.c winhttp.c xfer.c zip.c
6666
ORIGSRC=$(foreach sf,$(SRC),$(SRCDIR)$(sf))
6767
TRANSLATEDSRC=$(SRC:.c=_.c)
6868
TRANSLATEDOBJ=$(TRANSLATEDSRC:.c=.obj)
6969
7070
SQLITESRC=sqlite3.c
7171
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -60,11 +60,11 @@
60 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
61
62 UTILS=translate.exe mkindex.exe makeheaders.exe
63 UTILS_OBJ=$(UTILS:.exe=.obj)
64
65 SRC=add.c allrepo.c attach.c bag.c blob.c branch.c browse.c captcha.c cgi.c checkin.c checkout.c clearsign.c clone.c comformat.c configure.c content.c db.c delta.c deltacmd.c descendants.c diff.c diffcmd.c doc.c encode.c file.c finfo.c graph.c http.c http_socket.c http_ssl.c http_transport.c info.c login.c main.c manifest.c md5.c merge.c merge3.c name.c pivot.c popen.c pqueue.c printf.c rebuild.c report.c rss.c schema.c search.c setup.c sha1.c shun.c skins.c stat.c style.c sync.c tag.c th_main.c timeline.c tkt.c tktsetup.c undo.c update.c url.c user.c verify.c vfile.c wiki.c wikiformat.c winhttp.c xfer.c zip.c
66 ORIGSRC=$(foreach sf,$(SRC),$(SRCDIR)$(sf))
67 TRANSLATEDSRC=$(SRC:.c=_.c)
68 TRANSLATEDOBJ=$(TRANSLATEDSRC:.c=.obj)
69
70 SQLITESRC=sqlite3.c
71
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -60,11 +60,11 @@
60 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
61
62 UTILS=translate.exe mkindex.exe makeheaders.exe
63 UTILS_OBJ=$(UTILS:.exe=.obj)
64
65 SRC=add.c allrepo.c attach.c bag.c blob.c branch.c browse.c captcha.c cgi.c checkin.c checkout.c clearsign.c clone.c comformat.c configure.c content.c db.c delta.c deltacmd.c descendants.c diff.c diffcmd.c doc.c encode.c event.c file.c finfo.c graph.c http.c http_socket.c http_ssl.c http_transport.c info.c login.c main.c manifest.c md5.c merge.c merge3.c name.c pivot.c popen.c pqueue.c printf.c rebuild.c report.c rss.c schema.c search.c setup.c sha1.c shun.c skins.c stat.c style.c sync.c tag.c th_main.c timeline.c tkt.c tktsetup.c undo.c update.c url.c user.c verify.c vfile.c wiki.c wikiformat.c winhttp.c xfer.c zip.c
66 ORIGSRC=$(foreach sf,$(SRC),$(SRCDIR)$(sf))
67 TRANSLATEDSRC=$(SRC:.c=_.c)
68 TRANSLATEDOBJ=$(TRANSLATEDSRC:.c=.obj)
69
70 SQLITESRC=sqlite3.c
71
+10 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
2424
CFLAGS = -o
2525
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32
2828
29
-SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
29
+SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
3030
31
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
31
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3232
3333
3434
APPNAME = $(OBJDIR)\fossil$(E)
3535
3636
all: $(APPNAME)
@@ -38,11 +38,11 @@
3838
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\link
3939
cd $(OBJDIR)
4040
$(DMDIR)\bin\link @link
4141
4242
$(OBJDIR)\link: $B\win\Makefile.dmc
43
- +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
43
+ +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
4444
+echo fossil >> $@
4545
+echo fossil >> $@
4646
+echo $(LIBS) >> $@
4747
4848
@@ -217,10 +217,16 @@
217217
$(OBJDIR)\doc$O : doc_.c doc.h
218218
$(TCC) -o$@ -c doc_.c
219219
220220
doc_.c : $(SRCDIR)\doc.c
221221
+translate$E $** > $@
222
+
223
+$(OBJDIR)\event$O : event_.c event.h
224
+ $(TCC) -o$@ -c event_.c
225
+
226
+event_.c : $(SRCDIR)\event.c
227
+ +translate$E $** > $@
222228
223229
$(OBJDIR)\encode$O : encode_.c encode.h
224230
$(TCC) -o$@ -c encode_.c
225231
226232
encode_.c : $(SRCDIR)\encode.c
@@ -507,7 +513,7 @@
507513
508514
zip_.c : $(SRCDIR)\zip.c
509515
+translate$E $** > $@
510516
511517
headers: makeheaders$E page_index.h VERSION.h
512
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
518
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
513519
@copy /Y nul: headers
514520
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
28
29 SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
30
31 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
32
33
34 APPNAME = $(OBJDIR)\fossil$(E)
35
36 all: $(APPNAME)
@@ -38,11 +38,11 @@
38 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\link
39 cd $(OBJDIR)
40 $(DMDIR)\bin\link @link
41
42 $(OBJDIR)\link: $B\win\Makefile.dmc
43 +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
44 +echo fossil >> $@
45 +echo fossil >> $@
46 +echo $(LIBS) >> $@
47
48
@@ -217,10 +217,16 @@
217 $(OBJDIR)\doc$O : doc_.c doc.h
218 $(TCC) -o$@ -c doc_.c
219
220 doc_.c : $(SRCDIR)\doc.c
221 +translate$E $** > $@
 
 
 
 
 
 
222
223 $(OBJDIR)\encode$O : encode_.c encode.h
224 $(TCC) -o$@ -c encode_.c
225
226 encode_.c : $(SRCDIR)\encode.c
@@ -507,7 +513,7 @@
507
508 zip_.c : $(SRCDIR)\zip.c
509 +translate$E $** > $@
510
511 headers: makeheaders$E page_index.h VERSION.h
512 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
513 @copy /Y nul: headers
514
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
28
29 SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
30
31 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
32
33
34 APPNAME = $(OBJDIR)\fossil$(E)
35
36 all: $(APPNAME)
@@ -38,11 +38,11 @@
38 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\link
39 cd $(OBJDIR)
40 $(DMDIR)\bin\link @link
41
42 $(OBJDIR)\link: $B\win\Makefile.dmc
43 +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
44 +echo fossil >> $@
45 +echo fossil >> $@
46 +echo $(LIBS) >> $@
47
48
@@ -217,10 +217,16 @@
217 $(OBJDIR)\doc$O : doc_.c doc.h
218 $(TCC) -o$@ -c doc_.c
219
220 doc_.c : $(SRCDIR)\doc.c
221 +translate$E $** > $@
222
223 $(OBJDIR)\event$O : event_.c event.h
224 $(TCC) -o$@ -c event_.c
225
226 event_.c : $(SRCDIR)\event.c
227 +translate$E $** > $@
228
229 $(OBJDIR)\encode$O : encode_.c encode.h
230 $(TCC) -o$@ -c encode_.c
231
232 encode_.c : $(SRCDIR)\encode.c
@@ -507,7 +513,7 @@
513
514 zip_.c : $(SRCDIR)\zip.c
515 +translate$E $** > $@
516
517 headers: makeheaders$E page_index.h VERSION.h
518 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
519 @copy /Y nul: headers
520
+10 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
2424
CFLAGS = -o
2525
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32
2828
29
-SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
29
+SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
3030
31
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
31
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3232
3333
3434
APPNAME = $(OBJDIR)\fossil$(E)
3535
3636
all: $(APPNAME)
@@ -38,11 +38,11 @@
3838
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\link
3939
cd $(OBJDIR)
4040
$(DMDIR)\bin\link @link
4141
4242
$(OBJDIR)\link: $B\win\Makefile.dmc
43
- +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
43
+ +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
4444
+echo fossil >> $@
4545
+echo fossil >> $@
4646
+echo $(LIBS) >> $@
4747
4848
@@ -217,10 +217,16 @@
217217
$(OBJDIR)\doc$O : doc_.c doc.h
218218
$(TCC) -o$@ -c doc_.c
219219
220220
doc_.c : $(SRCDIR)\doc.c
221221
+translate$E $** > $@
222
+
223
+$(OBJDIR)\event$O : event_.c event.h
224
+ $(TCC) -o$@ -c event_.c
225
+
226
+event_.c : $(SRCDIR)\event.c
227
+ +translate$E $** > $@
222228
223229
$(OBJDIR)\encode$O : encode_.c encode.h
224230
$(TCC) -o$@ -c encode_.c
225231
226232
encode_.c : $(SRCDIR)\encode.c
@@ -507,7 +513,7 @@
507513
508514
zip_.c : $(SRCDIR)\zip.c
509515
+translate$E $** > $@
510516
511517
headers: makeheaders$E page_index.h VERSION.h
512
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
518
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
513519
@copy /Y nul: headers
514520
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
28
29 SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
30
31 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
32
33
34 APPNAME = $(OBJDIR)\fossil$(E)
35
36 all: $(APPNAME)
@@ -38,11 +38,11 @@
38 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\link
39 cd $(OBJDIR)
40 $(DMDIR)\bin\link @link
41
42 $(OBJDIR)\link: $B\win\Makefile.dmc
43 +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
44 +echo fossil >> $@
45 +echo fossil >> $@
46 +echo $(LIBS) >> $@
47
48
@@ -217,10 +217,16 @@
217 $(OBJDIR)\doc$O : doc_.c doc.h
218 $(TCC) -o$@ -c doc_.c
219
220 doc_.c : $(SRCDIR)\doc.c
221 +translate$E $** > $@
 
 
 
 
 
 
222
223 $(OBJDIR)\encode$O : encode_.c encode.h
224 $(TCC) -o$@ -c encode_.c
225
226 encode_.c : $(SRCDIR)\encode.c
@@ -507,7 +513,7 @@
507
508 zip_.c : $(SRCDIR)\zip.c
509 +translate$E $** > $@
510
511 headers: makeheaders$E page_index.h VERSION.h
512 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
513 @copy /Y nul: headers
514
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
28
29 SRC = add_.c allrepo_.c attach_.c bag_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c file_.c finfo_.c graph_.c http_.c http_socket_.c http_ssl_.c http_transport_.c info_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c stat_.c style_.c sync_.c tag_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
30
31 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\info$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
32
33
34 APPNAME = $(OBJDIR)\fossil$(E)
35
36 all: $(APPNAME)
@@ -38,11 +38,11 @@
38 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OBJDIR)\link
39 cd $(OBJDIR)
40 $(DMDIR)\bin\link @link
41
42 $(OBJDIR)\link: $B\win\Makefile.dmc
43 +echo add allrepo attach bag blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event file finfo graph http http_socket http_ssl http_transport info login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins stat style sync tag th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
44 +echo fossil >> $@
45 +echo fossil >> $@
46 +echo $(LIBS) >> $@
47
48
@@ -217,10 +217,16 @@
217 $(OBJDIR)\doc$O : doc_.c doc.h
218 $(TCC) -o$@ -c doc_.c
219
220 doc_.c : $(SRCDIR)\doc.c
221 +translate$E $** > $@
222
223 $(OBJDIR)\event$O : event_.c event.h
224 $(TCC) -o$@ -c event_.c
225
226 event_.c : $(SRCDIR)\event.c
227 +translate$E $** > $@
228
229 $(OBJDIR)\encode$O : encode_.c encode.h
230 $(TCC) -o$@ -c encode_.c
231
232 encode_.c : $(SRCDIR)\encode.c
@@ -507,7 +513,7 @@
513
514 zip_.c : $(SRCDIR)\zip.c
515 +translate$E $** > $@
516
517 headers: makeheaders$E page_index.h VERSION.h
518 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
519 @copy /Y nul: headers
520
--- www/branching.wiki
+++ www/branching.wiki
@@ -155,10 +155,11 @@
155155
accident that stems from concurrent development. In figure 4, giving
156156
check-in 2 multiple children is a deliberate act. So, to a good
157157
approximation, we define forking to be by accident and branching to
158158
be by intent. Apart from that, they are the same.
159159
160
+<a name="tags"></a>
160161
<h2>Tags And Properties</h2>
161162
162163
Tags and properties are used in fossil to help express the intent, and
163164
thus to distinguish between forks and branches. Figure 5 shows the
164165
same scenario as figure 4 but with tags and properties added:
165166
166167
ADDED www/event.wiki
--- www/branching.wiki
+++ www/branching.wiki
@@ -155,10 +155,11 @@
155 accident that stems from concurrent development. In figure 4, giving
156 check-in 2 multiple children is a deliberate act. So, to a good
157 approximation, we define forking to be by accident and branching to
158 be by intent. Apart from that, they are the same.
159
 
160 <h2>Tags And Properties</h2>
161
162 Tags and properties are used in fossil to help express the intent, and
163 thus to distinguish between forks and branches. Figure 5 shows the
164 same scenario as figure 4 but with tags and properties added:
165
166 DDED www/event.wiki
--- www/branching.wiki
+++ www/branching.wiki
@@ -155,10 +155,11 @@
155 accident that stems from concurrent development. In figure 4, giving
156 check-in 2 multiple children is a deliberate act. So, to a good
157 approximation, we define forking to be by accident and branching to
158 be by intent. Apart from that, they are the same.
159
160 <a name="tags"></a>
161 <h2>Tags And Properties</h2>
162
163 Tags and properties are used in fossil to help express the intent, and
164 thus to distinguish between forks and branches. Figure 5 shows the
165 same scenario as figure 4 but with tags and properties added:
166
167 DDED www/event.wiki
--- a/www/event.wiki
+++ b/www/event.wiki
@@ -0,0 +1,35 @@
1
+<title>Eventes</title>
2
+
3
+<h2>What Is A "Event"?</h2>e?y=<titl
4
+Possible uses for technotes include:
5
+
6
+ * <b>Milestones</b>. Project milestones, such as releases or beta-test
7
+ cycles, can be recorded as technotes. The timeline entry for the technote
8
+ can be something simple like "Version 1.2.3" perhaps with a bright
9
+ color background to draw attention to the entry and the wiki content
10
+ can contain release notes, for example.
11
+
12
+ * <b>Blog Entries</b>. Blog entries from developers describing the current
13
+ state of a project, or rational for v arious design decisions, or
14
+ roadmaps for future development, can be entered as technotes.
15
+
16
+ * <b>Process Checkpoints</b>. For projects that have a formal process,
17
+ technotes can be used to record the completion or the initiation of
18
+ various process steps. For example, a technote can be used to record
19
+ the successful completion of a long-running test, perhaps w[./wikitheory.wiki | wiki page]
20
+that is associated with a point in time rather thaevent causes a si [/timelinhyperlink ofTimeline Page]entry cause a jump to the wiThe wiki content, the timeline entry text, the
21
+time of the eventTechnical Notes</title>
22
+
23
+<h2>What Is A "Technote"?</h2>
24
+
25
+In Fossil, a "technical note" or "technoteventerly called an "event")
26
+is a speeventiki page]
27
+that is associated with a point in time rather than having a page name.
28
+eventaving a page name.
29
+Each technote causes a single entry to appear on the
30
+[/timeline?y=<titl
31
+Possible uses for technotes include:
32
+
33
+ * <b>Milestones</b>. Project milestones, such as releases or beta-test
34
+ cycles, can be recorded as technotes. The timeline entry for the technote
35
+ can be something simple like "V
--- a/www/event.wiki
+++ b/www/event.wiki
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/event.wiki
+++ b/www/event.wiki
@@ -0,0 +1,35 @@
1 <title>Eventes</title>
2
3 <h2>What Is A "Event"?</h2>e?y=<titl
4 Possible uses for technotes include:
5
6 * <b>Milestones</b>. Project milestones, such as releases or beta-test
7 cycles, can be recorded as technotes. The timeline entry for the technote
8 can be something simple like "Version 1.2.3" perhaps with a bright
9 color background to draw attention to the entry and the wiki content
10 can contain release notes, for example.
11
12 * <b>Blog Entries</b>. Blog entries from developers describing the current
13 state of a project, or rational for v arious design decisions, or
14 roadmaps for future development, can be entered as technotes.
15
16 * <b>Process Checkpoints</b>. For projects that have a formal process,
17 technotes can be used to record the completion or the initiation of
18 various process steps. For example, a technote can be used to record
19 the successful completion of a long-running test, perhaps w[./wikitheory.wiki | wiki page]
20 that is associated with a point in time rather thaevent causes a si [/timelinhyperlink ofTimeline Page]entry cause a jump to the wiThe wiki content, the timeline entry text, the
21 time of the eventTechnical Notes</title>
22
23 <h2>What Is A "Technote"?</h2>
24
25 In Fossil, a "technical note" or "technoteventerly called an "event")
26 is a speeventiki page]
27 that is associated with a point in time rather than having a page name.
28 eventaving a page name.
29 Each technote causes a single entry to appear on the
30 [/timeline?y=<titl
31 Possible uses for technotes include:
32
33 * <b>Milestones</b>. Project milestones, such as releases or beta-test
34 cycles, can be recorded as technotes. The timeline entry for the technote
35 can be something simple like "V
+106 -13
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -43,13 +43,14 @@
4343
<li> [#cluster | Clusters] </li>
4444
<li> [#ctrl | Control Artifacts] </li>
4545
<li> [#wikichng | Wiki Pages] </li>
4646
<li> [#tktchng | Ticket Changes] </li>
4747
<li> [#attachment | Attachments] </li>
48
+<li> [#event | Events] </li>
4849
</ul>
4950
50
-These five artifact types are described in the sequel.
51
+These seven artifact types are described in the sequel.
5152
5253
In the current implementation (as of 2009-01-25) the artifacts that
5354
make up a fossil repository are stored in in as delta- and zlib-compressed
5455
blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This
5556
is an implementation detail and might change in a future release. For
@@ -56,10 +57,13 @@
5657
the purpose of this article "file format" means the format of the artifacts,
5758
not how the artifacts are stored on disk. It is the artifact format that
5859
is intended to be enduring. The specifics of how artifacts are stored on
5960
disk, though stable, is not intended to live as long as the
6061
artifact format.
62
+
63
+All of the artifacts can be extracted from a Fossil repository using
64
+the "fossil deconstruct" command.
6165
6266
<a name="manifest"></a>
6367
<h2>1.0 The Manifest</h2>
6468
6569
A manifest defines a check-in or version of the project
@@ -165,12 +169,13 @@
165169
repository, append a single space (ASCII 0x20), the
166170
size of the file in ASCII decimal, a single newline
167171
character (ASCII 0x0A), and the complete text of the file.
168172
Compute the MD5 checksum of the result.
169173
170
-A manifest might contain one or more T-cards used to set tags or
171
-properties on the check-in. The format of the T-card is the same as
174
+A manifest might contain one or more T-cards used to set
175
+[./branching.wiki#tags | tags or properties]
176
+on the check-in. The format of the T-card is the same as
172177
described in <i>Control Artifacts</i> section below, except that the
173178
second argument is the single characcter "<b>*</b>" instead of an
174179
artifact ID. The <b>*</b> in place of the artifact ID indicates that
175180
the tag or property applies to the current artifact. It is not
176181
possible to encode the current artifact ID as part of an artifact,
@@ -182,11 +187,11 @@
182187
Each manifest has a single U-card. The argument to the U-card is
183188
the login of the user who created the manifest. The login name
184189
is encoded using the same character escapes as is used for the
185190
check-in comment argument to the C-card.
186191
187
-A manifest has an option Z-card as its last line. The argument
192
+A manifest has an optional Z-card as its last line. The argument
188193
to the Z-card is a 32-character lowercase hexadecimal MD5 hash
189194
of all prior lines of the manifest up to and including the newline
190195
character that immediately precedes the "Z". The Z-card is just
191196
a sanity check to prove that the manifest is well-formed and
192197
consistent.
@@ -262,11 +267,12 @@
262267
clearsigned.
263268
264269
The D card and the Z card of a control artifact are the same
265270
as in a manifest.
266271
267
-The T card represents a "tag" or property that is applied to
272
+The T card represents a [./branching.wiki#tags | tag or property]
273
+that is applied to
268274
some other artifact. The T card has two or three values. The
269275
second argument is the 40 character lowercase artifact ID of the artifact
270276
to which the tag is to be applied. The
271277
first value is the tag name. The first character of the tag
272278
is either "+", "-", or "*". A "+" means the tag should be added
@@ -324,11 +330,11 @@
324330
of text in the wiki page. That text follows the newline character
325331
that terminates the W card. The wiki text is always followed by one
326332
extra newline.
327333
328334
An example wiki artifact can be seen
329
-[/artifact/7b2f5fd0e0 | here].
335
+[/artifact?name=7b2f5fd0e0&txt=1 | here].
330336
331337
<a name="tktchng"></a>
332338
<h2>5.0 Ticket Changes</h2>
333339
334340
A ticket-change artifact represents a change to a trouble ticket.
@@ -375,25 +381,25 @@
375381
376382
<a name="attachment"></a>
377383
<h2>6.0 Attachments</h2>
378384
379385
An attachment artifact associates some other artifact that is the
380
-attachment (the source artifact) with a ticket or wiki page to which
386
+attachment (the source artifact) with a ticket or wiki page or event to which
381387
the attachment is connected (the target artifact).
382388
The following cards are allowed on an attachment artifact:
383389
384390
<blockquote>
385
-<b>A</b> <i>filename target</i> ?<i>source</i>?
386
-<b>C</b> <i>comment</i><br>
391
+<b>A</b> <i>filename target</i> ?<i>source</i>?<br />
392
+<b>C</b> <i>comment</i><br />
387393
<b>D</b> <i>time-and-date-stamp</i><br />
388394
<b>U</b> <i>user-name</i><br />
389395
<b>Z</b> <i>checksum</i>
390396
</blockquote>
391397
392398
The A card specifies a filename for the attachment in its first argument.
393399
The second argument to the A card is the name
394
-of the wiki page or ticket to which the attachment is connected. The
400
+of the wiki page or ticket or event to which the attachment is connected. The
395401
third argument is either missing or else it is the 40-character artifact
396402
ID of the attachment itself. A missing third argument means that the
397403
attachment should be deleted.
398404
399405
The C card is an optional comment describing what the attachment is about.
@@ -405,46 +411,111 @@
405411
A single U card gives the name of the user to added the attachment.
406412
If an attachment is added anonymously, then the U card may be omitted.
407413
408414
The Z card is the usual checksum over the rest of the attachment artifact.
409415
416
+
417
+<a name="event"></a>
418
+<h2>7.0 Events</h2>
419
+
420
+An event artifact associates a timeline comment and a page of text
421
+(similar to a wiki page) with a point in time. Events can be used
422
+to record project milestones, release notes, blog entries, process
423
+checkpoints, or news articles.
424
+The following cards are allowed on an event artifact:
425
+
426
+<blockquote>
427
+<b>C</b> <i>comment</i><br>
428
+<b>D</b> <i>time-and-date-stamp</i><br />
429
+<b>E</b> <i>event-time</i> <i>event-id</i><br />
430
+<b>P</b> <i>parent-artifact-id</i>+<br />
431
+<b>T</b> <b>+</b><i>tag-name</i> <b>*</b> <i>value</i><br />
432
+<b>U</b> <i>user-name</i><br />
433
+<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
434
+<b>Z</b> <i>checksum</i>
435
+</blockquote>
436
+
437
+The C card contains text that is displayed on the timeline for the
438
+event. Exactly one C card is required on an event artifact.
439
+
440
+A single D card is required to give the date and time when the
441
+event artifact was created. This is different from the time at which
442
+the event occurs.
443
+
444
+A single E card gives the time of the event (the point on the timeline
445
+where the event is displayed) and a unique identifier for the event.
446
+When there are multiple artifacts with the same event-id, the one with
447
+the most recent D card is the only one used. The event-id must be a
448
+40-character lower-case hexadecimal string.
449
+
450
+The option P card specifies a prior event with the same event-id from
451
+which the current event is an edit. The P card is a hint to the system
452
+that it might be space efficient to store one event as a delta of the
453
+other.
454
+
455
+An event might contain one or more T-cards used to set
456
+[./branching.wiki#tags | tags or properties]
457
+on the event. The format of the T-card is the same as
458
+described in [#ctrl | Control Artifacts] section above, except that the
459
+second argument is the single characcter "<b>*</b>" instead of an
460
+artifact ID and the name is always prefaced by "<b>+</b>".
461
+The <b>*</b> in place of the artifact ID indicates that
462
+the tag or property applies to the current artifact. It is not
463
+possible to encode the current artifact ID as part of an artifact,
464
+since the act of inserting the artifact ID would change the artifact ID,
465
+hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the
466
+name means that tags can only be add and they can only be non-propagating
467
+tags. A an event, T cards are normally used to set the background
468
+display color for timelines.
469
+
470
+The optional U card gives name of the user who entered the event.
471
+
472
+A single W card provides wiki text for the document associated with the
473
+event. The format of the W card is exactly the same as for a
474
+[#wikichng | wiki artifact].
475
+
476
+The Z card is the usual checksum over the rest of the attachment artifact.
477
+
410478
411479
<a name="summary"></a>
412
-<h2>7.0 Card Summary</h2>
480
+<h2>8.0 Card Summary</h2>
413481
414482
The following table summaries the various kinds of cards that
415483
appear on Fossil artifacts:
416484
417485
<table border=1 width="100%">
418486
<tr>
419487
<th rowspan=2 valign=bottom>Card Format</th>
420
-<th colspan=6>Used By</th>
488
+<th colspan=7>Used By</th>
421489
</tr>
422490
<tr>
423491
<th>Manifest</th>
424492
<th>Cluster</th>
425493
<th>Control</th>
426494
<th>Wiki</th>
427495
<th>Ticket</th>
428496
<th>Attachment</th>
497
+<th>Event</th>
429498
</tr>
430499
<tr>
431500
<td><b>A</b> <i>filename target source</i></td>
432501
<td>&nbsp;</td>
433502
<td>&nbsp;</td>
434503
<td>&nbsp;</td>
435504
<td>&nbsp;</td>
436505
<td>&nbsp;</td>
437506
<td align=center><b>X</b></td>
507
+<td>&nbsp;</td>
438508
</tr>
439509
<tr>
440
-<td><b>C</b> <i>coment-text</i></td>
510
+<td><b>C</b> <i>comment-text</i></td>
441511
<td align=center><b>X</b></td>
442512
<td>&nbsp;</td>
443513
<td>&nbsp;</td>
444514
<td>&nbsp;</td>
445515
<td>&nbsp;</td>
516
+<td align=center><b>X</b></td>
446517
<td align=center><b>X</b></td>
447518
</tr>
448519
<tr>
449520
<td><b>D</b> <i>date-time-stamp</i></td>
450521
<td align=center><b>X</b></td>
@@ -451,14 +522,26 @@
451522
<td align=center>&nbsp;</td>
452523
<td align=center><b>X</b></td>
453524
<td align=center><b>X</b></td>
454525
<td align=center><b>X</b></td>
455526
<td align=center><b>X</b></td>
527
+<td align=center><b>X</b></td>
528
+</tr>
529
+<tr>
530
+<td><b>E</b> <i>event-time event-id</i></td>
531
+<td align=center>&nbsp;</td>
532
+<td align=center>&nbsp;</td>
533
+<td align=center>&nbsp;</td>
534
+<td align=center>&nbsp;</td>
535
+<td align=center>&nbsp;</td>
536
+<td align=center>&nbsp;</td>
537
+<td align=center><b>X</b></td>
456538
</tr>
457539
<tr>
458540
<td><b>F</b> <i>filename uuid permissions oldname</i></td>
459541
<td align=center><b>X</b></td>
542
+<td align=center>&nbsp;</td>
460543
<td align=center>&nbsp;</td>
461544
<td align=center>&nbsp;</td>
462545
<td align=center>&nbsp;</td>
463546
<td align=center>&nbsp;</td>
464547
<td align=center>&nbsp;</td>
@@ -469,18 +552,20 @@
469552
<td align=center>&nbsp;</td>
470553
<td align=center>&nbsp;</td>
471554
<td align=center>&nbsp;</td>
472555
<td align=center><b>X</b></td>
473556
<td align=center>&nbsp;</td>
557
+<td align=center>&nbsp;</td>
474558
</tr>
475559
<tr>
476560
<td><b>K</b> <i>ticket-uuid</i></td>
477561
<td align=center>&nbsp;</td>
478562
<td align=center>&nbsp;</td>
479563
<td align=center>&nbsp;</td>
480564
<td align=center>&nbsp;</td>
481565
<td align=center><b>X</b></td>
566
+<td align=center>&nbsp;</td>
482567
<td align=center>&nbsp;</td>
483568
</tr>
484569
<tr>
485570
<td><b>L</b> <i>wiki-title</i></td>
486571
<td align=center>&nbsp;</td>
@@ -487,15 +572,17 @@
487572
<td align=center>&nbsp;</td>
488573
<td align=center>&nbsp;</td>
489574
<td align=center><b>X</b></td>
490575
<td align=center>&nbsp;</td>
491576
<td align=center>&nbsp;</td>
577
+<td align=center>&nbsp;</td>
492578
</tr>
493579
<tr>
494580
<td><b>M</b> <i>uuid</i></td>
495581
<td align=center>&nbsp;</td>
496582
<td align=center><b>X</b></td>
583
+<td align=center>&nbsp;</td>
497584
<td align=center>&nbsp;</td>
498585
<td align=center>&nbsp;</td>
499586
<td align=center>&nbsp;</td>
500587
<td align=center>&nbsp;</td>
501588
</tr>
@@ -505,14 +592,16 @@
505592
<td align=center>&nbsp;</td>
506593
<td align=center>&nbsp;</td>
507594
<td align=center><b>X</b></td>
508595
<td align=center>&nbsp;</td>
509596
<td align=center>&nbsp;</td>
597
+<td align=center>&nbsp;</td>
510598
</tr>
511599
<tr>
512600
<td><b>R</b> <i>md5sum</i></td>
513601
<td align=center><b>X</b></td>
602
+<td align=center>&nbsp;</td>
514603
<td align=center>&nbsp;</td>
515604
<td align=center>&nbsp;</td>
516605
<td align=center>&nbsp;</td>
517606
<td align=center>&nbsp;</td>
518607
<td align=center>&nbsp;</td>
@@ -522,15 +611,17 @@
522611
<td align=center>&nbsp;</td>
523612
<td align=center><b>X</b></td>
524613
<td align=center>&nbsp;</td>
525614
<td align=center>&nbsp;</td>
526615
<td align=center>&nbsp;</td>
616
+<td align=center><b>X</b></td>
527617
</tr>
528618
<tr>
529619
<td><b>U</b> <i>username</i></td>
530620
<td align=center><b>X</b></td>
531621
<td align=center>&nbsp;</td>
622
+<td align=center><b>X</b></td>
532623
<td align=center><b>X</b></td>
533624
<td align=center><b>X</b></td>
534625
<td align=center><b>X</b></td>
535626
<td align=center><b>X</b></td>
536627
</tr>
@@ -540,16 +631,18 @@
540631
<td align=center>&nbsp;</td>
541632
<td align=center>&nbsp;</td>
542633
<td align=center><b>X</b></td>
543634
<td align=center>&nbsp;</td>
544635
<td align=center>&nbsp;</td>
636
+<td align=center><b>X</b></td>
545637
</tr>
546638
<tr>
547639
<td><b>Z</b> <i>md5sum</i></td>
640
+<td align=center><b>X</b></td>
548641
<td align=center><b>X</b></td>
549642
<td align=center><b>X</b></td>
550643
<td align=center><b>X</b></td>
551644
<td align=center><b>X</b></td>
552645
<td align=center><b>X</b></td>
553646
<td align=center><b>X</b></td>
554647
</tr>
555648
</table>
556649
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -43,13 +43,14 @@
43 <li> [#cluster | Clusters] </li>
44 <li> [#ctrl | Control Artifacts] </li>
45 <li> [#wikichng | Wiki Pages] </li>
46 <li> [#tktchng | Ticket Changes] </li>
47 <li> [#attachment | Attachments] </li>
 
48 </ul>
49
50 These five artifact types are described in the sequel.
51
52 In the current implementation (as of 2009-01-25) the artifacts that
53 make up a fossil repository are stored in in as delta- and zlib-compressed
54 blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This
55 is an implementation detail and might change in a future release. For
@@ -56,10 +57,13 @@
56 the purpose of this article "file format" means the format of the artifacts,
57 not how the artifacts are stored on disk. It is the artifact format that
58 is intended to be enduring. The specifics of how artifacts are stored on
59 disk, though stable, is not intended to live as long as the
60 artifact format.
 
 
 
61
62 <a name="manifest"></a>
63 <h2>1.0 The Manifest</h2>
64
65 A manifest defines a check-in or version of the project
@@ -165,12 +169,13 @@
165 repository, append a single space (ASCII 0x20), the
166 size of the file in ASCII decimal, a single newline
167 character (ASCII 0x0A), and the complete text of the file.
168 Compute the MD5 checksum of the result.
169
170 A manifest might contain one or more T-cards used to set tags or
171 properties on the check-in. The format of the T-card is the same as
 
172 described in <i>Control Artifacts</i> section below, except that the
173 second argument is the single characcter "<b>*</b>" instead of an
174 artifact ID. The <b>*</b> in place of the artifact ID indicates that
175 the tag or property applies to the current artifact. It is not
176 possible to encode the current artifact ID as part of an artifact,
@@ -182,11 +187,11 @@
182 Each manifest has a single U-card. The argument to the U-card is
183 the login of the user who created the manifest. The login name
184 is encoded using the same character escapes as is used for the
185 check-in comment argument to the C-card.
186
187 A manifest has an option Z-card as its last line. The argument
188 to the Z-card is a 32-character lowercase hexadecimal MD5 hash
189 of all prior lines of the manifest up to and including the newline
190 character that immediately precedes the "Z". The Z-card is just
191 a sanity check to prove that the manifest is well-formed and
192 consistent.
@@ -262,11 +267,12 @@
262 clearsigned.
263
264 The D card and the Z card of a control artifact are the same
265 as in a manifest.
266
267 The T card represents a "tag" or property that is applied to
 
268 some other artifact. The T card has two or three values. The
269 second argument is the 40 character lowercase artifact ID of the artifact
270 to which the tag is to be applied. The
271 first value is the tag name. The first character of the tag
272 is either "+", "-", or "*". A "+" means the tag should be added
@@ -324,11 +330,11 @@
324 of text in the wiki page. That text follows the newline character
325 that terminates the W card. The wiki text is always followed by one
326 extra newline.
327
328 An example wiki artifact can be seen
329 [/artifact/7b2f5fd0e0 | here].
330
331 <a name="tktchng"></a>
332 <h2>5.0 Ticket Changes</h2>
333
334 A ticket-change artifact represents a change to a trouble ticket.
@@ -375,25 +381,25 @@
375
376 <a name="attachment"></a>
377 <h2>6.0 Attachments</h2>
378
379 An attachment artifact associates some other artifact that is the
380 attachment (the source artifact) with a ticket or wiki page to which
381 the attachment is connected (the target artifact).
382 The following cards are allowed on an attachment artifact:
383
384 <blockquote>
385 <b>A</b> <i>filename target</i> ?<i>source</i>?
386 <b>C</b> <i>comment</i><br>
387 <b>D</b> <i>time-and-date-stamp</i><br />
388 <b>U</b> <i>user-name</i><br />
389 <b>Z</b> <i>checksum</i>
390 </blockquote>
391
392 The A card specifies a filename for the attachment in its first argument.
393 The second argument to the A card is the name
394 of the wiki page or ticket to which the attachment is connected. The
395 third argument is either missing or else it is the 40-character artifact
396 ID of the attachment itself. A missing third argument means that the
397 attachment should be deleted.
398
399 The C card is an optional comment describing what the attachment is about.
@@ -405,46 +411,111 @@
405 A single U card gives the name of the user to added the attachment.
406 If an attachment is added anonymously, then the U card may be omitted.
407
408 The Z card is the usual checksum over the rest of the attachment artifact.
409
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
411 <a name="summary"></a>
412 <h2>7.0 Card Summary</h2>
413
414 The following table summaries the various kinds of cards that
415 appear on Fossil artifacts:
416
417 <table border=1 width="100%">
418 <tr>
419 <th rowspan=2 valign=bottom>Card Format</th>
420 <th colspan=6>Used By</th>
421 </tr>
422 <tr>
423 <th>Manifest</th>
424 <th>Cluster</th>
425 <th>Control</th>
426 <th>Wiki</th>
427 <th>Ticket</th>
428 <th>Attachment</th>
 
429 </tr>
430 <tr>
431 <td><b>A</b> <i>filename target source</i></td>
432 <td>&nbsp;</td>
433 <td>&nbsp;</td>
434 <td>&nbsp;</td>
435 <td>&nbsp;</td>
436 <td>&nbsp;</td>
437 <td align=center><b>X</b></td>
 
438 </tr>
439 <tr>
440 <td><b>C</b> <i>coment-text</i></td>
441 <td align=center><b>X</b></td>
442 <td>&nbsp;</td>
443 <td>&nbsp;</td>
444 <td>&nbsp;</td>
445 <td>&nbsp;</td>
 
446 <td align=center><b>X</b></td>
447 </tr>
448 <tr>
449 <td><b>D</b> <i>date-time-stamp</i></td>
450 <td align=center><b>X</b></td>
@@ -451,14 +522,26 @@
451 <td align=center>&nbsp;</td>
452 <td align=center><b>X</b></td>
453 <td align=center><b>X</b></td>
454 <td align=center><b>X</b></td>
455 <td align=center><b>X</b></td>
 
 
 
 
 
 
 
 
 
 
 
456 </tr>
457 <tr>
458 <td><b>F</b> <i>filename uuid permissions oldname</i></td>
459 <td align=center><b>X</b></td>
 
460 <td align=center>&nbsp;</td>
461 <td align=center>&nbsp;</td>
462 <td align=center>&nbsp;</td>
463 <td align=center>&nbsp;</td>
464 <td align=center>&nbsp;</td>
@@ -469,18 +552,20 @@
469 <td align=center>&nbsp;</td>
470 <td align=center>&nbsp;</td>
471 <td align=center>&nbsp;</td>
472 <td align=center><b>X</b></td>
473 <td align=center>&nbsp;</td>
 
474 </tr>
475 <tr>
476 <td><b>K</b> <i>ticket-uuid</i></td>
477 <td align=center>&nbsp;</td>
478 <td align=center>&nbsp;</td>
479 <td align=center>&nbsp;</td>
480 <td align=center>&nbsp;</td>
481 <td align=center><b>X</b></td>
 
482 <td align=center>&nbsp;</td>
483 </tr>
484 <tr>
485 <td><b>L</b> <i>wiki-title</i></td>
486 <td align=center>&nbsp;</td>
@@ -487,15 +572,17 @@
487 <td align=center>&nbsp;</td>
488 <td align=center>&nbsp;</td>
489 <td align=center><b>X</b></td>
490 <td align=center>&nbsp;</td>
491 <td align=center>&nbsp;</td>
 
492 </tr>
493 <tr>
494 <td><b>M</b> <i>uuid</i></td>
495 <td align=center>&nbsp;</td>
496 <td align=center><b>X</b></td>
 
497 <td align=center>&nbsp;</td>
498 <td align=center>&nbsp;</td>
499 <td align=center>&nbsp;</td>
500 <td align=center>&nbsp;</td>
501 </tr>
@@ -505,14 +592,16 @@
505 <td align=center>&nbsp;</td>
506 <td align=center>&nbsp;</td>
507 <td align=center><b>X</b></td>
508 <td align=center>&nbsp;</td>
509 <td align=center>&nbsp;</td>
 
510 </tr>
511 <tr>
512 <td><b>R</b> <i>md5sum</i></td>
513 <td align=center><b>X</b></td>
 
514 <td align=center>&nbsp;</td>
515 <td align=center>&nbsp;</td>
516 <td align=center>&nbsp;</td>
517 <td align=center>&nbsp;</td>
518 <td align=center>&nbsp;</td>
@@ -522,15 +611,17 @@
522 <td align=center>&nbsp;</td>
523 <td align=center><b>X</b></td>
524 <td align=center>&nbsp;</td>
525 <td align=center>&nbsp;</td>
526 <td align=center>&nbsp;</td>
 
527 </tr>
528 <tr>
529 <td><b>U</b> <i>username</i></td>
530 <td align=center><b>X</b></td>
531 <td align=center>&nbsp;</td>
 
532 <td align=center><b>X</b></td>
533 <td align=center><b>X</b></td>
534 <td align=center><b>X</b></td>
535 <td align=center><b>X</b></td>
536 </tr>
@@ -540,16 +631,18 @@
540 <td align=center>&nbsp;</td>
541 <td align=center>&nbsp;</td>
542 <td align=center><b>X</b></td>
543 <td align=center>&nbsp;</td>
544 <td align=center>&nbsp;</td>
 
545 </tr>
546 <tr>
547 <td><b>Z</b> <i>md5sum</i></td>
 
548 <td align=center><b>X</b></td>
549 <td align=center><b>X</b></td>
550 <td align=center><b>X</b></td>
551 <td align=center><b>X</b></td>
552 <td align=center><b>X</b></td>
553 <td align=center><b>X</b></td>
554 </tr>
555 </table>
556
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -43,13 +43,14 @@
43 <li> [#cluster | Clusters] </li>
44 <li> [#ctrl | Control Artifacts] </li>
45 <li> [#wikichng | Wiki Pages] </li>
46 <li> [#tktchng | Ticket Changes] </li>
47 <li> [#attachment | Attachments] </li>
48 <li> [#event | Events] </li>
49 </ul>
50
51 These seven artifact types are described in the sequel.
52
53 In the current implementation (as of 2009-01-25) the artifacts that
54 make up a fossil repository are stored in in as delta- and zlib-compressed
55 blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This
56 is an implementation detail and might change in a future release. For
@@ -56,10 +57,13 @@
57 the purpose of this article "file format" means the format of the artifacts,
58 not how the artifacts are stored on disk. It is the artifact format that
59 is intended to be enduring. The specifics of how artifacts are stored on
60 disk, though stable, is not intended to live as long as the
61 artifact format.
62
63 All of the artifacts can be extracted from a Fossil repository using
64 the "fossil deconstruct" command.
65
66 <a name="manifest"></a>
67 <h2>1.0 The Manifest</h2>
68
69 A manifest defines a check-in or version of the project
@@ -165,12 +169,13 @@
169 repository, append a single space (ASCII 0x20), the
170 size of the file in ASCII decimal, a single newline
171 character (ASCII 0x0A), and the complete text of the file.
172 Compute the MD5 checksum of the result.
173
174 A manifest might contain one or more T-cards used to set
175 [./branching.wiki#tags | tags or properties]
176 on the check-in. The format of the T-card is the same as
177 described in <i>Control Artifacts</i> section below, except that the
178 second argument is the single characcter "<b>*</b>" instead of an
179 artifact ID. The <b>*</b> in place of the artifact ID indicates that
180 the tag or property applies to the current artifact. It is not
181 possible to encode the current artifact ID as part of an artifact,
@@ -182,11 +187,11 @@
187 Each manifest has a single U-card. The argument to the U-card is
188 the login of the user who created the manifest. The login name
189 is encoded using the same character escapes as is used for the
190 check-in comment argument to the C-card.
191
192 A manifest has an optional Z-card as its last line. The argument
193 to the Z-card is a 32-character lowercase hexadecimal MD5 hash
194 of all prior lines of the manifest up to and including the newline
195 character that immediately precedes the "Z". The Z-card is just
196 a sanity check to prove that the manifest is well-formed and
197 consistent.
@@ -262,11 +267,12 @@
267 clearsigned.
268
269 The D card and the Z card of a control artifact are the same
270 as in a manifest.
271
272 The T card represents a [./branching.wiki#tags | tag or property]
273 that is applied to
274 some other artifact. The T card has two or three values. The
275 second argument is the 40 character lowercase artifact ID of the artifact
276 to which the tag is to be applied. The
277 first value is the tag name. The first character of the tag
278 is either "+", "-", or "*". A "+" means the tag should be added
@@ -324,11 +330,11 @@
330 of text in the wiki page. That text follows the newline character
331 that terminates the W card. The wiki text is always followed by one
332 extra newline.
333
334 An example wiki artifact can be seen
335 [/artifact?name=7b2f5fd0e0&txt=1 | here].
336
337 <a name="tktchng"></a>
338 <h2>5.0 Ticket Changes</h2>
339
340 A ticket-change artifact represents a change to a trouble ticket.
@@ -375,25 +381,25 @@
381
382 <a name="attachment"></a>
383 <h2>6.0 Attachments</h2>
384
385 An attachment artifact associates some other artifact that is the
386 attachment (the source artifact) with a ticket or wiki page or event to which
387 the attachment is connected (the target artifact).
388 The following cards are allowed on an attachment artifact:
389
390 <blockquote>
391 <b>A</b> <i>filename target</i> ?<i>source</i>?<br />
392 <b>C</b> <i>comment</i><br />
393 <b>D</b> <i>time-and-date-stamp</i><br />
394 <b>U</b> <i>user-name</i><br />
395 <b>Z</b> <i>checksum</i>
396 </blockquote>
397
398 The A card specifies a filename for the attachment in its first argument.
399 The second argument to the A card is the name
400 of the wiki page or ticket or event to which the attachment is connected. The
401 third argument is either missing or else it is the 40-character artifact
402 ID of the attachment itself. A missing third argument means that the
403 attachment should be deleted.
404
405 The C card is an optional comment describing what the attachment is about.
@@ -405,46 +411,111 @@
411 A single U card gives the name of the user to added the attachment.
412 If an attachment is added anonymously, then the U card may be omitted.
413
414 The Z card is the usual checksum over the rest of the attachment artifact.
415
416
417 <a name="event"></a>
418 <h2>7.0 Events</h2>
419
420 An event artifact associates a timeline comment and a page of text
421 (similar to a wiki page) with a point in time. Events can be used
422 to record project milestones, release notes, blog entries, process
423 checkpoints, or news articles.
424 The following cards are allowed on an event artifact:
425
426 <blockquote>
427 <b>C</b> <i>comment</i><br>
428 <b>D</b> <i>time-and-date-stamp</i><br />
429 <b>E</b> <i>event-time</i> <i>event-id</i><br />
430 <b>P</b> <i>parent-artifact-id</i>+<br />
431 <b>T</b> <b>+</b><i>tag-name</i> <b>*</b> <i>value</i><br />
432 <b>U</b> <i>user-name</i><br />
433 <b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
434 <b>Z</b> <i>checksum</i>
435 </blockquote>
436
437 The C card contains text that is displayed on the timeline for the
438 event. Exactly one C card is required on an event artifact.
439
440 A single D card is required to give the date and time when the
441 event artifact was created. This is different from the time at which
442 the event occurs.
443
444 A single E card gives the time of the event (the point on the timeline
445 where the event is displayed) and a unique identifier for the event.
446 When there are multiple artifacts with the same event-id, the one with
447 the most recent D card is the only one used. The event-id must be a
448 40-character lower-case hexadecimal string.
449
450 The option P card specifies a prior event with the same event-id from
451 which the current event is an edit. The P card is a hint to the system
452 that it might be space efficient to store one event as a delta of the
453 other.
454
455 An event might contain one or more T-cards used to set
456 [./branching.wiki#tags | tags or properties]
457 on the event. The format of the T-card is the same as
458 described in [#ctrl | Control Artifacts] section above, except that the
459 second argument is the single characcter "<b>*</b>" instead of an
460 artifact ID and the name is always prefaced by "<b>+</b>".
461 The <b>*</b> in place of the artifact ID indicates that
462 the tag or property applies to the current artifact. It is not
463 possible to encode the current artifact ID as part of an artifact,
464 since the act of inserting the artifact ID would change the artifact ID,
465 hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the
466 name means that tags can only be add and they can only be non-propagating
467 tags. A an event, T cards are normally used to set the background
468 display color for timelines.
469
470 The optional U card gives name of the user who entered the event.
471
472 A single W card provides wiki text for the document associated with the
473 event. The format of the W card is exactly the same as for a
474 [#wikichng | wiki artifact].
475
476 The Z card is the usual checksum over the rest of the attachment artifact.
477
478
479 <a name="summary"></a>
480 <h2>8.0 Card Summary</h2>
481
482 The following table summaries the various kinds of cards that
483 appear on Fossil artifacts:
484
485 <table border=1 width="100%">
486 <tr>
487 <th rowspan=2 valign=bottom>Card Format</th>
488 <th colspan=7>Used By</th>
489 </tr>
490 <tr>
491 <th>Manifest</th>
492 <th>Cluster</th>
493 <th>Control</th>
494 <th>Wiki</th>
495 <th>Ticket</th>
496 <th>Attachment</th>
497 <th>Event</th>
498 </tr>
499 <tr>
500 <td><b>A</b> <i>filename target source</i></td>
501 <td>&nbsp;</td>
502 <td>&nbsp;</td>
503 <td>&nbsp;</td>
504 <td>&nbsp;</td>
505 <td>&nbsp;</td>
506 <td align=center><b>X</b></td>
507 <td>&nbsp;</td>
508 </tr>
509 <tr>
510 <td><b>C</b> <i>comment-text</i></td>
511 <td align=center><b>X</b></td>
512 <td>&nbsp;</td>
513 <td>&nbsp;</td>
514 <td>&nbsp;</td>
515 <td>&nbsp;</td>
516 <td align=center><b>X</b></td>
517 <td align=center><b>X</b></td>
518 </tr>
519 <tr>
520 <td><b>D</b> <i>date-time-stamp</i></td>
521 <td align=center><b>X</b></td>
@@ -451,14 +522,26 @@
522 <td align=center>&nbsp;</td>
523 <td align=center><b>X</b></td>
524 <td align=center><b>X</b></td>
525 <td align=center><b>X</b></td>
526 <td align=center><b>X</b></td>
527 <td align=center><b>X</b></td>
528 </tr>
529 <tr>
530 <td><b>E</b> <i>event-time event-id</i></td>
531 <td align=center>&nbsp;</td>
532 <td align=center>&nbsp;</td>
533 <td align=center>&nbsp;</td>
534 <td align=center>&nbsp;</td>
535 <td align=center>&nbsp;</td>
536 <td align=center>&nbsp;</td>
537 <td align=center><b>X</b></td>
538 </tr>
539 <tr>
540 <td><b>F</b> <i>filename uuid permissions oldname</i></td>
541 <td align=center><b>X</b></td>
542 <td align=center>&nbsp;</td>
543 <td align=center>&nbsp;</td>
544 <td align=center>&nbsp;</td>
545 <td align=center>&nbsp;</td>
546 <td align=center>&nbsp;</td>
547 <td align=center>&nbsp;</td>
@@ -469,18 +552,20 @@
552 <td align=center>&nbsp;</td>
553 <td align=center>&nbsp;</td>
554 <td align=center>&nbsp;</td>
555 <td align=center><b>X</b></td>
556 <td align=center>&nbsp;</td>
557 <td align=center>&nbsp;</td>
558 </tr>
559 <tr>
560 <td><b>K</b> <i>ticket-uuid</i></td>
561 <td align=center>&nbsp;</td>
562 <td align=center>&nbsp;</td>
563 <td align=center>&nbsp;</td>
564 <td align=center>&nbsp;</td>
565 <td align=center><b>X</b></td>
566 <td align=center>&nbsp;</td>
567 <td align=center>&nbsp;</td>
568 </tr>
569 <tr>
570 <td><b>L</b> <i>wiki-title</i></td>
571 <td align=center>&nbsp;</td>
@@ -487,15 +572,17 @@
572 <td align=center>&nbsp;</td>
573 <td align=center>&nbsp;</td>
574 <td align=center><b>X</b></td>
575 <td align=center>&nbsp;</td>
576 <td align=center>&nbsp;</td>
577 <td align=center>&nbsp;</td>
578 </tr>
579 <tr>
580 <td><b>M</b> <i>uuid</i></td>
581 <td align=center>&nbsp;</td>
582 <td align=center><b>X</b></td>
583 <td align=center>&nbsp;</td>
584 <td align=center>&nbsp;</td>
585 <td align=center>&nbsp;</td>
586 <td align=center>&nbsp;</td>
587 <td align=center>&nbsp;</td>
588 </tr>
@@ -505,14 +592,16 @@
592 <td align=center>&nbsp;</td>
593 <td align=center>&nbsp;</td>
594 <td align=center><b>X</b></td>
595 <td align=center>&nbsp;</td>
596 <td align=center>&nbsp;</td>
597 <td align=center>&nbsp;</td>
598 </tr>
599 <tr>
600 <td><b>R</b> <i>md5sum</i></td>
601 <td align=center><b>X</b></td>
602 <td align=center>&nbsp;</td>
603 <td align=center>&nbsp;</td>
604 <td align=center>&nbsp;</td>
605 <td align=center>&nbsp;</td>
606 <td align=center>&nbsp;</td>
607 <td align=center>&nbsp;</td>
@@ -522,15 +611,17 @@
611 <td align=center>&nbsp;</td>
612 <td align=center><b>X</b></td>
613 <td align=center>&nbsp;</td>
614 <td align=center>&nbsp;</td>
615 <td align=center>&nbsp;</td>
616 <td align=center><b>X</b></td>
617 </tr>
618 <tr>
619 <td><b>U</b> <i>username</i></td>
620 <td align=center><b>X</b></td>
621 <td align=center>&nbsp;</td>
622 <td align=center><b>X</b></td>
623 <td align=center><b>X</b></td>
624 <td align=center><b>X</b></td>
625 <td align=center><b>X</b></td>
626 <td align=center><b>X</b></td>
627 </tr>
@@ -540,16 +631,18 @@
631 <td align=center>&nbsp;</td>
632 <td align=center>&nbsp;</td>
633 <td align=center><b>X</b></td>
634 <td align=center>&nbsp;</td>
635 <td align=center>&nbsp;</td>
636 <td align=center><b>X</b></td>
637 </tr>
638 <tr>
639 <td><b>Z</b> <i>md5sum</i></td>
640 <td align=center><b>X</b></td>
641 <td align=center><b>X</b></td>
642 <td align=center><b>X</b></td>
643 <td align=center><b>X</b></td>
644 <td align=center><b>X</b></td>
645 <td align=center><b>X</b></td>
646 <td align=center><b>X</b></td>
647 </tr>
648 </table>
649
+5 -2
--- www/index.wiki
+++ www/index.wiki
@@ -40,12 +40,13 @@
4040
internet these days. What makes Fossil worthy of attention?
4141
4242
1. <b>Bug Tracking And Wiki</b> -
4343
In addition to doing [./concepts.wiki | distributed version control]
4444
like Git and Mercurial,
45
- Fossil also supports [./bugtheory.wiki | distributed bug tracking] and
46
- [./wikitheory.wiki | distributed wiki] all in a single
45
+ Fossil also supports [./bugtheory.wiki | distributed bug tracking],
46
+ [./wikitheory.wiki | distributed wiki], and a
47
+ [./event.wiki | distributed blog] mechanism all in a single
4748
integrated package.
4849
4950
2. <b>Web Interface</b> -
5051
Fossil has a built-in and easy-to-use [./webui.wiki | web interface]
5152
that simplifies project tracking and promotes situational awareness.
@@ -111,10 +112,12 @@
111112
* A tutorial on [./branching.wiki | branching], what it means and how
112113
to do it using fossil.
113114
* The [./selfcheck.wiki | automatic self-check] mechanism
114115
helps insure project integrity.
115116
* Fossil contains a [./wikitheory.wiki | built-in wiki].
117
+ * An [./event.wiki | Event] is a special kind of wiki page associated
118
+ with a point in time rather than a name.
116119
* There is a
117120
[http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable
118121
[http://www.mail-archive.com/[email protected] | archives]
119122
available for discussing fossil issues.
120123
* [./stats.wiki | Performance statistics] taken from real-world projects
121124
--- www/index.wiki
+++ www/index.wiki
@@ -40,12 +40,13 @@
40 internet these days. What makes Fossil worthy of attention?
41
42 1. <b>Bug Tracking And Wiki</b> -
43 In addition to doing [./concepts.wiki | distributed version control]
44 like Git and Mercurial,
45 Fossil also supports [./bugtheory.wiki | distributed bug tracking] and
46 [./wikitheory.wiki | distributed wiki] all in a single
 
47 integrated package.
48
49 2. <b>Web Interface</b> -
50 Fossil has a built-in and easy-to-use [./webui.wiki | web interface]
51 that simplifies project tracking and promotes situational awareness.
@@ -111,10 +112,12 @@
111 * A tutorial on [./branching.wiki | branching], what it means and how
112 to do it using fossil.
113 * The [./selfcheck.wiki | automatic self-check] mechanism
114 helps insure project integrity.
115 * Fossil contains a [./wikitheory.wiki | built-in wiki].
 
 
116 * There is a
117 [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable
118 [http://www.mail-archive.com/[email protected] | archives]
119 available for discussing fossil issues.
120 * [./stats.wiki | Performance statistics] taken from real-world projects
121
--- www/index.wiki
+++ www/index.wiki
@@ -40,12 +40,13 @@
40 internet these days. What makes Fossil worthy of attention?
41
42 1. <b>Bug Tracking And Wiki</b> -
43 In addition to doing [./concepts.wiki | distributed version control]
44 like Git and Mercurial,
45 Fossil also supports [./bugtheory.wiki | distributed bug tracking],
46 [./wikitheory.wiki | distributed wiki], and a
47 [./event.wiki | distributed blog] mechanism all in a single
48 integrated package.
49
50 2. <b>Web Interface</b> -
51 Fossil has a built-in and easy-to-use [./webui.wiki | web interface]
52 that simplifies project tracking and promotes situational awareness.
@@ -111,10 +112,12 @@
112 * A tutorial on [./branching.wiki | branching], what it means and how
113 to do it using fossil.
114 * The [./selfcheck.wiki | automatic self-check] mechanism
115 helps insure project integrity.
116 * Fossil contains a [./wikitheory.wiki | built-in wiki].
117 * An [./event.wiki | Event] is a special kind of wiki page associated
118 with a point in time rather than a name.
119 * There is a
120 [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable
121 [http://www.mail-archive.com/[email protected] | archives]
122 available for discussing fossil issues.
123 * [./stats.wiki | Performance statistics] taken from real-world projects
124
+1 -1
--- www/qandc.wiki
+++ www/qandc.wiki
@@ -63,11 +63,11 @@
6363
Other projects are also adopting fossil. But fossil does not yet have
6464
the massive user base of git or mercurial.
6565
</blockquote>
6666
6767
<b>Fossil looks like the bug tracker that would be in your
68
-Linksys Router's administration screen.</p>
68
+Linksys Router's administration screen.</b>
6969
7070
<blockquote>
7171
<p>I take a pragmatic approach to software: form follows function.
7272
To me, it is more important to have a reliable, fast, efficient,
7373
enduring, and simple DVCS than one that looks pretty.</p>
7474
--- www/qandc.wiki
+++ www/qandc.wiki
@@ -63,11 +63,11 @@
63 Other projects are also adopting fossil. But fossil does not yet have
64 the massive user base of git or mercurial.
65 </blockquote>
66
67 <b>Fossil looks like the bug tracker that would be in your
68 Linksys Router's administration screen.</p>
69
70 <blockquote>
71 <p>I take a pragmatic approach to software: form follows function.
72 To me, it is more important to have a reliable, fast, efficient,
73 enduring, and simple DVCS than one that looks pretty.</p>
74
--- www/qandc.wiki
+++ www/qandc.wiki
@@ -63,11 +63,11 @@
63 Other projects are also adopting fossil. But fossil does not yet have
64 the massive user base of git or mercurial.
65 </blockquote>
66
67 <b>Fossil looks like the bug tracker that would be in your
68 Linksys Router's administration screen.</b>
69
70 <blockquote>
71 <p>I take a pragmatic approach to software: form follows function.
72 To me, it is more important to have a reliable, fast, efficient,
73 enduring, and simple DVCS than one that looks pretty.</p>
74
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -5,10 +5,11 @@
55
* Stand-alone wiki pages.
66
* Description and comments in [./bugtheory.wiki | bug reports].
77
* Check-in comments.
88
* [./embeddeddoc.wiki | Embedded documentation] files whose
99
name ends in "wiki".
10
+ * [./event.wiki | Event descriptions].
1011
1112
The [/wiki_rules | formatting rules] for fossil wiki
1213
are designed to be simple and intuitive. The idea is that wiki provides
1314
paragraph breaks, numbered and bulleted lists, and hyperlinking for
1415
simple documents together with a safe subset of HTML for more complex
1516
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -5,10 +5,11 @@
5 * Stand-alone wiki pages.
6 * Description and comments in [./bugtheory.wiki | bug reports].
7 * Check-in comments.
8 * [./embeddeddoc.wiki | Embedded documentation] files whose
9 name ends in "wiki".
 
10
11 The [/wiki_rules | formatting rules] for fossil wiki
12 are designed to be simple and intuitive. The idea is that wiki provides
13 paragraph breaks, numbered and bulleted lists, and hyperlinking for
14 simple documents together with a safe subset of HTML for more complex
15
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -5,10 +5,11 @@
5 * Stand-alone wiki pages.
6 * Description and comments in [./bugtheory.wiki | bug reports].
7 * Check-in comments.
8 * [./embeddeddoc.wiki | Embedded documentation] files whose
9 name ends in "wiki".
10 * [./event.wiki | Event descriptions].
11
12 The [/wiki_rules | formatting rules] for fossil wiki
13 are designed to be simple and intuitive. The idea is that wiki provides
14 paragraph breaks, numbered and bulleted lists, and hyperlinking for
15 simple documents together with a safe subset of HTML for more complex
16

Keyboard Shortcuts

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