Fossil SCM

merge trunk

jan.nijtmans 2015-01-08 14:40 cleanX merge
Commit 4105aed80d9077456057b2f02d7403f623ed18d6
+1 -1
--- src/allrepo.c
+++ src/allrepo.c
@@ -76,11 +76,11 @@
7676
7777
7878
/*
7979
** COMMAND: all
8080
**
81
-** Usage: %fossil all (changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync)
81
+** Usage: %fossil all SUBCOMMAND ...
8282
**
8383
** The ~/.fossil file records the location of all repositories for a
8484
** user. This command performs certain operations on all repositories
8585
** that can be useful before or after a period of disconnected operation.
8686
**
8787
--- src/allrepo.c
+++ src/allrepo.c
@@ -76,11 +76,11 @@
76
77
78 /*
79 ** COMMAND: all
80 **
81 ** Usage: %fossil all (changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync)
82 **
83 ** The ~/.fossil file records the location of all repositories for a
84 ** user. This command performs certain operations on all repositories
85 ** that can be useful before or after a period of disconnected operation.
86 **
87
--- src/allrepo.c
+++ src/allrepo.c
@@ -76,11 +76,11 @@
76
77
78 /*
79 ** COMMAND: all
80 **
81 ** Usage: %fossil all SUBCOMMAND ...
82 **
83 ** The ~/.fossil file records the location of all repositories for a
84 ** user. This command performs certain operations on all repositories
85 ** that can be useful before or after a period of disconnected operation.
86 **
87
+153 -38
--- src/branch.c
+++ src/branch.c
@@ -179,47 +179,67 @@
179179
180180
/* Do an autosync push, if requested */
181181
if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1));
182182
}
183183
184
+#if INTERFACE
185
+/*
186
+** Allows bits in the mBplqFlags parameter to branch_prepare_list_query().
187
+*/
188
+#define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */
189
+#define BRL_OPEN_ONLY 0x002 /* Show only open branches */
190
+#define BRL_BOTH 0x003 /* Show both open and closed branches */
191
+#define BRL_OPEN_CLOSED_MASK 0x003
192
+#define BRL_MTIME 0x004 /* Include lastest check-in time */
193
+#dfeine BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/
194
+
195
+#endif /* INTERFACE */
196
+
184197
/*
185198
** Prepare a query that will list branches.
186199
**
187200
** If (which<0) then the query pulls only closed branches. If
188201
** (which>0) then the query pulls all (closed and opened)
189202
** branches. Else the query pulls currently-opened branches.
190203
*/
191
-void branch_prepare_list_query(Stmt *pQuery, int which ){
192
- if( which < 0 ){
193
- db_prepare(pQuery,
194
- "SELECT value FROM tagxref"
195
- " WHERE tagid=%d AND value NOT NULL "
196
- "EXCEPT "
197
- "SELECT value FROM tagxref"
198
- " WHERE tagid=%d"
199
- " AND rid IN leaf"
200
- " AND NOT %z"
201
- " ORDER BY value COLLATE nocase /*sort*/",
202
- TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
203
- );
204
- }else if( which>0 ){
205
- db_prepare(pQuery,
206
- "SELECT DISTINCT value FROM tagxref"
207
- " WHERE tagid=%d AND value NOT NULL"
208
- " AND rid IN leaf"
209
- " ORDER BY value COLLATE nocase /*sort*/",
210
- TAG_BRANCH
211
- );
212
- }else{
213
- db_prepare(pQuery,
214
- "SELECT DISTINCT value FROM tagxref"
215
- " WHERE tagid=%d AND value NOT NULL"
216
- " AND rid IN leaf"
217
- " AND NOT %z"
218
- " ORDER BY value COLLATE nocase /*sort*/",
219
- TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
220
- );
204
+void branch_prepare_list_query(Stmt *pQuery, int brFlags){
205
+ switch( brFlags & BRL_OPEN_CLOSED_MASK ){
206
+ case BRL_CLOSED_ONLY: {
207
+ db_prepare(pQuery,
208
+ "SELECT value FROM tagxref"
209
+ " WHERE tagid=%d AND value NOT NULL "
210
+ "EXCEPT "
211
+ "SELECT value FROM tagxref"
212
+ " WHERE tagid=%d"
213
+ " AND rid IN leaf"
214
+ " AND NOT %z"
215
+ " ORDER BY value COLLATE nocase /*sort*/",
216
+ TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
217
+ );
218
+ break;
219
+ }
220
+ case BRL_BOTH: {
221
+ db_prepare(pQuery,
222
+ "SELECT DISTINCT value FROM tagxref"
223
+ " WHERE tagid=%d AND value NOT NULL"
224
+ " AND rid IN leaf"
225
+ " ORDER BY value COLLATE nocase /*sort*/",
226
+ TAG_BRANCH
227
+ );
228
+ break;
229
+ }
230
+ case BRL_OPEN_ONLY: {
231
+ db_prepare(pQuery,
232
+ "SELECT DISTINCT value FROM tagxref"
233
+ " WHERE tagid=%d AND value NOT NULL"
234
+ " AND rid IN leaf"
235
+ " AND NOT %z"
236
+ " ORDER BY value COLLATE nocase /*sort*/",
237
+ TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
238
+ );
239
+ break;
240
+ }
221241
}
222242
}
223243
224244
225245
/*
@@ -260,19 +280,20 @@
260280
branch_new();
261281
}else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
262282
Stmt q;
263283
int vid;
264284
char *zCurrent = 0;
265
- int showAll = find_option("all","a",0)!=0;
266
- int showClosed = find_option("closed","c",0)!=0;
285
+ int brFlags = BRL_OPEN_ONLY;
286
+ if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
287
+ if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
267288
268289
if( g.localOpen ){
269290
vid = db_lget_int("checkout", 0);
270291
zCurrent = db_text(0, "SELECT value FROM tagxref"
271292
" WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
272293
}
273
- branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
294
+ branch_prepare_list_query(&q, brFlags);
274295
while( db_step(&q)==SQLITE_ROW ){
275296
const char *zBr = db_column_text(&q, 0);
276297
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
277298
fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
278299
}
@@ -280,36 +301,130 @@
280301
}else{
281302
fossil_fatal("branch subcommand should be one of: "
282303
"new list ls");
283304
}
284305
}
306
+
307
+static char brlistQuery[] =
308
+@ SELECT
309
+@ tagxref.value,
310
+@ max(event.mtime),
311
+@ EXISTS(SELECT 1 FROM tagxref AS tx
312
+@ WHERE tx.rid=tagxref.rid
313
+@ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed')
314
+@ AND tx.tagtype>0),
315
+@ (SELECT tagxref.value
316
+@ FROM plink CROSS JOIN tagxref
317
+@ WHERE plink.pid=event.objid
318
+@ AND tagxref.rid=plink.cid
319
+@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
320
+@ AND tagtype>0),
321
+@ count(*),
322
+@ (SELECT uuid FROM blob WHERE rid=tagxref.rid)
323
+@ FROM tagxref, tag, event
324
+@ WHERE tagxref.tagid=tag.tagid
325
+@ AND tagxref.tagtype>0
326
+@ AND tag.tagname='branch'
327
+@ AND event.objid=tagxref.rid
328
+@ GROUP BY 1
329
+@ ORDER BY 2 DESC;
330
+;
331
+
332
+/*
333
+** This is the new-style branch-list page that shows the branch names
334
+** together with their ages (time of last check-in) and whether or not
335
+** they are closed or merged to another branch.
336
+**
337
+** Control jumps to this routine from brlist_page() (the /brlist handler)
338
+** if there are no query parameters.
339
+*/
340
+static void new_brlist_page(void){
341
+ Stmt q;
342
+ double rNow;
343
+ login_check_credentials();
344
+ if( !g.perm.Read ){ login_needed(); return; }
345
+ style_header("Branches");
346
+ login_anonymous_available();
347
+
348
+ db_prepare(&q, brlistQuery/*works-like:""*/);
349
+ rNow = db_double(0.0, "SELECT julianday('now')");
350
+ @ <div class="brlist"><table id="branchlisttable">
351
+ @ <thead><tr>
352
+ @ <th>Branch Name</th>
353
+ @ <th>Age</th>
354
+ @ <th>Checkins</th>
355
+ @ <th>Status</th>
356
+ @ <th>Resolution</th>
357
+ @ </tr></thead><tbody>
358
+ while( db_step(&q)==SQLITE_ROW ){
359
+ const char *zBranch = db_column_text(&q, 0);
360
+ double rMtime = db_column_double(&q, 1);
361
+ int isClosed = db_column_int(&q, 2);
362
+ const char *zMergeTo = db_column_text(&q, 3);
363
+ int nCkin = db_column_int(&q, 4);
364
+ const char *zLastCkin = db_column_text(&q, 5);
365
+ char *zAge = human_readable_age(rNow - rMtime);
366
+ sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
367
+ if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
368
+ @ <tr>
369
+ @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
370
+ @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
371
+ @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td>
372
+ fossil_free(zAge);
373
+ @ <td>%s(isClosed?"closed":"")</td>
374
+ if( zMergeTo ){
375
+ @ <td>merged into
376
+ @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td>
377
+ }else{
378
+ @ <td></td>
379
+ }
380
+ @ </tr>
381
+ }
382
+ @ </tbody></table></div>
383
+ db_finalize(&q);
384
+ output_table_sorting_javascript("branchlisttable","tkktt",2);
385
+ style_footer();
386
+}
285387
286388
/*
287389
** WEBPAGE: brlist
390
+** Show a list of branches
391
+** Query parameters:
288392
**
289
-** Show a timeline of all branches
393
+** all Show all branches
394
+** closed Show only closed branches
395
+** open Show only open branches (default behavior)
396
+** colortest Show all branches with automatic color
290397
*/
291398
void brlist_page(void){
292399
Stmt q;
293400
int cnt;
294401
int showClosed = P("closed")!=0;
295402
int showAll = P("all")!=0;
403
+ int showOpen = P("open")!=0;
296404
int colorTest = P("colortest")!=0;
405
+ int brFlags = BRL_OPEN_ONLY;
297406
407
+ if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){
408
+ new_brlist_page();
409
+ return;
410
+ }
298411
login_check_credentials();
299412
if( !g.perm.Read ){ login_needed(); return; }
300413
if( colorTest ){
301414
showClosed = 0;
302415
showAll = 1;
303416
}
417
+ if( showAll ) brFlags = BRL_BOTH;
418
+ if( showClosed ) brFlags = BRL_CLOSED_ONLY;
304419
305420
style_header("%s", showClosed ? "Closed Branches" :
306421
showAll ? "All Branches" : "Open Branches");
307422
style_submenu_element("Timeline", "Timeline", "brtimeline");
308423
if( showClosed ){
309424
style_submenu_element("All", "All", "brlist?all");
310
- style_submenu_element("Open","Open","brlist");
425
+ style_submenu_element("Open","Open","brlist?open");
311426
}else if( showAll ){
312427
style_submenu_element("Closed", "Closed", "brlist?closed");
313428
style_submenu_element("Open","Open","brlist");
314429
}else{
315430
style_submenu_element("All", "All", "brlist?all");
@@ -335,21 +450,21 @@
335450
@ Closed branches are fixed and do not change (unless they are first
336451
@ reopened).</li>
337452
@ </ol>
338453
style_sidebox_end();
339454
340
- branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
455
+ branch_prepare_list_query(&q, brFlags);
341456
cnt = 0;
342457
while( db_step(&q)==SQLITE_ROW ){
343458
const char *zBr = db_column_text(&q, 0);
344459
if( cnt==0 ){
345460
if( colorTest ){
346461
@ <h2>Default background colors for all branches:</h2>
462
+ }else if( showClosed ){
463
+ @ <h2>Closed Branches:</h2>
347464
}else if( showAll ){
348465
@ <h2>All Branches:</h2>
349
- }else if( showClosed ){
350
- @ <h2>Closed Branches:</h2>
351466
}else{
352467
@ <h2>Open Branches:</h2>
353468
}
354469
@ <ul>
355470
cnt++;
356471
--- src/branch.c
+++ src/branch.c
@@ -179,47 +179,67 @@
179
180 /* Do an autosync push, if requested */
181 if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1));
182 }
183
 
 
 
 
 
 
 
 
 
 
 
 
 
184 /*
185 ** Prepare a query that will list branches.
186 **
187 ** If (which<0) then the query pulls only closed branches. If
188 ** (which>0) then the query pulls all (closed and opened)
189 ** branches. Else the query pulls currently-opened branches.
190 */
191 void branch_prepare_list_query(Stmt *pQuery, int which ){
192 if( which < 0 ){
193 db_prepare(pQuery,
194 "SELECT value FROM tagxref"
195 " WHERE tagid=%d AND value NOT NULL "
196 "EXCEPT "
197 "SELECT value FROM tagxref"
198 " WHERE tagid=%d"
199 " AND rid IN leaf"
200 " AND NOT %z"
201 " ORDER BY value COLLATE nocase /*sort*/",
202 TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
203 );
204 }else if( which>0 ){
205 db_prepare(pQuery,
206 "SELECT DISTINCT value FROM tagxref"
207 " WHERE tagid=%d AND value NOT NULL"
208 " AND rid IN leaf"
209 " ORDER BY value COLLATE nocase /*sort*/",
210 TAG_BRANCH
211 );
212 }else{
213 db_prepare(pQuery,
214 "SELECT DISTINCT value FROM tagxref"
215 " WHERE tagid=%d AND value NOT NULL"
216 " AND rid IN leaf"
217 " AND NOT %z"
218 " ORDER BY value COLLATE nocase /*sort*/",
219 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
220 );
 
 
 
 
 
 
 
221 }
222 }
223
224
225 /*
@@ -260,19 +280,20 @@
260 branch_new();
261 }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
262 Stmt q;
263 int vid;
264 char *zCurrent = 0;
265 int showAll = find_option("all","a",0)!=0;
266 int showClosed = find_option("closed","c",0)!=0;
 
267
268 if( g.localOpen ){
269 vid = db_lget_int("checkout", 0);
270 zCurrent = db_text(0, "SELECT value FROM tagxref"
271 " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
272 }
273 branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
274 while( db_step(&q)==SQLITE_ROW ){
275 const char *zBr = db_column_text(&q, 0);
276 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
277 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
278 }
@@ -280,36 +301,130 @@
280 }else{
281 fossil_fatal("branch subcommand should be one of: "
282 "new list ls");
283 }
284 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
286 /*
287 ** WEBPAGE: brlist
 
 
288 **
289 ** Show a timeline of all branches
 
 
 
290 */
291 void brlist_page(void){
292 Stmt q;
293 int cnt;
294 int showClosed = P("closed")!=0;
295 int showAll = P("all")!=0;
 
296 int colorTest = P("colortest")!=0;
 
297
 
 
 
 
298 login_check_credentials();
299 if( !g.perm.Read ){ login_needed(); return; }
300 if( colorTest ){
301 showClosed = 0;
302 showAll = 1;
303 }
 
 
304
305 style_header("%s", showClosed ? "Closed Branches" :
306 showAll ? "All Branches" : "Open Branches");
307 style_submenu_element("Timeline", "Timeline", "brtimeline");
308 if( showClosed ){
309 style_submenu_element("All", "All", "brlist?all");
310 style_submenu_element("Open","Open","brlist");
311 }else if( showAll ){
312 style_submenu_element("Closed", "Closed", "brlist?closed");
313 style_submenu_element("Open","Open","brlist");
314 }else{
315 style_submenu_element("All", "All", "brlist?all");
@@ -335,21 +450,21 @@
335 @ Closed branches are fixed and do not change (unless they are first
336 @ reopened).</li>
337 @ </ol>
338 style_sidebox_end();
339
340 branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
341 cnt = 0;
342 while( db_step(&q)==SQLITE_ROW ){
343 const char *zBr = db_column_text(&q, 0);
344 if( cnt==0 ){
345 if( colorTest ){
346 @ <h2>Default background colors for all branches:</h2>
 
 
347 }else if( showAll ){
348 @ <h2>All Branches:</h2>
349 }else if( showClosed ){
350 @ <h2>Closed Branches:</h2>
351 }else{
352 @ <h2>Open Branches:</h2>
353 }
354 @ <ul>
355 cnt++;
356
--- src/branch.c
+++ src/branch.c
@@ -179,47 +179,67 @@
179
180 /* Do an autosync push, if requested */
181 if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1));
182 }
183
184 #if INTERFACE
185 /*
186 ** Allows bits in the mBplqFlags parameter to branch_prepare_list_query().
187 */
188 #define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */
189 #define BRL_OPEN_ONLY 0x002 /* Show only open branches */
190 #define BRL_BOTH 0x003 /* Show both open and closed branches */
191 #define BRL_OPEN_CLOSED_MASK 0x003
192 #define BRL_MTIME 0x004 /* Include lastest check-in time */
193 #dfeine BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/
194
195 #endif /* INTERFACE */
196
197 /*
198 ** Prepare a query that will list branches.
199 **
200 ** If (which<0) then the query pulls only closed branches. If
201 ** (which>0) then the query pulls all (closed and opened)
202 ** branches. Else the query pulls currently-opened branches.
203 */
204 void branch_prepare_list_query(Stmt *pQuery, int brFlags){
205 switch( brFlags & BRL_OPEN_CLOSED_MASK ){
206 case BRL_CLOSED_ONLY: {
207 db_prepare(pQuery,
208 "SELECT value FROM tagxref"
209 " WHERE tagid=%d AND value NOT NULL "
210 "EXCEPT "
211 "SELECT value FROM tagxref"
212 " WHERE tagid=%d"
213 " AND rid IN leaf"
214 " AND NOT %z"
215 " ORDER BY value COLLATE nocase /*sort*/",
216 TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
217 );
218 break;
219 }
220 case BRL_BOTH: {
221 db_prepare(pQuery,
222 "SELECT DISTINCT value FROM tagxref"
223 " WHERE tagid=%d AND value NOT NULL"
224 " AND rid IN leaf"
225 " ORDER BY value COLLATE nocase /*sort*/",
226 TAG_BRANCH
227 );
228 break;
229 }
230 case BRL_OPEN_ONLY: {
231 db_prepare(pQuery,
232 "SELECT DISTINCT value FROM tagxref"
233 " WHERE tagid=%d AND value NOT NULL"
234 " AND rid IN leaf"
235 " AND NOT %z"
236 " ORDER BY value COLLATE nocase /*sort*/",
237 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
238 );
239 break;
240 }
241 }
242 }
243
244
245 /*
@@ -260,19 +280,20 @@
280 branch_new();
281 }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
282 Stmt q;
283 int vid;
284 char *zCurrent = 0;
285 int brFlags = BRL_OPEN_ONLY;
286 if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
287 if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
288
289 if( g.localOpen ){
290 vid = db_lget_int("checkout", 0);
291 zCurrent = db_text(0, "SELECT value FROM tagxref"
292 " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
293 }
294 branch_prepare_list_query(&q, brFlags);
295 while( db_step(&q)==SQLITE_ROW ){
296 const char *zBr = db_column_text(&q, 0);
297 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
298 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
299 }
@@ -280,36 +301,130 @@
301 }else{
302 fossil_fatal("branch subcommand should be one of: "
303 "new list ls");
304 }
305 }
306
307 static char brlistQuery[] =
308 @ SELECT
309 @ tagxref.value,
310 @ max(event.mtime),
311 @ EXISTS(SELECT 1 FROM tagxref AS tx
312 @ WHERE tx.rid=tagxref.rid
313 @ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed')
314 @ AND tx.tagtype>0),
315 @ (SELECT tagxref.value
316 @ FROM plink CROSS JOIN tagxref
317 @ WHERE plink.pid=event.objid
318 @ AND tagxref.rid=plink.cid
319 @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
320 @ AND tagtype>0),
321 @ count(*),
322 @ (SELECT uuid FROM blob WHERE rid=tagxref.rid)
323 @ FROM tagxref, tag, event
324 @ WHERE tagxref.tagid=tag.tagid
325 @ AND tagxref.tagtype>0
326 @ AND tag.tagname='branch'
327 @ AND event.objid=tagxref.rid
328 @ GROUP BY 1
329 @ ORDER BY 2 DESC;
330 ;
331
332 /*
333 ** This is the new-style branch-list page that shows the branch names
334 ** together with their ages (time of last check-in) and whether or not
335 ** they are closed or merged to another branch.
336 **
337 ** Control jumps to this routine from brlist_page() (the /brlist handler)
338 ** if there are no query parameters.
339 */
340 static void new_brlist_page(void){
341 Stmt q;
342 double rNow;
343 login_check_credentials();
344 if( !g.perm.Read ){ login_needed(); return; }
345 style_header("Branches");
346 login_anonymous_available();
347
348 db_prepare(&q, brlistQuery/*works-like:""*/);
349 rNow = db_double(0.0, "SELECT julianday('now')");
350 @ <div class="brlist"><table id="branchlisttable">
351 @ <thead><tr>
352 @ <th>Branch Name</th>
353 @ <th>Age</th>
354 @ <th>Checkins</th>
355 @ <th>Status</th>
356 @ <th>Resolution</th>
357 @ </tr></thead><tbody>
358 while( db_step(&q)==SQLITE_ROW ){
359 const char *zBranch = db_column_text(&q, 0);
360 double rMtime = db_column_double(&q, 1);
361 int isClosed = db_column_int(&q, 2);
362 const char *zMergeTo = db_column_text(&q, 3);
363 int nCkin = db_column_int(&q, 4);
364 const char *zLastCkin = db_column_text(&q, 5);
365 char *zAge = human_readable_age(rNow - rMtime);
366 sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
367 if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
368 @ <tr>
369 @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
370 @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
371 @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td>
372 fossil_free(zAge);
373 @ <td>%s(isClosed?"closed":"")</td>
374 if( zMergeTo ){
375 @ <td>merged into
376 @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td>
377 }else{
378 @ <td></td>
379 }
380 @ </tr>
381 }
382 @ </tbody></table></div>
383 db_finalize(&q);
384 output_table_sorting_javascript("branchlisttable","tkktt",2);
385 style_footer();
386 }
387
388 /*
389 ** WEBPAGE: brlist
390 ** Show a list of branches
391 ** Query parameters:
392 **
393 ** all Show all branches
394 ** closed Show only closed branches
395 ** open Show only open branches (default behavior)
396 ** colortest Show all branches with automatic color
397 */
398 void brlist_page(void){
399 Stmt q;
400 int cnt;
401 int showClosed = P("closed")!=0;
402 int showAll = P("all")!=0;
403 int showOpen = P("open")!=0;
404 int colorTest = P("colortest")!=0;
405 int brFlags = BRL_OPEN_ONLY;
406
407 if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){
408 new_brlist_page();
409 return;
410 }
411 login_check_credentials();
412 if( !g.perm.Read ){ login_needed(); return; }
413 if( colorTest ){
414 showClosed = 0;
415 showAll = 1;
416 }
417 if( showAll ) brFlags = BRL_BOTH;
418 if( showClosed ) brFlags = BRL_CLOSED_ONLY;
419
420 style_header("%s", showClosed ? "Closed Branches" :
421 showAll ? "All Branches" : "Open Branches");
422 style_submenu_element("Timeline", "Timeline", "brtimeline");
423 if( showClosed ){
424 style_submenu_element("All", "All", "brlist?all");
425 style_submenu_element("Open","Open","brlist?open");
426 }else if( showAll ){
427 style_submenu_element("Closed", "Closed", "brlist?closed");
428 style_submenu_element("Open","Open","brlist");
429 }else{
430 style_submenu_element("All", "All", "brlist?all");
@@ -335,21 +450,21 @@
450 @ Closed branches are fixed and do not change (unless they are first
451 @ reopened).</li>
452 @ </ol>
453 style_sidebox_end();
454
455 branch_prepare_list_query(&q, brFlags);
456 cnt = 0;
457 while( db_step(&q)==SQLITE_ROW ){
458 const char *zBr = db_column_text(&q, 0);
459 if( cnt==0 ){
460 if( colorTest ){
461 @ <h2>Default background colors for all branches:</h2>
462 }else if( showClosed ){
463 @ <h2>Closed Branches:</h2>
464 }else if( showAll ){
465 @ <h2>All Branches:</h2>
 
 
466 }else{
467 @ <h2>Open Branches:</h2>
468 }
469 @ <ul>
470 cnt++;
471
+394 -192
--- src/browse.c
+++ src/browse.c
@@ -304,89 +304,206 @@
304304
305305
/*
306306
** A single line of the file hierarchy
307307
*/
308308
struct FileTreeNode {
309
- FileTreeNode *pNext; /* Next line in sequence */
310
- FileTreeNode *pPrev; /* Previous line */
311
- FileTreeNode *pParent; /* Directory containing this line */
309
+ FileTreeNode *pNext; /* Next entry in an ordered list of them all */
310
+ FileTreeNode *pParent; /* Directory containing this entry */
311
+ FileTreeNode *pSibling; /* Next element in the same subdirectory */
312
+ FileTreeNode *pChild; /* List of child nodes */
313
+ FileTreeNode *pLastChild; /* Last child on the pChild list */
312314
char *zName; /* Name of this entry. The "tail" */
313315
char *zFullName; /* Full pathname of this entry */
314316
char *zUuid; /* SHA1 hash of this file. May be NULL. */
317
+ double mtime; /* Modification time for this entry */
315318
unsigned nFullName; /* Length of zFullName */
316319
unsigned iLevel; /* Levels of parent directories */
317
- u8 isDir; /* True if there are children */
318
- u8 isLast; /* True if this is the last child of its parent */
319320
};
320321
321322
/*
322323
** A complete file hierarchy
323324
*/
324325
struct FileTree {
325326
FileTreeNode *pFirst; /* First line of the list */
326327
FileTreeNode *pLast; /* Last line of the list */
328
+ FileTreeNode *pLastTop; /* Last top-level node */
327329
};
328330
329331
/*
330332
** Add one or more new FileTreeNodes to the FileTree object so that the
331
-** leaf object zPathname is at the end of the node list
333
+** leaf object zPathname is at the end of the node list.
334
+**
335
+** The caller invokes this routine once for each leaf node (each file
336
+** as opposed to each directory). This routine fills in any missing
337
+** intermediate nodes automatically.
338
+**
339
+** When constructing a list of FileTreeNodes, all entries that have
340
+** a common directory prefix must be added consecutively in order for
341
+** the tree to be constructed properly.
332342
*/
333343
static void tree_add_node(
334344
FileTree *pTree, /* Tree into which nodes are added */
335345
const char *zPath, /* The full pathname of file to add */
336
- const char *zUuid /* UUID of the file. Might be NULL. */
346
+ const char *zUuid, /* UUID of the file. Might be NULL. */
347
+ double mtime /* Modification time for this entry */
337348
){
338349
int i;
339
- FileTreeNode *pParent;
340
- FileTreeNode *pChild;
350
+ FileTreeNode *pParent; /* Parent (directory) of the next node to insert */
341351
342
- pChild = pTree->pLast;
343
- pParent = pChild ? pChild->pParent : 0;
352
+ /* Make pParent point to the most recent ancestor of zPath, or
353
+ ** NULL if there are no prior entires that are a container for zPath.
354
+ */
355
+ pParent = pTree->pLast;
344356
while( pParent!=0 &&
345357
( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0
346358
|| zPath[pParent->nFullName]!='/' )
347359
){
348
- pChild = pParent;
349
- pParent = pChild->pParent;
360
+ pParent = pParent->pParent;
350361
}
351362
i = pParent ? pParent->nFullName+1 : 0;
352
- if( pChild ) pChild->isLast = 0;
353363
while( zPath[i] ){
354364
FileTreeNode *pNew;
355365
int iStart = i;
356366
int nByte;
357367
while( zPath[i] && zPath[i]!='/' ){ i++; }
358368
nByte = sizeof(*pNew) + i + 1;
359369
if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1;
360370
pNew = fossil_malloc( nByte );
371
+ memset(pNew, 0, sizeof(*pNew));
361372
pNew->zFullName = (char*)&pNew[1];
362373
memcpy(pNew->zFullName, zPath, i);
363374
pNew->zFullName[i] = 0;
364375
pNew->nFullName = i;
365376
if( zUuid!=0 && zPath[i]==0 ){
366377
pNew->zUuid = pNew->zFullName + i + 1;
367378
memcpy(pNew->zUuid, zUuid, UUID_SIZE+1);
368
- }else{
369
- pNew->zUuid = 0;
370379
}
371380
pNew->zName = pNew->zFullName + iStart;
372381
if( pTree->pLast ){
373382
pTree->pLast->pNext = pNew;
374383
}else{
375384
pTree->pFirst = pNew;
376385
}
377
- pNew->pPrev = pTree->pLast;
378
- pNew->pNext = 0;
386
+ pTree->pLast = pNew;
379387
pNew->pParent = pParent;
380
- pTree->pLast = pNew;
381
- pNew->iLevel = pParent ? pParent->iLevel+1 : 0;
382
- pNew->isDir = zPath[i]=='/';
383
- pNew->isLast = 1;
388
+ if( pParent ){
389
+ if( pParent->pChild ){
390
+ pParent->pLastChild->pSibling = pNew;
391
+ }else{
392
+ pParent->pChild = pNew;
393
+ }
394
+ pNew->iLevel = pParent->iLevel + 1;
395
+ pParent->pLastChild = pNew;
396
+ }else{
397
+ if( pTree->pLastTop ) pTree->pLastTop->pSibling = pNew;
398
+ pTree->pLastTop = pNew;
399
+ }
400
+ pNew->mtime = mtime;
384401
while( zPath[i]=='/' ){ i++; }
385402
pParent = pNew;
386403
}
404
+ while( pParent && pParent->pParent ){
405
+ if( pParent->pParent->mtime < pParent->mtime ){
406
+ pParent->pParent->mtime = pParent->mtime;
407
+ }
408
+ pParent = pParent->pParent;
409
+ }
410
+}
411
+
412
+/* Comparison function for two FileTreeNode objects. Sort first by
413
+** mtime (larger numbers first) and then by zName (smaller names first).
414
+**
415
+** Return negative if pLeft<pRight.
416
+** Return positive if pLeft>pRight.
417
+** Return zero if pLeft==pRight.
418
+*/
419
+static int compareNodes(FileTreeNode *pLeft, FileTreeNode *pRight){
420
+ if( pLeft->mtime>pRight->mtime ) return -1;
421
+ if( pLeft->mtime<pRight->mtime ) return +1;
422
+ return fossil_stricmp(pLeft->zName, pRight->zName);
423
+}
424
+
425
+/* Merge together two sorted lists of FileTreeNode objects */
426
+static FileTreeNode *mergeNodes(FileTreeNode *pLeft, FileTreeNode *pRight){
427
+ FileTreeNode *pEnd;
428
+ FileTreeNode base;
429
+ pEnd = &base;
430
+ while( pLeft && pRight ){
431
+ if( compareNodes(pLeft,pRight)<=0 ){
432
+ pEnd = pEnd->pSibling = pLeft;
433
+ pLeft = pLeft->pSibling;
434
+ }else{
435
+ pEnd = pEnd->pSibling = pRight;
436
+ pRight = pRight->pSibling;
437
+ }
438
+ }
439
+ if( pLeft ){
440
+ pEnd->pSibling = pLeft;
441
+ }else{
442
+ pEnd->pSibling = pRight;
443
+ }
444
+ return base.pSibling;
445
+}
446
+
447
+/* Sort a list of FileTreeNode objects in mtime order. */
448
+static FileTreeNode *sortNodesByMtime(FileTreeNode *p){
449
+ FileTreeNode *a[30];
450
+ FileTreeNode *pX;
451
+ int i;
452
+
453
+ memset(a, 0, sizeof(a));
454
+ while( p ){
455
+ pX = p;
456
+ p = pX->pSibling;
457
+ pX->pSibling = 0;
458
+ for(i=0; i<count(a)-1 && a[i]!=0; i++){
459
+ pX = mergeNodes(a[i], pX);
460
+ a[i] = 0;
461
+ }
462
+ a[i] = mergeNodes(a[i], pX);
463
+ }
464
+ pX = 0;
465
+ for(i=0; i<count(a); i++){
466
+ pX = mergeNodes(a[i], pX);
467
+ }
468
+ return pX;
469
+}
470
+
471
+/* Sort an entire FileTreeNode tree by mtime
472
+**
473
+** This routine invalidates the following fields:
474
+**
475
+** FileTreeNode.pLastChild
476
+** FileTreeNode.pNext
477
+**
478
+** Use relinkTree to reconnect the pNext pointers.
479
+*/
480
+static FileTreeNode *sortTreeByMtime(FileTreeNode *p){
481
+ FileTreeNode *pX;
482
+ for(pX=p; pX; pX=pX->pSibling){
483
+ if( pX->pChild ) pX->pChild = sortTreeByMtime(pX->pChild);
484
+ }
485
+ return sortNodesByMtime(p);
486
+}
487
+
488
+/* Reconstruct the FileTree by reconnecting the FileTreeNode.pNext
489
+** fields in sequential order.
490
+*/
491
+static void relinkTree(FileTree *pTree, FileTreeNode *pRoot){
492
+ while( pRoot ){
493
+ if( pTree->pLast ){
494
+ pTree->pLast->pNext = pRoot;
495
+ }else{
496
+ pTree->pFirst = pRoot;
497
+ }
498
+ pTree->pLast = pRoot;
499
+ if( pRoot->pChild ) relinkTree(pTree, pRoot->pChild);
500
+ pRoot = pRoot->pSibling;
501
+ }
502
+ if( pTree->pLast ) pTree->pLast->pNext = 0;
387503
}
504
+
388505
389506
/*
390507
** WEBPAGE: tree
391508
**
392509
** Query parameters:
@@ -394,19 +511,23 @@
394511
** name=PATH Directory to display. Optional
395512
** ci=LABEL Show only files in this check-in. Optional.
396513
** re=REGEXP Show only files matching REGEXP. Optional.
397514
** expand Begin with the tree fully expanded.
398515
** nofiles Show directories (folders) only. Omit files.
516
+** mtime Order directory elements by decreasing mtime
399517
*/
400518
void page_tree(void){
401519
char *zD = fossil_strdup(P("name"));
402520
int nD = zD ? strlen(zD)+1 : 0;
403521
const char *zCI = P("ci");
404522
int rid = 0;
405523
char *zUuid = 0;
406524
Blob dirname;
407525
Manifest *pM = 0;
526
+ double rNow = 0;
527
+ char *zNow = 0;
528
+ int useMtime = atoi(PD("mtime","0"));
408529
int nFile = 0; /* Number of files (or folders with "nofiles") */
409530
int linkTrunk = 1; /* include link to "trunk" */
410531
int linkTip = 1; /* include link to "tip" */
411532
const char *zRE; /* the value for the re=REGEXP query parameter */
412533
const char *zObjType; /* "files" by default or "folders" for "nofiles" */
@@ -464,14 +585,21 @@
464585
int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
465586
linkTrunk = trunkRid && rid != trunkRid;
466587
linkTip = rid != symbolic_name_to_rid("tip", "ci");
467588
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
468589
url_add_parameter(&sURI, "ci", zCI);
590
+ rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
591
+ zNow = db_text("", "SELECT datetime(mtime,'localtime')"
592
+ " FROM event WHERE objid=%d", rid);
469593
}else{
470594
zCI = 0;
471595
}
472596
}
597
+ if( zCI==0 ){
598
+ rNow = db_double(0.0, "SELECT max(mtime) FROM event");
599
+ zNow = db_text("", "SELECT datetime(max(mtime),'localtime') FROM event");
600
+ }
473601
474602
/* Compute the title of the page */
475603
blob_zero(&dirname);
476604
if( zD ){
477605
url_add_parameter(&sURI, "name", zD);
@@ -483,10 +611,18 @@
483611
}else{
484612
if( zRE ){
485613
blob_appendf(&dirname, "matching \"%s\"", zRE);
486614
}
487615
}
616
+ if( useMtime ){
617
+ style_submenu_element("Sort By Filename","Sort By Filename", "%s",
618
+ url_render(&sURI, 0, 0, 0, 0));
619
+ url_add_parameter(&sURI, "mtime", "1");
620
+ }else{
621
+ style_submenu_element("Sort By Time","Sort By Time", "%s",
622
+ url_render(&sURI, "mtime", "1", 0, 0));
623
+ }
488624
if( zCI ){
489625
style_submenu_element("All", "All", "%s",
490626
url_render(&sURI, "ci", 0, 0, 0));
491627
if( nD==0 && !showDirOnly ){
492628
style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
@@ -499,87 +635,82 @@
499635
}
500636
if( linkTip ){
501637
style_submenu_element("Tip", "Tip", "%s",
502638
url_render(&sURI, "ci", "tip", 0, 0));
503639
}
504
- if( !showDirOnly ){
505
- style_submenu_element("Flat-View", "Flat-View", "%s",
506
- url_render(&sURI, "type", "flat", 0, 0));
507
- }
508640
509641
/* Compute the file hierarchy.
510642
*/
511643
if( zCI ){
512
- Stmt ins, q;
513
- ManifestFile *pFile;
514
-
515
- db_multi_exec(
516
- "CREATE TEMP TABLE filelist("
517
- " x TEXT PRIMARY KEY COLLATE nocase,"
518
- " uuid TEXT"
519
- ") WITHOUT ROWID;"
644
+ Stmt q;
645
+ compute_fileage(rid, 0);
646
+ db_prepare(&q,
647
+ "SELECT filename.name, blob.uuid, fileage.mtime\n"
648
+ " FROM fileage, filename, blob\n"
649
+ " WHERE filename.fnid=fileage.fnid\n"
650
+ " AND blob.rid=fileage.fid\n"
651
+ " ORDER BY filename.name COLLATE nocase;"
520652
);
521
- db_prepare(&ins, "INSERT OR IGNORE INTO filelist VALUES(:f,:u)");
522
- manifest_file_rewind(pM);
523
- while( (pFile = manifest_file_next(pM,0))!=0 ){
524
- if( nD>0
525
- && (fossil_strncmp(pFile->zName, zD, nD-1)!=0
526
- || pFile->zName[nD-1]!='/')
527
- ){
528
- continue;
529
- }
530
- if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue;
531
- db_bind_text(&ins, ":f", pFile->zName);
532
- db_bind_text(&ins, ":u", pFile->zUuid);
533
- db_step(&ins);
534
- db_reset(&ins);
535
- }
536
- db_finalize(&ins);
537
- db_prepare(&q, "SELECT x, uuid FROM filelist ORDER BY x");
538653
while( db_step(&q)==SQLITE_ROW ){
539
- tree_add_node(&sTree, db_column_text(&q,0), db_column_text(&q,1));
654
+ const char *zFile = db_column_text(&q,0);
655
+ const char *zUuid = db_column_text(&q,1);
656
+ double mtime = db_column_double(&q,2);
657
+ if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue;
658
+ tree_add_node(&sTree, zFile, zUuid, mtime);
540659
nFile++;
541660
}
542661
db_finalize(&q);
543662
}else{
544663
Stmt q;
545
- db_prepare(&q, "SELECT name FROM filename ORDER BY name COLLATE nocase");
664
+ db_prepare(&q,
665
+ "SELECT filename.name, blob.uuid, max(event.mtime)\n"
666
+ " FROM filename, mlink, blob, event\n"
667
+ " WHERE mlink.fnid=filename.fnid\n"
668
+ " AND event.objid=mlink.mid\n"
669
+ " AND blob.rid=mlink.fid\n"
670
+ " GROUP BY 1 ORDER BY 1 COLLATE nocase");
546671
while( db_step(&q)==SQLITE_ROW ){
547
- const char *z = db_column_text(&q, 0);
548
- if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){
672
+ const char *zName = db_column_text(&q, 0);
673
+ const char *zUuid = db_column_text(&q,1);
674
+ double mtime = db_column_double(&q,2);
675
+ if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){
549676
continue;
550677
}
551
- if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue;
552
- tree_add_node(&sTree, z, 0);
678
+ if( pRE && re_match(pRE, (const u8*)zName, -1)==0 ) continue;
679
+ tree_add_node(&sTree, zName, zUuid, mtime);
553680
nFile++;
554681
}
555682
db_finalize(&q);
556683
}
557684
558685
if( showDirOnly ){
559686
for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
560
- if( p->isDir && p->nFullName>nD ) nFile++;
687
+ if( p->pChild!=0 && p->nFullName>nD ) nFile++;
561688
}
562
- zObjType = "folders";
689
+ zObjType = "Folders";
563690
style_submenu_element("Files","Files","%s",
564691
url_render(&sURI,"nofiles",0,0,0));
565692
}else{
566
- zObjType = "files";
693
+ zObjType = "Files";
567694
style_submenu_element("Folders","Folders","%s",
568695
url_render(&sURI,"nofiles","1",0,0));
569696
}
570697
571698
if( zCI ){
572
- @ <h2>%d(nFile) %s(zObjType) of check-in
699
+ @ <h2>%s(zObjType) from
573700
if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
574701
@ "%h(zCI)"
575702
}
576
- @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))</h2>
703
+ @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))
577704
}else{
578705
int n = db_int(0, "SELECT count(*) FROM plink");
579
- @ <h2>%d(nFile) %s(zObjType) from all %d(n) check-ins
580
- @ %s(blob_str(&dirname))</h2>
706
+ @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
707
+ }
708
+ if( useMtime ){
709
+ @ sorted by modification time</h2>
710
+ }else{
711
+ @ sorted by filename</h2>
581712
}
582713
583714
584715
/* Generate tree of lists.
585716
**
@@ -596,18 +727,33 @@
596727
if( nD ){
597728
@ <li class="dir last">
598729
}else{
599730
@ <li class="dir subdir last">
600731
}
732
+ @ <div class="filetreeline">
601733
@ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a>
734
+ if( zNow ){
735
+ @ <div class="filetreeage">%s(zNow)</div>
736
+ }
737
+ @ </div>
602738
@ <ul>
739
+ if( useMtime ){
740
+ p = sortTreeByMtime(sTree.pFirst);
741
+ memset(&sTree, 0, sizeof(sTree));
742
+ relinkTree(&sTree, p);
743
+ }
603744
for(p=sTree.pFirst, nDir=0; p; p=p->pNext){
604
- const char *zLastClass = p->isLast ? " last" : "";
605
- if( p->isDir ){
745
+ const char *zLastClass = p->pSibling==0 ? " last" : "";
746
+ if( p->pChild ){
606747
const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : "";
607
- @ <li class="dir%s(zSubdirClass)%s(zLastClass)">
748
+ @ <li class="dir%s(zSubdirClass)%s(zLastClass)"><div class="filetreeline">
608749
@ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a>
750
+ if( p->mtime>0.0 ){
751
+ char *zAge = human_readable_age(rNow - p->mtime);
752
+ @ <div class="filetreeage">%s(zAge)</div>
753
+ }
754
+ @ </div>
609755
if( startExpanded || p->nFullName<=nD ){
610756
@ <ul id="dir%d(nDir)">
611757
}else{
612758
@ <ul id="dir%d(nDir)" class="collapsed">
613759
}
@@ -614,17 +760,23 @@
614760
nDir++;
615761
}else if( !showDirOnly ){
616762
const char *zFileClass = fileext_class(p->zName);
617763
char *zLink;
618764
if( zCI ){
619
- zLink = href("%R/artifact/%s",p->zUuid);
765
+ zLink = href("%R/artifact/%.16s",p->zUuid);
620766
}else{
621767
zLink = href("%R/finfo?name=%T",p->zFullName);
622768
}
623
- @ <li class="%z(zFileClass)%s(zLastClass)">%z(zLink)%h(p->zName)</a>
769
+ @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
770
+ @ %z(zLink)%h(p->zName)</a>
771
+ if( p->mtime>0 ){
772
+ char *zAge = human_readable_age(rNow - p->mtime);
773
+ @ <div class="filetreeage">%s(zAge)</div>
774
+ }
775
+ @ </div>
624776
}
625
- if( p->isLast ){
777
+ if( p->pSibling==0 ){
626778
int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);
627779
while( nClose-- > 0 ){
628780
@ </ul>
629781
}
630782
}
@@ -687,16 +839,16 @@
687839
@ checkState();
688840
@ outer_ul.onclick = function(e){
689841
@ e = e || window.event;
690842
@ var a = e.target || e.srcElement;
691843
@ if( a.nodeName!='A' ) return true;
692
- @ if( a.parentNode==subdir ){
844
+ @ if( a.parentNode.parentNode==subdir ){
693845
@ toggleAll(outer_ul);
694846
@ return false;
695847
@ }
696848
@ if( !belowSubdir(a) ) return true;
697
- @ var ul = a.nextSibling;
849
+ @ var ul = a.parentNode.nextSibling;
698850
@ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling;
699851
@ if( !ul ) return true; /* This is a file link, not a directory */
700852
@ toggleDir(ul);
701853
@ return false;
702854
@ }
@@ -724,87 +876,115 @@
724876
}else{
725877
zClass = mprintf("file");
726878
}
727879
return zClass;
728880
}
881
+
882
+/*
883
+** SQL used to compute the age of all files in checkin :ckin whose
884
+** names match :glob
885
+*/
886
+static const char zComputeFileAgeSetup[] =
887
+@ CREATE TABLE IF NOT EXISTS temp.fileage(
888
+@ fnid INTEGER PRIMARY KEY,
889
+@ fid INTEGER,
890
+@ mid INTEGER,
891
+@ mtime DATETIME,
892
+@ pathname TEXT
893
+@ );
894
+@ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin;
895
+;
896
+
897
+static const char zComputeFileAgeRun[] =
898
+@ WITH RECURSIVE
899
+@ ckin(x) AS (VALUES(:ckin) UNION ALL
900
+@ SELECT pid FROM ckin, plink WHERE cid=x AND isprim)
901
+@ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname)
902
+@ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name
903
+@ FROM ckin, mlink, event, filename
904
+@ WHERE mlink.mid=ckin.x
905
+@ AND mlink.fnid IN (SELECT fnid FROM foci, filename
906
+@ WHERE foci.checkinID=:ckin
907
+@ AND filename.name=foci.filename
908
+@ AND filename.name GLOB :glob)
909
+@ AND filename.fnid=mlink.fnid
910
+@ AND event.objid=mlink.mid;
911
+;
912
+
729913
730914
/*
731915
** Look at all file containing in the version "vid". Construct a
732916
** temporary table named "fileage" that contains the file-id for each
733917
** files, the pathname, the check-in where the file was added, and the
734918
** mtime on that checkin. If zGlob and *zGlob then only files matching
735919
** the given glob are computed.
736920
*/
737921
int compute_fileage(int vid, const char* zGlob){
738
- Manifest *pManifest;
739
- ManifestFile *pFile;
740
- int nFile = 0;
741
- double vmtime;
742
- Stmt ins;
743
- Stmt q1, q2, q3;
744
- Stmt upd;
745
- if(zGlob && !*zGlob) zGlob = NULL;
746
- db_multi_exec(
747
- /*"DROP TABLE IF EXISTS temp.fileage;"*/
748
- "CREATE TEMP TABLE fileage("
749
- " fid INTEGER,"
750
- " mid INTEGER,"
751
- " mtime DATETIME,"
752
- " pathname TEXT"
753
- ");"
754
- "CREATE INDEX fileage_fid ON fileage(fid);"
755
- );
756
- pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0);
757
- if( pManifest==0 ) return 1;
758
- manifest_file_rewind(pManifest);
759
- db_prepare(&ins,
760
- "INSERT INTO temp.fileage(fid, pathname)"
761
- " SELECT rid, :path FROM blob WHERE uuid=:uuid"
762
- );
763
- while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
764
- if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue;
765
- db_bind_text(&ins, ":uuid", pFile->zUuid);
766
- db_bind_text(&ins, ":path", pFile->zName);
767
- db_step(&ins);
768
- db_reset(&ins);
769
- nFile++;
770
- }
771
- db_finalize(&ins);
772
- manifest_destroy(pManifest);
773
- db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid");
774
- db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime"
775
- " WHERE fid=:fid AND mid IS NULL");
776
- db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim");
777
- db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid");
778
- while( nFile>0 && vid>0 ){
779
- db_bind_int(&q3, ":vid", vid);
780
- if( db_step(&q3)==SQLITE_ROW ){
781
- vmtime = db_column_double(&q3, 0);
782
- }else{
783
- break;
784
- }
785
- db_reset(&q3);
786
- db_bind_int(&q1, ":mid", vid);
787
- db_bind_int(&upd, ":mid", vid);
788
- db_bind_double(&upd, ":vmtime", vmtime);
789
- while( db_step(&q1)==SQLITE_ROW ){
790
- db_bind_int(&upd, ":fid", db_column_int(&q1, 0));
791
- db_step(&upd);
792
- nFile -= db_changes();
793
- db_reset(&upd);
794
- }
795
- db_reset(&q1);
796
- db_bind_int(&q2, ":vid", vid);
797
- if( db_step(&q2)!=SQLITE_ROW ) break;
798
- vid = db_column_int(&q2, 0);
799
- db_reset(&q2);
800
- }
801
- db_finalize(&q1);
802
- db_finalize(&upd);
803
- db_finalize(&q2);
804
- db_finalize(&q3);
805
- return 0;
922
+ Stmt q;
923
+ db_multi_exec(zComputeFileAgeSetup /*works-like:"constant"*/);
924
+ db_prepare(&q, zComputeFileAgeRun /*works-like:"constant"*/);
925
+ db_bind_int(&q, ":ckin", vid);
926
+ db_bind_text(&q, ":glob", zGlob && zGlob[0] ? zGlob : "*");
927
+ db_exec(&q);
928
+ db_finalize(&q);
929
+ return 0;
930
+}
931
+
932
+/*
933
+** Render the number of days in rAge as a more human-readable time span.
934
+** Different units (seconds, minutes, hours, days, months, years) are
935
+** selected depending on the magnitude of rAge.
936
+**
937
+** The string returned is obtained from fossil_malloc() and should be
938
+** freed by the caller.
939
+*/
940
+char *human_readable_age(double rAge){
941
+ if( rAge*86400.0<120 ){
942
+ if( rAge*86400.0<1.0 ){
943
+ return mprintf("current");
944
+ }else{
945
+ return mprintf("%d seconds", (int)(rAge*86400.0));
946
+ }
947
+ }else if( rAge*1440.0<90 ){
948
+ return mprintf("%.1f minutes", rAge*1440.0);
949
+ }else if( rAge*24.0<36 ){
950
+ return mprintf("%.1f hours", rAge*24.0);
951
+ }else if( rAge<365.0 ){
952
+ return mprintf("%.1f days", rAge);
953
+ }else{
954
+ return mprintf("%.2f years", rAge/365.0);
955
+ }
956
+}
957
+
958
+/*
959
+** COMMAND: test-fileage
960
+**
961
+** Usage: %fossil test-fileage CHECKIN
962
+*/
963
+void test_fileage_cmd(void){
964
+ int mid;
965
+ Stmt q;
966
+ const char *zGlob = find_option("glob",0,1);
967
+ db_find_and_open_repository(0,0);
968
+ verify_all_options();
969
+ if( g.argc!=3 ) usage("test-fileage CHECKIN");
970
+ mid = name_to_typed_rid(g.argv[2],"ci");
971
+ compute_fileage(mid, zGlob);
972
+ db_prepare(&q,
973
+ "SELECT fid, mid, julianday('now') - mtime, pathname"
974
+ " FROM fileage"
975
+ );
976
+ while( db_step(&q)==SQLITE_ROW ){
977
+ char *zAge = human_readable_age(db_column_double(&q,2));
978
+ fossil_print("%8d %8d %16s %s\n",
979
+ db_column_int(&q,0),
980
+ db_column_int(&q,1),
981
+ zAge,
982
+ db_column_text(&q,3));
983
+ fossil_free(zAge);
984
+ }
985
+ db_finalize(&q);
806986
}
807987
808988
/*
809989
** WEBPAGE: fileage
810990
**
@@ -814,72 +994,94 @@
814994
** (e.g. *.c or *.txt).
815995
*/
816996
void fileage_page(void){
817997
int rid;
818998
const char *zName;
819
- char *zBaseTime;
820999
const char *zGlob;
821
- Stmt q;
1000
+ const char *zUuid;
1001
+ const char *zNow; /* Time of checkin */
1002
+ Stmt q1, q2;
8221003
double baseTime;
823
- int lastMid = -1;
8241004
login_check_credentials();
8251005
if( !g.perm.Read ){ login_needed(); return; }
8261006
zName = P("name");
8271007
if( zName==0 ) zName = "tip";
8281008
rid = symbolic_name_to_rid(zName, "ci");
8291009
if( rid==0 ){
8301010
fossil_fatal("not a valid check-in: %s", zName);
8311011
}
832
- style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName);
1012
+ zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1013
+ baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1014
+ zNow = db_text("", "SELECT datetime(mtime,'localtime') FROM event"
1015
+ " WHERE objid=%d", rid);
1016
+ style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T&mtime=1",
1017
+ zName);
8331018
style_header("File Ages");
8341019
zGlob = P("glob");
8351020
compute_fileage(rid,zGlob);
836
- baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
837
- zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc());
838
- @ <h2>File Ages For Check-in
839
- @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
840
- @
841
- @ <p>The times given are relative to
842
- @ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the
843
- @ check-in time for
844
- @ %z(href("%R/info?name=%T",zName))%h(zName)</a></p>
845
- @
846
- @ <table border=0 cellspacing=0 cellpadding=0>
847
- db_prepare(&q,
848
- "SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname"
849
- " FROM fileage"
850
- " ORDER BY mtime DESC, mid, pathname"
851
- );
852
- while( db_step(&q)==SQLITE_ROW ){
853
- double age = baseTime - db_column_double(&q, 0);
854
- int mid = db_column_int(&q, 2);
855
- const char *zFUuid = db_column_text(&q, 1);
856
- char zAge[200];
857
- if( lastMid!=mid ){
858
- @ <tr><td colspan=3><hr></tr>
859
- lastMid = mid;
860
- if( age*86400.0<120 ){
861
- sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0));
862
- }else if( age*1440.0<90 ){
863
- sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0);
864
- }else if( age*24.0<36 ){
865
- sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0);
866
- }else if( age<365.0 ){
867
- sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age);
868
- }else{
869
- sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0);
870
- }
871
- }else{
872
- zAge[0] = 0;
873
- }
874
- @ <tr>
875
- @ <td>%s(zAge)
876
- @ <td width="25">
877
- @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a>
878
- @ </tr>
879
- @
880
- }
881
- @ <tr><td colspan=3><hr></tr>
882
- @ </table>
883
- db_finalize(&q);
1021
+ db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1022
+
1023
+ @ <h2>Files in
1024
+ @ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a>
1025
+ if( zGlob && zGlob[0] ){
1026
+ @ that match "%h(zGlob)" and
1027
+ }
1028
+ @ ordered by check-in time</h2>
1029
+ @
1030
+ @ <p>Times are relative to the checkin time for
1031
+ @ %z(href("%R/ci/%s",zUuid))[%S(zUuid)]</a> which is
1032
+ @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
1033
+ @
1034
+ @ <div class='fileage'><table>
1035
+ @ <tr><th>Time</th><th>Files</th><th>Checkin</th></tr>
1036
+ db_prepare(&q1,
1037
+ "SELECT event.mtime, event.objid, blob.uuid,\n"
1038
+ " coalesce(event.ecomment,event.comment),\n"
1039
+ " coalesce(event.euser,event.user),\n"
1040
+ " coalesce((SELECT value FROM tagxref\n"
1041
+ " WHERE tagtype>0 AND tagid=%d\n"
1042
+ " AND rid=event.objid),'trunk')\n"
1043
+ " FROM event, blob\n"
1044
+ " WHERE event.objid IN (SELECT mid FROM fileage)\n"
1045
+ " AND blob.rid=event.objid\n"
1046
+ " ORDER BY event.mtime DESC;",
1047
+ TAG_BRANCH
1048
+ );
1049
+ db_prepare(&q2,
1050
+ "SELECT blob.uuid, filename.name\n"
1051
+ " FROM fileage, blob, filename\n"
1052
+ " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
1053
+ " AND blob.rid=fileage.fid;"
1054
+ );
1055
+ while( db_step(&q1)==SQLITE_ROW ){
1056
+ double age = baseTime - db_column_double(&q1, 0);
1057
+ int mid = db_column_int(&q1, 1);
1058
+ const char *zUuid = db_column_text(&q1, 2);
1059
+ const char *zComment = db_column_text(&q1, 3);
1060
+ const char *zUser = db_column_text(&q1, 4);
1061
+ const char *zBranch = db_column_text(&q1, 5);
1062
+ char *zAge = human_readable_age(age);
1063
+ @ <tr><td>%s(zAge)</td>
1064
+ @ <td>
1065
+ db_bind_int(&q2, ":mid", mid);
1066
+ while( db_step(&q2)==SQLITE_ROW ){
1067
+ const char *zFUuid = db_column_text(&q2,0);
1068
+ const char *zFile = db_column_text(&q2,1);
1069
+ @ %z(href("%R/artifact/%s",zFUuid))%h(zFile)</a><br>
1070
+ }
1071
+ db_reset(&q2);
1072
+ @ </td>
1073
+ @ <td>
1074
+ @ %z(href("%R/info/%s",zUuid))[%S(zUuid)]</a>
1075
+ @ %W(zComment) (user:
1076
+ @ %z(href("%R/timeline?u=%t&c=%t&nd&n=200",zUser,zUuid))%h(zUser)</a>,
1077
+ @ branch:
1078
+ @ %z(href("%R/timeline?r=%t&c=%t&nd&n=200",zBranch,zUuid))%h(zBranch)</a>)
1079
+ @ </td></tr>
1080
+ @
1081
+ fossil_free(zAge);
1082
+ }
1083
+ @ </table></div>
1084
+ db_finalize(&q1);
1085
+ db_finalize(&q2);
8841086
style_footer();
8851087
}
8861088
--- src/browse.c
+++ src/browse.c
@@ -304,89 +304,206 @@
304
305 /*
306 ** A single line of the file hierarchy
307 */
308 struct FileTreeNode {
309 FileTreeNode *pNext; /* Next line in sequence */
310 FileTreeNode *pPrev; /* Previous line */
311 FileTreeNode *pParent; /* Directory containing this line */
 
 
312 char *zName; /* Name of this entry. The "tail" */
313 char *zFullName; /* Full pathname of this entry */
314 char *zUuid; /* SHA1 hash of this file. May be NULL. */
 
315 unsigned nFullName; /* Length of zFullName */
316 unsigned iLevel; /* Levels of parent directories */
317 u8 isDir; /* True if there are children */
318 u8 isLast; /* True if this is the last child of its parent */
319 };
320
321 /*
322 ** A complete file hierarchy
323 */
324 struct FileTree {
325 FileTreeNode *pFirst; /* First line of the list */
326 FileTreeNode *pLast; /* Last line of the list */
 
327 };
328
329 /*
330 ** Add one or more new FileTreeNodes to the FileTree object so that the
331 ** leaf object zPathname is at the end of the node list
 
 
 
 
 
 
 
 
332 */
333 static void tree_add_node(
334 FileTree *pTree, /* Tree into which nodes are added */
335 const char *zPath, /* The full pathname of file to add */
336 const char *zUuid /* UUID of the file. Might be NULL. */
 
337 ){
338 int i;
339 FileTreeNode *pParent;
340 FileTreeNode *pChild;
341
342 pChild = pTree->pLast;
343 pParent = pChild ? pChild->pParent : 0;
 
 
344 while( pParent!=0 &&
345 ( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0
346 || zPath[pParent->nFullName]!='/' )
347 ){
348 pChild = pParent;
349 pParent = pChild->pParent;
350 }
351 i = pParent ? pParent->nFullName+1 : 0;
352 if( pChild ) pChild->isLast = 0;
353 while( zPath[i] ){
354 FileTreeNode *pNew;
355 int iStart = i;
356 int nByte;
357 while( zPath[i] && zPath[i]!='/' ){ i++; }
358 nByte = sizeof(*pNew) + i + 1;
359 if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1;
360 pNew = fossil_malloc( nByte );
 
361 pNew->zFullName = (char*)&pNew[1];
362 memcpy(pNew->zFullName, zPath, i);
363 pNew->zFullName[i] = 0;
364 pNew->nFullName = i;
365 if( zUuid!=0 && zPath[i]==0 ){
366 pNew->zUuid = pNew->zFullName + i + 1;
367 memcpy(pNew->zUuid, zUuid, UUID_SIZE+1);
368 }else{
369 pNew->zUuid = 0;
370 }
371 pNew->zName = pNew->zFullName + iStart;
372 if( pTree->pLast ){
373 pTree->pLast->pNext = pNew;
374 }else{
375 pTree->pFirst = pNew;
376 }
377 pNew->pPrev = pTree->pLast;
378 pNew->pNext = 0;
379 pNew->pParent = pParent;
380 pTree->pLast = pNew;
381 pNew->iLevel = pParent ? pParent->iLevel+1 : 0;
382 pNew->isDir = zPath[i]=='/';
383 pNew->isLast = 1;
 
 
 
 
 
 
 
 
 
384 while( zPath[i]=='/' ){ i++; }
385 pParent = pNew;
386 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387 }
 
388
389 /*
390 ** WEBPAGE: tree
391 **
392 ** Query parameters:
@@ -394,19 +511,23 @@
394 ** name=PATH Directory to display. Optional
395 ** ci=LABEL Show only files in this check-in. Optional.
396 ** re=REGEXP Show only files matching REGEXP. Optional.
397 ** expand Begin with the tree fully expanded.
398 ** nofiles Show directories (folders) only. Omit files.
 
399 */
400 void page_tree(void){
401 char *zD = fossil_strdup(P("name"));
402 int nD = zD ? strlen(zD)+1 : 0;
403 const char *zCI = P("ci");
404 int rid = 0;
405 char *zUuid = 0;
406 Blob dirname;
407 Manifest *pM = 0;
 
 
 
408 int nFile = 0; /* Number of files (or folders with "nofiles") */
409 int linkTrunk = 1; /* include link to "trunk" */
410 int linkTip = 1; /* include link to "tip" */
411 const char *zRE; /* the value for the re=REGEXP query parameter */
412 const char *zObjType; /* "files" by default or "folders" for "nofiles" */
@@ -464,14 +585,21 @@
464 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
465 linkTrunk = trunkRid && rid != trunkRid;
466 linkTip = rid != symbolic_name_to_rid("tip", "ci");
467 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
468 url_add_parameter(&sURI, "ci", zCI);
 
 
 
469 }else{
470 zCI = 0;
471 }
472 }
 
 
 
 
473
474 /* Compute the title of the page */
475 blob_zero(&dirname);
476 if( zD ){
477 url_add_parameter(&sURI, "name", zD);
@@ -483,10 +611,18 @@
483 }else{
484 if( zRE ){
485 blob_appendf(&dirname, "matching \"%s\"", zRE);
486 }
487 }
 
 
 
 
 
 
 
 
488 if( zCI ){
489 style_submenu_element("All", "All", "%s",
490 url_render(&sURI, "ci", 0, 0, 0));
491 if( nD==0 && !showDirOnly ){
492 style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
@@ -499,87 +635,82 @@
499 }
500 if( linkTip ){
501 style_submenu_element("Tip", "Tip", "%s",
502 url_render(&sURI, "ci", "tip", 0, 0));
503 }
504 if( !showDirOnly ){
505 style_submenu_element("Flat-View", "Flat-View", "%s",
506 url_render(&sURI, "type", "flat", 0, 0));
507 }
508
509 /* Compute the file hierarchy.
510 */
511 if( zCI ){
512 Stmt ins, q;
513 ManifestFile *pFile;
514
515 db_multi_exec(
516 "CREATE TEMP TABLE filelist("
517 " x TEXT PRIMARY KEY COLLATE nocase,"
518 " uuid TEXT"
519 ") WITHOUT ROWID;"
520 );
521 db_prepare(&ins, "INSERT OR IGNORE INTO filelist VALUES(:f,:u)");
522 manifest_file_rewind(pM);
523 while( (pFile = manifest_file_next(pM,0))!=0 ){
524 if( nD>0
525 && (fossil_strncmp(pFile->zName, zD, nD-1)!=0
526 || pFile->zName[nD-1]!='/')
527 ){
528 continue;
529 }
530 if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue;
531 db_bind_text(&ins, ":f", pFile->zName);
532 db_bind_text(&ins, ":u", pFile->zUuid);
533 db_step(&ins);
534 db_reset(&ins);
535 }
536 db_finalize(&ins);
537 db_prepare(&q, "SELECT x, uuid FROM filelist ORDER BY x");
538 while( db_step(&q)==SQLITE_ROW ){
539 tree_add_node(&sTree, db_column_text(&q,0), db_column_text(&q,1));
 
 
 
 
540 nFile++;
541 }
542 db_finalize(&q);
543 }else{
544 Stmt q;
545 db_prepare(&q, "SELECT name FROM filename ORDER BY name COLLATE nocase");
 
 
 
 
 
 
546 while( db_step(&q)==SQLITE_ROW ){
547 const char *z = db_column_text(&q, 0);
548 if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){
 
 
549 continue;
550 }
551 if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue;
552 tree_add_node(&sTree, z, 0);
553 nFile++;
554 }
555 db_finalize(&q);
556 }
557
558 if( showDirOnly ){
559 for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
560 if( p->isDir && p->nFullName>nD ) nFile++;
561 }
562 zObjType = "folders";
563 style_submenu_element("Files","Files","%s",
564 url_render(&sURI,"nofiles",0,0,0));
565 }else{
566 zObjType = "files";
567 style_submenu_element("Folders","Folders","%s",
568 url_render(&sURI,"nofiles","1",0,0));
569 }
570
571 if( zCI ){
572 @ <h2>%d(nFile) %s(zObjType) of check-in
573 if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
574 @ "%h(zCI)"
575 }
576 @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))</h2>
577 }else{
578 int n = db_int(0, "SELECT count(*) FROM plink");
579 @ <h2>%d(nFile) %s(zObjType) from all %d(n) check-ins
580 @ %s(blob_str(&dirname))</h2>
 
 
 
 
581 }
582
583
584 /* Generate tree of lists.
585 **
@@ -596,18 +727,33 @@
596 if( nD ){
597 @ <li class="dir last">
598 }else{
599 @ <li class="dir subdir last">
600 }
 
601 @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a>
 
 
 
 
602 @ <ul>
 
 
 
 
 
603 for(p=sTree.pFirst, nDir=0; p; p=p->pNext){
604 const char *zLastClass = p->isLast ? " last" : "";
605 if( p->isDir ){
606 const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : "";
607 @ <li class="dir%s(zSubdirClass)%s(zLastClass)">
608 @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a>
 
 
 
 
 
609 if( startExpanded || p->nFullName<=nD ){
610 @ <ul id="dir%d(nDir)">
611 }else{
612 @ <ul id="dir%d(nDir)" class="collapsed">
613 }
@@ -614,17 +760,23 @@
614 nDir++;
615 }else if( !showDirOnly ){
616 const char *zFileClass = fileext_class(p->zName);
617 char *zLink;
618 if( zCI ){
619 zLink = href("%R/artifact/%s",p->zUuid);
620 }else{
621 zLink = href("%R/finfo?name=%T",p->zFullName);
622 }
623 @ <li class="%z(zFileClass)%s(zLastClass)">%z(zLink)%h(p->zName)</a>
 
 
 
 
 
 
624 }
625 if( p->isLast ){
626 int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);
627 while( nClose-- > 0 ){
628 @ </ul>
629 }
630 }
@@ -687,16 +839,16 @@
687 @ checkState();
688 @ outer_ul.onclick = function(e){
689 @ e = e || window.event;
690 @ var a = e.target || e.srcElement;
691 @ if( a.nodeName!='A' ) return true;
692 @ if( a.parentNode==subdir ){
693 @ toggleAll(outer_ul);
694 @ return false;
695 @ }
696 @ if( !belowSubdir(a) ) return true;
697 @ var ul = a.nextSibling;
698 @ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling;
699 @ if( !ul ) return true; /* This is a file link, not a directory */
700 @ toggleDir(ul);
701 @ return false;
702 @ }
@@ -724,87 +876,115 @@
724 }else{
725 zClass = mprintf("file");
726 }
727 return zClass;
728 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
729
730 /*
731 ** Look at all file containing in the version "vid". Construct a
732 ** temporary table named "fileage" that contains the file-id for each
733 ** files, the pathname, the check-in where the file was added, and the
734 ** mtime on that checkin. If zGlob and *zGlob then only files matching
735 ** the given glob are computed.
736 */
737 int compute_fileage(int vid, const char* zGlob){
738 Manifest *pManifest;
739 ManifestFile *pFile;
740 int nFile = 0;
741 double vmtime;
742 Stmt ins;
743 Stmt q1, q2, q3;
744 Stmt upd;
745 if(zGlob && !*zGlob) zGlob = NULL;
746 db_multi_exec(
747 /*"DROP TABLE IF EXISTS temp.fileage;"*/
748 "CREATE TEMP TABLE fileage("
749 " fid INTEGER,"
750 " mid INTEGER,"
751 " mtime DATETIME,"
752 " pathname TEXT"
753 ");"
754 "CREATE INDEX fileage_fid ON fileage(fid);"
755 );
756 pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0);
757 if( pManifest==0 ) return 1;
758 manifest_file_rewind(pManifest);
759 db_prepare(&ins,
760 "INSERT INTO temp.fileage(fid, pathname)"
761 " SELECT rid, :path FROM blob WHERE uuid=:uuid"
762 );
763 while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
764 if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue;
765 db_bind_text(&ins, ":uuid", pFile->zUuid);
766 db_bind_text(&ins, ":path", pFile->zName);
767 db_step(&ins);
768 db_reset(&ins);
769 nFile++;
770 }
771 db_finalize(&ins);
772 manifest_destroy(pManifest);
773 db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid");
774 db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime"
775 " WHERE fid=:fid AND mid IS NULL");
776 db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim");
777 db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid");
778 while( nFile>0 && vid>0 ){
779 db_bind_int(&q3, ":vid", vid);
780 if( db_step(&q3)==SQLITE_ROW ){
781 vmtime = db_column_double(&q3, 0);
782 }else{
783 break;
784 }
785 db_reset(&q3);
786 db_bind_int(&q1, ":mid", vid);
787 db_bind_int(&upd, ":mid", vid);
788 db_bind_double(&upd, ":vmtime", vmtime);
789 while( db_step(&q1)==SQLITE_ROW ){
790 db_bind_int(&upd, ":fid", db_column_int(&q1, 0));
791 db_step(&upd);
792 nFile -= db_changes();
793 db_reset(&upd);
794 }
795 db_reset(&q1);
796 db_bind_int(&q2, ":vid", vid);
797 if( db_step(&q2)!=SQLITE_ROW ) break;
798 vid = db_column_int(&q2, 0);
799 db_reset(&q2);
800 }
801 db_finalize(&q1);
802 db_finalize(&upd);
803 db_finalize(&q2);
804 db_finalize(&q3);
805 return 0;
806 }
807
808 /*
809 ** WEBPAGE: fileage
810 **
@@ -814,72 +994,94 @@
814 ** (e.g. *.c or *.txt).
815 */
816 void fileage_page(void){
817 int rid;
818 const char *zName;
819 char *zBaseTime;
820 const char *zGlob;
821 Stmt q;
 
 
822 double baseTime;
823 int lastMid = -1;
824 login_check_credentials();
825 if( !g.perm.Read ){ login_needed(); return; }
826 zName = P("name");
827 if( zName==0 ) zName = "tip";
828 rid = symbolic_name_to_rid(zName, "ci");
829 if( rid==0 ){
830 fossil_fatal("not a valid check-in: %s", zName);
831 }
832 style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName);
 
 
 
 
 
833 style_header("File Ages");
834 zGlob = P("glob");
835 compute_fileage(rid,zGlob);
836 baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
837 zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc());
838 @ <h2>File Ages For Check-in
839 @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
840 @
841 @ <p>The times given are relative to
842 @ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the
843 @ check-in time for
844 @ %z(href("%R/info?name=%T",zName))%h(zName)</a></p>
845 @
846 @ <table border=0 cellspacing=0 cellpadding=0>
847 db_prepare(&q,
848 "SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname"
849 " FROM fileage"
850 " ORDER BY mtime DESC, mid, pathname"
851 );
852 while( db_step(&q)==SQLITE_ROW ){
853 double age = baseTime - db_column_double(&q, 0);
854 int mid = db_column_int(&q, 2);
855 const char *zFUuid = db_column_text(&q, 1);
856 char zAge[200];
857 if( lastMid!=mid ){
858 @ <tr><td colspan=3><hr></tr>
859 lastMid = mid;
860 if( age*86400.0<120 ){
861 sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0));
862 }else if( age*1440.0<90 ){
863 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0);
864 }else if( age*24.0<36 ){
865 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0);
866 }else if( age<365.0 ){
867 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age);
868 }else{
869 sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0);
870 }
871 }else{
872 zAge[0] = 0;
873 }
874 @ <tr>
875 @ <td>%s(zAge)
876 @ <td width="25">
877 @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a>
878 @ </tr>
879 @
880 }
881 @ <tr><td colspan=3><hr></tr>
882 @ </table>
883 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
884 style_footer();
885 }
886
--- src/browse.c
+++ src/browse.c
@@ -304,89 +304,206 @@
304
305 /*
306 ** A single line of the file hierarchy
307 */
308 struct FileTreeNode {
309 FileTreeNode *pNext; /* Next entry in an ordered list of them all */
310 FileTreeNode *pParent; /* Directory containing this entry */
311 FileTreeNode *pSibling; /* Next element in the same subdirectory */
312 FileTreeNode *pChild; /* List of child nodes */
313 FileTreeNode *pLastChild; /* Last child on the pChild list */
314 char *zName; /* Name of this entry. The "tail" */
315 char *zFullName; /* Full pathname of this entry */
316 char *zUuid; /* SHA1 hash of this file. May be NULL. */
317 double mtime; /* Modification time for this entry */
318 unsigned nFullName; /* Length of zFullName */
319 unsigned iLevel; /* Levels of parent directories */
 
 
320 };
321
322 /*
323 ** A complete file hierarchy
324 */
325 struct FileTree {
326 FileTreeNode *pFirst; /* First line of the list */
327 FileTreeNode *pLast; /* Last line of the list */
328 FileTreeNode *pLastTop; /* Last top-level node */
329 };
330
331 /*
332 ** Add one or more new FileTreeNodes to the FileTree object so that the
333 ** leaf object zPathname is at the end of the node list.
334 **
335 ** The caller invokes this routine once for each leaf node (each file
336 ** as opposed to each directory). This routine fills in any missing
337 ** intermediate nodes automatically.
338 **
339 ** When constructing a list of FileTreeNodes, all entries that have
340 ** a common directory prefix must be added consecutively in order for
341 ** the tree to be constructed properly.
342 */
343 static void tree_add_node(
344 FileTree *pTree, /* Tree into which nodes are added */
345 const char *zPath, /* The full pathname of file to add */
346 const char *zUuid, /* UUID of the file. Might be NULL. */
347 double mtime /* Modification time for this entry */
348 ){
349 int i;
350 FileTreeNode *pParent; /* Parent (directory) of the next node to insert */
 
351
352 /* Make pParent point to the most recent ancestor of zPath, or
353 ** NULL if there are no prior entires that are a container for zPath.
354 */
355 pParent = pTree->pLast;
356 while( pParent!=0 &&
357 ( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0
358 || zPath[pParent->nFullName]!='/' )
359 ){
360 pParent = pParent->pParent;
 
361 }
362 i = pParent ? pParent->nFullName+1 : 0;
 
363 while( zPath[i] ){
364 FileTreeNode *pNew;
365 int iStart = i;
366 int nByte;
367 while( zPath[i] && zPath[i]!='/' ){ i++; }
368 nByte = sizeof(*pNew) + i + 1;
369 if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1;
370 pNew = fossil_malloc( nByte );
371 memset(pNew, 0, sizeof(*pNew));
372 pNew->zFullName = (char*)&pNew[1];
373 memcpy(pNew->zFullName, zPath, i);
374 pNew->zFullName[i] = 0;
375 pNew->nFullName = i;
376 if( zUuid!=0 && zPath[i]==0 ){
377 pNew->zUuid = pNew->zFullName + i + 1;
378 memcpy(pNew->zUuid, zUuid, UUID_SIZE+1);
 
 
379 }
380 pNew->zName = pNew->zFullName + iStart;
381 if( pTree->pLast ){
382 pTree->pLast->pNext = pNew;
383 }else{
384 pTree->pFirst = pNew;
385 }
386 pTree->pLast = pNew;
 
387 pNew->pParent = pParent;
388 if( pParent ){
389 if( pParent->pChild ){
390 pParent->pLastChild->pSibling = pNew;
391 }else{
392 pParent->pChild = pNew;
393 }
394 pNew->iLevel = pParent->iLevel + 1;
395 pParent->pLastChild = pNew;
396 }else{
397 if( pTree->pLastTop ) pTree->pLastTop->pSibling = pNew;
398 pTree->pLastTop = pNew;
399 }
400 pNew->mtime = mtime;
401 while( zPath[i]=='/' ){ i++; }
402 pParent = pNew;
403 }
404 while( pParent && pParent->pParent ){
405 if( pParent->pParent->mtime < pParent->mtime ){
406 pParent->pParent->mtime = pParent->mtime;
407 }
408 pParent = pParent->pParent;
409 }
410 }
411
412 /* Comparison function for two FileTreeNode objects. Sort first by
413 ** mtime (larger numbers first) and then by zName (smaller names first).
414 **
415 ** Return negative if pLeft<pRight.
416 ** Return positive if pLeft>pRight.
417 ** Return zero if pLeft==pRight.
418 */
419 static int compareNodes(FileTreeNode *pLeft, FileTreeNode *pRight){
420 if( pLeft->mtime>pRight->mtime ) return -1;
421 if( pLeft->mtime<pRight->mtime ) return +1;
422 return fossil_stricmp(pLeft->zName, pRight->zName);
423 }
424
425 /* Merge together two sorted lists of FileTreeNode objects */
426 static FileTreeNode *mergeNodes(FileTreeNode *pLeft, FileTreeNode *pRight){
427 FileTreeNode *pEnd;
428 FileTreeNode base;
429 pEnd = &base;
430 while( pLeft && pRight ){
431 if( compareNodes(pLeft,pRight)<=0 ){
432 pEnd = pEnd->pSibling = pLeft;
433 pLeft = pLeft->pSibling;
434 }else{
435 pEnd = pEnd->pSibling = pRight;
436 pRight = pRight->pSibling;
437 }
438 }
439 if( pLeft ){
440 pEnd->pSibling = pLeft;
441 }else{
442 pEnd->pSibling = pRight;
443 }
444 return base.pSibling;
445 }
446
447 /* Sort a list of FileTreeNode objects in mtime order. */
448 static FileTreeNode *sortNodesByMtime(FileTreeNode *p){
449 FileTreeNode *a[30];
450 FileTreeNode *pX;
451 int i;
452
453 memset(a, 0, sizeof(a));
454 while( p ){
455 pX = p;
456 p = pX->pSibling;
457 pX->pSibling = 0;
458 for(i=0; i<count(a)-1 && a[i]!=0; i++){
459 pX = mergeNodes(a[i], pX);
460 a[i] = 0;
461 }
462 a[i] = mergeNodes(a[i], pX);
463 }
464 pX = 0;
465 for(i=0; i<count(a); i++){
466 pX = mergeNodes(a[i], pX);
467 }
468 return pX;
469 }
470
471 /* Sort an entire FileTreeNode tree by mtime
472 **
473 ** This routine invalidates the following fields:
474 **
475 ** FileTreeNode.pLastChild
476 ** FileTreeNode.pNext
477 **
478 ** Use relinkTree to reconnect the pNext pointers.
479 */
480 static FileTreeNode *sortTreeByMtime(FileTreeNode *p){
481 FileTreeNode *pX;
482 for(pX=p; pX; pX=pX->pSibling){
483 if( pX->pChild ) pX->pChild = sortTreeByMtime(pX->pChild);
484 }
485 return sortNodesByMtime(p);
486 }
487
488 /* Reconstruct the FileTree by reconnecting the FileTreeNode.pNext
489 ** fields in sequential order.
490 */
491 static void relinkTree(FileTree *pTree, FileTreeNode *pRoot){
492 while( pRoot ){
493 if( pTree->pLast ){
494 pTree->pLast->pNext = pRoot;
495 }else{
496 pTree->pFirst = pRoot;
497 }
498 pTree->pLast = pRoot;
499 if( pRoot->pChild ) relinkTree(pTree, pRoot->pChild);
500 pRoot = pRoot->pSibling;
501 }
502 if( pTree->pLast ) pTree->pLast->pNext = 0;
503 }
504
505
506 /*
507 ** WEBPAGE: tree
508 **
509 ** Query parameters:
@@ -394,19 +511,23 @@
511 ** name=PATH Directory to display. Optional
512 ** ci=LABEL Show only files in this check-in. Optional.
513 ** re=REGEXP Show only files matching REGEXP. Optional.
514 ** expand Begin with the tree fully expanded.
515 ** nofiles Show directories (folders) only. Omit files.
516 ** mtime Order directory elements by decreasing mtime
517 */
518 void page_tree(void){
519 char *zD = fossil_strdup(P("name"));
520 int nD = zD ? strlen(zD)+1 : 0;
521 const char *zCI = P("ci");
522 int rid = 0;
523 char *zUuid = 0;
524 Blob dirname;
525 Manifest *pM = 0;
526 double rNow = 0;
527 char *zNow = 0;
528 int useMtime = atoi(PD("mtime","0"));
529 int nFile = 0; /* Number of files (or folders with "nofiles") */
530 int linkTrunk = 1; /* include link to "trunk" */
531 int linkTip = 1; /* include link to "tip" */
532 const char *zRE; /* the value for the re=REGEXP query parameter */
533 const char *zObjType; /* "files" by default or "folders" for "nofiles" */
@@ -464,14 +585,21 @@
585 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
586 linkTrunk = trunkRid && rid != trunkRid;
587 linkTip = rid != symbolic_name_to_rid("tip", "ci");
588 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
589 url_add_parameter(&sURI, "ci", zCI);
590 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
591 zNow = db_text("", "SELECT datetime(mtime,'localtime')"
592 " FROM event WHERE objid=%d", rid);
593 }else{
594 zCI = 0;
595 }
596 }
597 if( zCI==0 ){
598 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
599 zNow = db_text("", "SELECT datetime(max(mtime),'localtime') FROM event");
600 }
601
602 /* Compute the title of the page */
603 blob_zero(&dirname);
604 if( zD ){
605 url_add_parameter(&sURI, "name", zD);
@@ -483,10 +611,18 @@
611 }else{
612 if( zRE ){
613 blob_appendf(&dirname, "matching \"%s\"", zRE);
614 }
615 }
616 if( useMtime ){
617 style_submenu_element("Sort By Filename","Sort By Filename", "%s",
618 url_render(&sURI, 0, 0, 0, 0));
619 url_add_parameter(&sURI, "mtime", "1");
620 }else{
621 style_submenu_element("Sort By Time","Sort By Time", "%s",
622 url_render(&sURI, "mtime", "1", 0, 0));
623 }
624 if( zCI ){
625 style_submenu_element("All", "All", "%s",
626 url_render(&sURI, "ci", 0, 0, 0));
627 if( nD==0 && !showDirOnly ){
628 style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
@@ -499,87 +635,82 @@
635 }
636 if( linkTip ){
637 style_submenu_element("Tip", "Tip", "%s",
638 url_render(&sURI, "ci", "tip", 0, 0));
639 }
 
 
 
 
640
641 /* Compute the file hierarchy.
642 */
643 if( zCI ){
644 Stmt q;
645 compute_fileage(rid, 0);
646 db_prepare(&q,
647 "SELECT filename.name, blob.uuid, fileage.mtime\n"
648 " FROM fileage, filename, blob\n"
649 " WHERE filename.fnid=fileage.fnid\n"
650 " AND blob.rid=fileage.fid\n"
651 " ORDER BY filename.name COLLATE nocase;"
652 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
653 while( db_step(&q)==SQLITE_ROW ){
654 const char *zFile = db_column_text(&q,0);
655 const char *zUuid = db_column_text(&q,1);
656 double mtime = db_column_double(&q,2);
657 if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue;
658 tree_add_node(&sTree, zFile, zUuid, mtime);
659 nFile++;
660 }
661 db_finalize(&q);
662 }else{
663 Stmt q;
664 db_prepare(&q,
665 "SELECT filename.name, blob.uuid, max(event.mtime)\n"
666 " FROM filename, mlink, blob, event\n"
667 " WHERE mlink.fnid=filename.fnid\n"
668 " AND event.objid=mlink.mid\n"
669 " AND blob.rid=mlink.fid\n"
670 " GROUP BY 1 ORDER BY 1 COLLATE nocase");
671 while( db_step(&q)==SQLITE_ROW ){
672 const char *zName = db_column_text(&q, 0);
673 const char *zUuid = db_column_text(&q,1);
674 double mtime = db_column_double(&q,2);
675 if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){
676 continue;
677 }
678 if( pRE && re_match(pRE, (const u8*)zName, -1)==0 ) continue;
679 tree_add_node(&sTree, zName, zUuid, mtime);
680 nFile++;
681 }
682 db_finalize(&q);
683 }
684
685 if( showDirOnly ){
686 for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
687 if( p->pChild!=0 && p->nFullName>nD ) nFile++;
688 }
689 zObjType = "Folders";
690 style_submenu_element("Files","Files","%s",
691 url_render(&sURI,"nofiles",0,0,0));
692 }else{
693 zObjType = "Files";
694 style_submenu_element("Folders","Folders","%s",
695 url_render(&sURI,"nofiles","1",0,0));
696 }
697
698 if( zCI ){
699 @ <h2>%s(zObjType) from
700 if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
701 @ "%h(zCI)"
702 }
703 @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))
704 }else{
705 int n = db_int(0, "SELECT count(*) FROM plink");
706 @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
707 }
708 if( useMtime ){
709 @ sorted by modification time</h2>
710 }else{
711 @ sorted by filename</h2>
712 }
713
714
715 /* Generate tree of lists.
716 **
@@ -596,18 +727,33 @@
727 if( nD ){
728 @ <li class="dir last">
729 }else{
730 @ <li class="dir subdir last">
731 }
732 @ <div class="filetreeline">
733 @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a>
734 if( zNow ){
735 @ <div class="filetreeage">%s(zNow)</div>
736 }
737 @ </div>
738 @ <ul>
739 if( useMtime ){
740 p = sortTreeByMtime(sTree.pFirst);
741 memset(&sTree, 0, sizeof(sTree));
742 relinkTree(&sTree, p);
743 }
744 for(p=sTree.pFirst, nDir=0; p; p=p->pNext){
745 const char *zLastClass = p->pSibling==0 ? " last" : "";
746 if( p->pChild ){
747 const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : "";
748 @ <li class="dir%s(zSubdirClass)%s(zLastClass)"><div class="filetreeline">
749 @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a>
750 if( p->mtime>0.0 ){
751 char *zAge = human_readable_age(rNow - p->mtime);
752 @ <div class="filetreeage">%s(zAge)</div>
753 }
754 @ </div>
755 if( startExpanded || p->nFullName<=nD ){
756 @ <ul id="dir%d(nDir)">
757 }else{
758 @ <ul id="dir%d(nDir)" class="collapsed">
759 }
@@ -614,17 +760,23 @@
760 nDir++;
761 }else if( !showDirOnly ){
762 const char *zFileClass = fileext_class(p->zName);
763 char *zLink;
764 if( zCI ){
765 zLink = href("%R/artifact/%.16s",p->zUuid);
766 }else{
767 zLink = href("%R/finfo?name=%T",p->zFullName);
768 }
769 @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
770 @ %z(zLink)%h(p->zName)</a>
771 if( p->mtime>0 ){
772 char *zAge = human_readable_age(rNow - p->mtime);
773 @ <div class="filetreeage">%s(zAge)</div>
774 }
775 @ </div>
776 }
777 if( p->pSibling==0 ){
778 int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);
779 while( nClose-- > 0 ){
780 @ </ul>
781 }
782 }
@@ -687,16 +839,16 @@
839 @ checkState();
840 @ outer_ul.onclick = function(e){
841 @ e = e || window.event;
842 @ var a = e.target || e.srcElement;
843 @ if( a.nodeName!='A' ) return true;
844 @ if( a.parentNode.parentNode==subdir ){
845 @ toggleAll(outer_ul);
846 @ return false;
847 @ }
848 @ if( !belowSubdir(a) ) return true;
849 @ var ul = a.parentNode.nextSibling;
850 @ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling;
851 @ if( !ul ) return true; /* This is a file link, not a directory */
852 @ toggleDir(ul);
853 @ return false;
854 @ }
@@ -724,87 +876,115 @@
876 }else{
877 zClass = mprintf("file");
878 }
879 return zClass;
880 }
881
882 /*
883 ** SQL used to compute the age of all files in checkin :ckin whose
884 ** names match :glob
885 */
886 static const char zComputeFileAgeSetup[] =
887 @ CREATE TABLE IF NOT EXISTS temp.fileage(
888 @ fnid INTEGER PRIMARY KEY,
889 @ fid INTEGER,
890 @ mid INTEGER,
891 @ mtime DATETIME,
892 @ pathname TEXT
893 @ );
894 @ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin;
895 ;
896
897 static const char zComputeFileAgeRun[] =
898 @ WITH RECURSIVE
899 @ ckin(x) AS (VALUES(:ckin) UNION ALL
900 @ SELECT pid FROM ckin, plink WHERE cid=x AND isprim)
901 @ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname)
902 @ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name
903 @ FROM ckin, mlink, event, filename
904 @ WHERE mlink.mid=ckin.x
905 @ AND mlink.fnid IN (SELECT fnid FROM foci, filename
906 @ WHERE foci.checkinID=:ckin
907 @ AND filename.name=foci.filename
908 @ AND filename.name GLOB :glob)
909 @ AND filename.fnid=mlink.fnid
910 @ AND event.objid=mlink.mid;
911 ;
912
913
914 /*
915 ** Look at all file containing in the version "vid". Construct a
916 ** temporary table named "fileage" that contains the file-id for each
917 ** files, the pathname, the check-in where the file was added, and the
918 ** mtime on that checkin. If zGlob and *zGlob then only files matching
919 ** the given glob are computed.
920 */
921 int compute_fileage(int vid, const char* zGlob){
922 Stmt q;
923 db_multi_exec(zComputeFileAgeSetup /*works-like:"constant"*/);
924 db_prepare(&q, zComputeFileAgeRun /*works-like:"constant"*/);
925 db_bind_int(&q, ":ckin", vid);
926 db_bind_text(&q, ":glob", zGlob && zGlob[0] ? zGlob : "*");
927 db_exec(&q);
928 db_finalize(&q);
929 return 0;
930 }
931
932 /*
933 ** Render the number of days in rAge as a more human-readable time span.
934 ** Different units (seconds, minutes, hours, days, months, years) are
935 ** selected depending on the magnitude of rAge.
936 **
937 ** The string returned is obtained from fossil_malloc() and should be
938 ** freed by the caller.
939 */
940 char *human_readable_age(double rAge){
941 if( rAge*86400.0<120 ){
942 if( rAge*86400.0<1.0 ){
943 return mprintf("current");
944 }else{
945 return mprintf("%d seconds", (int)(rAge*86400.0));
946 }
947 }else if( rAge*1440.0<90 ){
948 return mprintf("%.1f minutes", rAge*1440.0);
949 }else if( rAge*24.0<36 ){
950 return mprintf("%.1f hours", rAge*24.0);
951 }else if( rAge<365.0 ){
952 return mprintf("%.1f days", rAge);
953 }else{
954 return mprintf("%.2f years", rAge/365.0);
955 }
956 }
957
958 /*
959 ** COMMAND: test-fileage
960 **
961 ** Usage: %fossil test-fileage CHECKIN
962 */
963 void test_fileage_cmd(void){
964 int mid;
965 Stmt q;
966 const char *zGlob = find_option("glob",0,1);
967 db_find_and_open_repository(0,0);
968 verify_all_options();
969 if( g.argc!=3 ) usage("test-fileage CHECKIN");
970 mid = name_to_typed_rid(g.argv[2],"ci");
971 compute_fileage(mid, zGlob);
972 db_prepare(&q,
973 "SELECT fid, mid, julianday('now') - mtime, pathname"
974 " FROM fileage"
975 );
976 while( db_step(&q)==SQLITE_ROW ){
977 char *zAge = human_readable_age(db_column_double(&q,2));
978 fossil_print("%8d %8d %16s %s\n",
979 db_column_int(&q,0),
980 db_column_int(&q,1),
981 zAge,
982 db_column_text(&q,3));
983 fossil_free(zAge);
984 }
985 db_finalize(&q);
 
 
 
 
986 }
987
988 /*
989 ** WEBPAGE: fileage
990 **
@@ -814,72 +994,94 @@
994 ** (e.g. *.c or *.txt).
995 */
996 void fileage_page(void){
997 int rid;
998 const char *zName;
 
999 const char *zGlob;
1000 const char *zUuid;
1001 const char *zNow; /* Time of checkin */
1002 Stmt q1, q2;
1003 double baseTime;
 
1004 login_check_credentials();
1005 if( !g.perm.Read ){ login_needed(); return; }
1006 zName = P("name");
1007 if( zName==0 ) zName = "tip";
1008 rid = symbolic_name_to_rid(zName, "ci");
1009 if( rid==0 ){
1010 fossil_fatal("not a valid check-in: %s", zName);
1011 }
1012 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1013 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1014 zNow = db_text("", "SELECT datetime(mtime,'localtime') FROM event"
1015 " WHERE objid=%d", rid);
1016 style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T&mtime=1",
1017 zName);
1018 style_header("File Ages");
1019 zGlob = P("glob");
1020 compute_fileage(rid,zGlob);
1021 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1022
1023 @ <h2>Files in
1024 @ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a>
1025 if( zGlob && zGlob[0] ){
1026 @ that match "%h(zGlob)" and
1027 }
1028 @ ordered by check-in time</h2>
1029 @
1030 @ <p>Times are relative to the checkin time for
1031 @ %z(href("%R/ci/%s",zUuid))[%S(zUuid)]</a> which is
1032 @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
1033 @
1034 @ <div class='fileage'><table>
1035 @ <tr><th>Time</th><th>Files</th><th>Checkin</th></tr>
1036 db_prepare(&q1,
1037 "SELECT event.mtime, event.objid, blob.uuid,\n"
1038 " coalesce(event.ecomment,event.comment),\n"
1039 " coalesce(event.euser,event.user),\n"
1040 " coalesce((SELECT value FROM tagxref\n"
1041 " WHERE tagtype>0 AND tagid=%d\n"
1042 " AND rid=event.objid),'trunk')\n"
1043 " FROM event, blob\n"
1044 " WHERE event.objid IN (SELECT mid FROM fileage)\n"
1045 " AND blob.rid=event.objid\n"
1046 " ORDER BY event.mtime DESC;",
1047 TAG_BRANCH
1048 );
1049 db_prepare(&q2,
1050 "SELECT blob.uuid, filename.name\n"
1051 " FROM fileage, blob, filename\n"
1052 " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
1053 " AND blob.rid=fileage.fid;"
1054 );
1055 while( db_step(&q1)==SQLITE_ROW ){
1056 double age = baseTime - db_column_double(&q1, 0);
1057 int mid = db_column_int(&q1, 1);
1058 const char *zUuid = db_column_text(&q1, 2);
1059 const char *zComment = db_column_text(&q1, 3);
1060 const char *zUser = db_column_text(&q1, 4);
1061 const char *zBranch = db_column_text(&q1, 5);
1062 char *zAge = human_readable_age(age);
1063 @ <tr><td>%s(zAge)</td>
1064 @ <td>
1065 db_bind_int(&q2, ":mid", mid);
1066 while( db_step(&q2)==SQLITE_ROW ){
1067 const char *zFUuid = db_column_text(&q2,0);
1068 const char *zFile = db_column_text(&q2,1);
1069 @ %z(href("%R/artifact/%s",zFUuid))%h(zFile)</a><br>
1070 }
1071 db_reset(&q2);
1072 @ </td>
1073 @ <td>
1074 @ %z(href("%R/info/%s",zUuid))[%S(zUuid)]</a>
1075 @ %W(zComment) (user:
1076 @ %z(href("%R/timeline?u=%t&c=%t&nd&n=200",zUser,zUuid))%h(zUser)</a>,
1077 @ branch:
1078 @ %z(href("%R/timeline?r=%t&c=%t&nd&n=200",zBranch,zUuid))%h(zBranch)</a>)
1079 @ </td></tr>
1080 @
1081 fossil_free(zAge);
1082 }
1083 @ </table></div>
1084 db_finalize(&q1);
1085 db_finalize(&q2);
1086 style_footer();
1087 }
1088
+1 -3
--- src/cgi.c
+++ src/cgi.c
@@ -342,13 +342,11 @@
342342
** case of most /getfile calls for specific versions, the only way the
343343
** content changes is if someone breaks the SCM. And if that happens, a
344344
** stale cache is the least of the problem. So we provide an Expires
345345
** header set to a reasonable period (default: one week).
346346
*/
347
- /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/
348
- time_t expires = time(0) + 604800;
349
- fprintf(g.httpOut, "Expires: %s\r\n", cgi_rfc822_datestamp(expires));
347
+ fprintf(g.httpOut, "Cache-control: max-age=28800\r\n");
350348
}else{
351349
fprintf(g.httpOut, "Cache-control: no-cache\r\n");
352350
}
353351
354352
/* Content intended for logged in users should only be cached in
355353
--- src/cgi.c
+++ src/cgi.c
@@ -342,13 +342,11 @@
342 ** case of most /getfile calls for specific versions, the only way the
343 ** content changes is if someone breaks the SCM. And if that happens, a
344 ** stale cache is the least of the problem. So we provide an Expires
345 ** header set to a reasonable period (default: one week).
346 */
347 /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/
348 time_t expires = time(0) + 604800;
349 fprintf(g.httpOut, "Expires: %s\r\n", cgi_rfc822_datestamp(expires));
350 }else{
351 fprintf(g.httpOut, "Cache-control: no-cache\r\n");
352 }
353
354 /* Content intended for logged in users should only be cached in
355
--- src/cgi.c
+++ src/cgi.c
@@ -342,13 +342,11 @@
342 ** case of most /getfile calls for specific versions, the only way the
343 ** content changes is if someone breaks the SCM. And if that happens, a
344 ** stale cache is the least of the problem. So we provide an Expires
345 ** header set to a reasonable period (default: one week).
346 */
347 fprintf(g.httpOut, "Cache-control: max-age=28800\r\n");
 
 
348 }else{
349 fprintf(g.httpOut, "Cache-control: no-cache\r\n");
350 }
351
352 /* Content intended for logged in users should only be cached in
353
+9 -1
--- src/checkin.c
+++ src/checkin.c
@@ -65,11 +65,11 @@
6565
6666
db_prepare(&q,
6767
"SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
6868
" FROM vfile "
6969
" WHERE is_selected(id) %s"
70
- " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1",
70
+ " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/",
7171
blob_sql_text(&where)
7272
);
7373
blob_zero(&rewrittenPathname);
7474
while( db_step(&q)==SQLITE_ROW ){
7575
const char *zPathname = db_column_text(&q,0);
@@ -498,10 +498,11 @@
498498
" ORDER BY 1",
499499
fossil_all_reserved_names(0)
500500
);
501501
db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
502502
blob_zero(&rewrittenPathname);
503
+ g.allowSymlinks = 1; /* Report on symbolic links */
503504
while( db_step(&q)==SQLITE_ROW ){
504505
zDisplayName = zPathname = db_column_text(&q, 0);
505506
if( cwdRelative ) {
506507
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
507508
file_relative_name(zFullName, &rewrittenPathname, 0);
@@ -569,10 +570,11 @@
569570
** argument. Matching files, if any, are removed
570571
** prior to checking for any empty directories;
571572
** therefore, directories that contain only files
572573
** that were removed will be removed as well.
573574
** -f|--force Remove files without prompting.
575
+** --verily Shorthand for: -f --emptydirs --dotfiles
574576
** --clean <CSG> Never prompt for files matching this
575577
** comma separated list of glob patterns.
576578
** --ignore <CSG> Ignore files matching patterns from the
577579
** comma separated list of glob patterns.
578580
** --keep <CSG> Keep files matching this comma separated
@@ -613,10 +615,15 @@
613615
zIgnoreFlag = find_option("ignore",0,1);
614616
verboseFlag = find_option("verbose","v",0)!=0;
615617
zKeepFlag = find_option("keep",0,1);
616618
zCleanFlag = find_option("clean",0,1);
617619
db_must_be_within_tree();
620
+ if( find_option("verily",0,0)!=0 ){
621
+ allFileFlag = allDirFlag = 1;
622
+ emptyDirsFlag = 1;
623
+ scanFlags |= SCAN_ALL;
624
+ }
618625
if( zIgnoreFlag==0 ){
619626
zIgnoreFlag = db_get("ignore-glob", 0);
620627
}
621628
if( zKeepFlag==0 ){
622629
zKeepFlag = db_get("keep-glob", 0);
@@ -646,10 +653,11 @@
646653
}
647654
pIgnore = glob_create(zIgnoreFlag);
648655
pKeep = glob_create(zKeepFlag);
649656
pClean = glob_create(zCleanFlag);
650657
nRoot = (int)strlen(g.zLocalRoot);
658
+ g.allowSymlinks = 1; /* Find symlinks too */
651659
if( !dirsOnlyFlag ){
652660
Stmt q;
653661
Blob repo;
654662
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags,
655663
extremeFlag ? 0 : pIgnore, 0);
656664
--- src/checkin.c
+++ src/checkin.c
@@ -65,11 +65,11 @@
65
66 db_prepare(&q,
67 "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
68 " FROM vfile "
69 " WHERE is_selected(id) %s"
70 " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1",
71 blob_sql_text(&where)
72 );
73 blob_zero(&rewrittenPathname);
74 while( db_step(&q)==SQLITE_ROW ){
75 const char *zPathname = db_column_text(&q,0);
@@ -498,10 +498,11 @@
498 " ORDER BY 1",
499 fossil_all_reserved_names(0)
500 );
501 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
502 blob_zero(&rewrittenPathname);
 
503 while( db_step(&q)==SQLITE_ROW ){
504 zDisplayName = zPathname = db_column_text(&q, 0);
505 if( cwdRelative ) {
506 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
507 file_relative_name(zFullName, &rewrittenPathname, 0);
@@ -569,10 +570,11 @@
569 ** argument. Matching files, if any, are removed
570 ** prior to checking for any empty directories;
571 ** therefore, directories that contain only files
572 ** that were removed will be removed as well.
573 ** -f|--force Remove files without prompting.
 
574 ** --clean <CSG> Never prompt for files matching this
575 ** comma separated list of glob patterns.
576 ** --ignore <CSG> Ignore files matching patterns from the
577 ** comma separated list of glob patterns.
578 ** --keep <CSG> Keep files matching this comma separated
@@ -613,10 +615,15 @@
613 zIgnoreFlag = find_option("ignore",0,1);
614 verboseFlag = find_option("verbose","v",0)!=0;
615 zKeepFlag = find_option("keep",0,1);
616 zCleanFlag = find_option("clean",0,1);
617 db_must_be_within_tree();
 
 
 
 
 
618 if( zIgnoreFlag==0 ){
619 zIgnoreFlag = db_get("ignore-glob", 0);
620 }
621 if( zKeepFlag==0 ){
622 zKeepFlag = db_get("keep-glob", 0);
@@ -646,10 +653,11 @@
646 }
647 pIgnore = glob_create(zIgnoreFlag);
648 pKeep = glob_create(zKeepFlag);
649 pClean = glob_create(zCleanFlag);
650 nRoot = (int)strlen(g.zLocalRoot);
 
651 if( !dirsOnlyFlag ){
652 Stmt q;
653 Blob repo;
654 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags,
655 extremeFlag ? 0 : pIgnore, 0);
656
--- src/checkin.c
+++ src/checkin.c
@@ -65,11 +65,11 @@
65
66 db_prepare(&q,
67 "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
68 " FROM vfile "
69 " WHERE is_selected(id) %s"
70 " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/",
71 blob_sql_text(&where)
72 );
73 blob_zero(&rewrittenPathname);
74 while( db_step(&q)==SQLITE_ROW ){
75 const char *zPathname = db_column_text(&q,0);
@@ -498,10 +498,11 @@
498 " ORDER BY 1",
499 fossil_all_reserved_names(0)
500 );
501 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
502 blob_zero(&rewrittenPathname);
503 g.allowSymlinks = 1; /* Report on symbolic links */
504 while( db_step(&q)==SQLITE_ROW ){
505 zDisplayName = zPathname = db_column_text(&q, 0);
506 if( cwdRelative ) {
507 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
508 file_relative_name(zFullName, &rewrittenPathname, 0);
@@ -569,10 +570,11 @@
570 ** argument. Matching files, if any, are removed
571 ** prior to checking for any empty directories;
572 ** therefore, directories that contain only files
573 ** that were removed will be removed as well.
574 ** -f|--force Remove files without prompting.
575 ** --verily Shorthand for: -f --emptydirs --dotfiles
576 ** --clean <CSG> Never prompt for files matching this
577 ** comma separated list of glob patterns.
578 ** --ignore <CSG> Ignore files matching patterns from the
579 ** comma separated list of glob patterns.
580 ** --keep <CSG> Keep files matching this comma separated
@@ -613,10 +615,15 @@
615 zIgnoreFlag = find_option("ignore",0,1);
616 verboseFlag = find_option("verbose","v",0)!=0;
617 zKeepFlag = find_option("keep",0,1);
618 zCleanFlag = find_option("clean",0,1);
619 db_must_be_within_tree();
620 if( find_option("verily",0,0)!=0 ){
621 allFileFlag = allDirFlag = 1;
622 emptyDirsFlag = 1;
623 scanFlags |= SCAN_ALL;
624 }
625 if( zIgnoreFlag==0 ){
626 zIgnoreFlag = db_get("ignore-glob", 0);
627 }
628 if( zKeepFlag==0 ){
629 zKeepFlag = db_get("keep-glob", 0);
@@ -646,10 +653,11 @@
653 }
654 pIgnore = glob_create(zIgnoreFlag);
655 pKeep = glob_create(zKeepFlag);
656 pClean = glob_create(zCleanFlag);
657 nRoot = (int)strlen(g.zLocalRoot);
658 g.allowSymlinks = 1; /* Find symlinks too */
659 if( !dirsOnlyFlag ){
660 Stmt q;
661 Blob repo;
662 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags,
663 extremeFlag ? 0 : pIgnore, 0);
664
+9 -1
--- src/checkin.c
+++ src/checkin.c
@@ -65,11 +65,11 @@
6565
6666
db_prepare(&q,
6767
"SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
6868
" FROM vfile "
6969
" WHERE is_selected(id) %s"
70
- " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1",
70
+ " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/",
7171
blob_sql_text(&where)
7272
);
7373
blob_zero(&rewrittenPathname);
7474
while( db_step(&q)==SQLITE_ROW ){
7575
const char *zPathname = db_column_text(&q,0);
@@ -498,10 +498,11 @@
498498
" ORDER BY 1",
499499
fossil_all_reserved_names(0)
500500
);
501501
db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
502502
blob_zero(&rewrittenPathname);
503
+ g.allowSymlinks = 1; /* Report on symbolic links */
503504
while( db_step(&q)==SQLITE_ROW ){
504505
zDisplayName = zPathname = db_column_text(&q, 0);
505506
if( cwdRelative ) {
506507
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
507508
file_relative_name(zFullName, &rewrittenPathname, 0);
@@ -569,10 +570,11 @@
569570
** argument. Matching files, if any, are removed
570571
** prior to checking for any empty directories;
571572
** therefore, directories that contain only files
572573
** that were removed will be removed as well.
573574
** -f|--force Remove files without prompting.
575
+** --verily Shorthand for: -f --emptydirs --dotfiles
574576
** --clean <CSG> Never prompt for files matching this
575577
** comma separated list of glob patterns.
576578
** --ignore <CSG> Ignore files matching patterns from the
577579
** comma separated list of glob patterns.
578580
** --keep <CSG> Keep files matching this comma separated
@@ -613,10 +615,15 @@
613615
zIgnoreFlag = find_option("ignore",0,1);
614616
verboseFlag = find_option("verbose","v",0)!=0;
615617
zKeepFlag = find_option("keep",0,1);
616618
zCleanFlag = find_option("clean",0,1);
617619
db_must_be_within_tree();
620
+ if( find_option("verily",0,0)!=0 ){
621
+ allFileFlag = allDirFlag = 1;
622
+ emptyDirsFlag = 1;
623
+ scanFlags |= SCAN_ALL;
624
+ }
618625
if( zIgnoreFlag==0 ){
619626
zIgnoreFlag = db_get("ignore-glob", 0);
620627
}
621628
if( zKeepFlag==0 ){
622629
zKeepFlag = db_get("keep-glob", 0);
@@ -646,10 +653,11 @@
646653
}
647654
pIgnore = glob_create(zIgnoreFlag);
648655
pKeep = glob_create(zKeepFlag);
649656
pClean = glob_create(zCleanFlag);
650657
nRoot = (int)strlen(g.zLocalRoot);
658
+ g.allowSymlinks = 1; /* Find symlinks too */
651659
if( !dirsOnlyFlag ){
652660
Stmt q;
653661
Blob repo;
654662
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags,
655663
extremeFlag ? 0 : pIgnore, 0);
656664
--- src/checkin.c
+++ src/checkin.c
@@ -65,11 +65,11 @@
65
66 db_prepare(&q,
67 "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
68 " FROM vfile "
69 " WHERE is_selected(id) %s"
70 " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1",
71 blob_sql_text(&where)
72 );
73 blob_zero(&rewrittenPathname);
74 while( db_step(&q)==SQLITE_ROW ){
75 const char *zPathname = db_column_text(&q,0);
@@ -498,10 +498,11 @@
498 " ORDER BY 1",
499 fossil_all_reserved_names(0)
500 );
501 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
502 blob_zero(&rewrittenPathname);
 
503 while( db_step(&q)==SQLITE_ROW ){
504 zDisplayName = zPathname = db_column_text(&q, 0);
505 if( cwdRelative ) {
506 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
507 file_relative_name(zFullName, &rewrittenPathname, 0);
@@ -569,10 +570,11 @@
569 ** argument. Matching files, if any, are removed
570 ** prior to checking for any empty directories;
571 ** therefore, directories that contain only files
572 ** that were removed will be removed as well.
573 ** -f|--force Remove files without prompting.
 
574 ** --clean <CSG> Never prompt for files matching this
575 ** comma separated list of glob patterns.
576 ** --ignore <CSG> Ignore files matching patterns from the
577 ** comma separated list of glob patterns.
578 ** --keep <CSG> Keep files matching this comma separated
@@ -613,10 +615,15 @@
613 zIgnoreFlag = find_option("ignore",0,1);
614 verboseFlag = find_option("verbose","v",0)!=0;
615 zKeepFlag = find_option("keep",0,1);
616 zCleanFlag = find_option("clean",0,1);
617 db_must_be_within_tree();
 
 
 
 
 
618 if( zIgnoreFlag==0 ){
619 zIgnoreFlag = db_get("ignore-glob", 0);
620 }
621 if( zKeepFlag==0 ){
622 zKeepFlag = db_get("keep-glob", 0);
@@ -646,10 +653,11 @@
646 }
647 pIgnore = glob_create(zIgnoreFlag);
648 pKeep = glob_create(zKeepFlag);
649 pClean = glob_create(zCleanFlag);
650 nRoot = (int)strlen(g.zLocalRoot);
 
651 if( !dirsOnlyFlag ){
652 Stmt q;
653 Blob repo;
654 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags,
655 extremeFlag ? 0 : pIgnore, 0);
656
--- src/checkin.c
+++ src/checkin.c
@@ -65,11 +65,11 @@
65
66 db_prepare(&q,
67 "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
68 " FROM vfile "
69 " WHERE is_selected(id) %s"
70 " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/",
71 blob_sql_text(&where)
72 );
73 blob_zero(&rewrittenPathname);
74 while( db_step(&q)==SQLITE_ROW ){
75 const char *zPathname = db_column_text(&q,0);
@@ -498,10 +498,11 @@
498 " ORDER BY 1",
499 fossil_all_reserved_names(0)
500 );
501 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
502 blob_zero(&rewrittenPathname);
503 g.allowSymlinks = 1; /* Report on symbolic links */
504 while( db_step(&q)==SQLITE_ROW ){
505 zDisplayName = zPathname = db_column_text(&q, 0);
506 if( cwdRelative ) {
507 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
508 file_relative_name(zFullName, &rewrittenPathname, 0);
@@ -569,10 +570,11 @@
570 ** argument. Matching files, if any, are removed
571 ** prior to checking for any empty directories;
572 ** therefore, directories that contain only files
573 ** that were removed will be removed as well.
574 ** -f|--force Remove files without prompting.
575 ** --verily Shorthand for: -f --emptydirs --dotfiles
576 ** --clean <CSG> Never prompt for files matching this
577 ** comma separated list of glob patterns.
578 ** --ignore <CSG> Ignore files matching patterns from the
579 ** comma separated list of glob patterns.
580 ** --keep <CSG> Keep files matching this comma separated
@@ -613,10 +615,15 @@
615 zIgnoreFlag = find_option("ignore",0,1);
616 verboseFlag = find_option("verbose","v",0)!=0;
617 zKeepFlag = find_option("keep",0,1);
618 zCleanFlag = find_option("clean",0,1);
619 db_must_be_within_tree();
620 if( find_option("verily",0,0)!=0 ){
621 allFileFlag = allDirFlag = 1;
622 emptyDirsFlag = 1;
623 scanFlags |= SCAN_ALL;
624 }
625 if( zIgnoreFlag==0 ){
626 zIgnoreFlag = db_get("ignore-glob", 0);
627 }
628 if( zKeepFlag==0 ){
629 zKeepFlag = db_get("keep-glob", 0);
@@ -646,10 +653,11 @@
653 }
654 pIgnore = glob_create(zIgnoreFlag);
655 pKeep = glob_create(zKeepFlag);
656 pClean = glob_create(zCleanFlag);
657 nRoot = (int)strlen(g.zLocalRoot);
658 g.allowSymlinks = 1; /* Find symlinks too */
659 if( !dirsOnlyFlag ){
660 Stmt q;
661 Blob repo;
662 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags,
663 extremeFlag ? 0 : pIgnore, 0);
664
+1 -2
--- src/checkout.c
+++ src/checkout.c
@@ -305,12 +305,11 @@
305305
306306
if( !forceFlag && unsaved_changes(0) ){
307307
fossil_fatal("there are unsaved changes in the current checkout");
308308
}
309309
if( !forceFlag
310
- && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'",
311
- db_name("localdb"))
310
+ && db_table_exists("localdb","stash")
312311
&& db_exists("SELECT 1 FROM %s.stash", db_name("localdb"))
313312
){
314313
fossil_fatal("closing the checkout will delete your stash");
315314
}
316315
if( db_is_writeable("repository") ){
317316
--- src/checkout.c
+++ src/checkout.c
@@ -305,12 +305,11 @@
305
306 if( !forceFlag && unsaved_changes(0) ){
307 fossil_fatal("there are unsaved changes in the current checkout");
308 }
309 if( !forceFlag
310 && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'",
311 db_name("localdb"))
312 && db_exists("SELECT 1 FROM %s.stash", db_name("localdb"))
313 ){
314 fossil_fatal("closing the checkout will delete your stash");
315 }
316 if( db_is_writeable("repository") ){
317
--- src/checkout.c
+++ src/checkout.c
@@ -305,12 +305,11 @@
305
306 if( !forceFlag && unsaved_changes(0) ){
307 fossil_fatal("there are unsaved changes in the current checkout");
308 }
309 if( !forceFlag
310 && db_table_exists("localdb","stash")
 
311 && db_exists("SELECT 1 FROM %s.stash", db_name("localdb"))
312 ){
313 fossil_fatal("closing the checkout will delete your stash");
314 }
315 if( db_is_writeable("repository") ){
316
+7 -4
--- src/clone.c
+++ src/clone.c
@@ -110,23 +110,26 @@
110110
** --once Don't save url.
111111
** --private Also clone private branches
112112
** --ssl-identity=filename Use the SSL identity if requested by the server
113113
** --ssh-command|-c 'command' Use this SSH command
114114
** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests
115
+** --verbose Show more statistics in output
115116
**
116117
** See also: init
117118
*/
118119
void clone_cmd(void){
119120
char *zPassword;
120121
const char *zDefaultUser; /* Optional name of the default user */
121122
const char *zHttpAuth; /* HTTP Authorization user:pass information */
122123
int nErr = 0;
123
- int bPrivate = 0; /* Also clone private branches */
124124
int urlFlags = URL_PROMPT_PW | URL_REMEMBER;
125
+ int syncFlags = SYNC_CLONE;
125126
126
- if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
127
+ /* Also clone private branches */
128
+ if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE;
127129
if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
130
+ if( find_option("verbose",0,0)!=0) syncFlags |= SYNC_VERBOSE;
128131
zHttpAuth = find_option("httpauth","B",1);
129132
zDefaultUser = find_option("admin-user","A",1);
130133
clone_ssh_find_options();
131134
url_proxy_options();
132135
@@ -147,11 +150,11 @@
147150
file_copy(g.url.name, g.argv[3]);
148151
db_close(1);
149152
db_open_repository(g.argv[3]);
150153
db_record_repository_filename(g.argv[3]);
151154
url_remember();
152
- if( !bPrivate ) delete_private_content();
155
+ if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content();
153156
shun_artifacts();
154157
db_create_default_users(1, zDefaultUser);
155158
if( zDefaultUser ){
156159
g.zLogin = zDefaultUser;
157160
}else{
@@ -184,11 +187,11 @@
184187
);
185188
url_enable_proxy(0);
186189
clone_ssh_db_set_options();
187190
url_get_password_if_needed();
188191
g.xlinkClusterOnly = 1;
189
- nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
192
+ nErr = client_sync(syncFlags,CONFIGSET_ALL,0);
190193
g.xlinkClusterOnly = 0;
191194
verify_cancel();
192195
db_end_transaction(0);
193196
db_close(1);
194197
if( nErr ){
195198
--- src/clone.c
+++ src/clone.c
@@ -110,23 +110,26 @@
110 ** --once Don't save url.
111 ** --private Also clone private branches
112 ** --ssl-identity=filename Use the SSL identity if requested by the server
113 ** --ssh-command|-c 'command' Use this SSH command
114 ** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests
 
115 **
116 ** See also: init
117 */
118 void clone_cmd(void){
119 char *zPassword;
120 const char *zDefaultUser; /* Optional name of the default user */
121 const char *zHttpAuth; /* HTTP Authorization user:pass information */
122 int nErr = 0;
123 int bPrivate = 0; /* Also clone private branches */
124 int urlFlags = URL_PROMPT_PW | URL_REMEMBER;
 
125
126 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
 
127 if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
 
128 zHttpAuth = find_option("httpauth","B",1);
129 zDefaultUser = find_option("admin-user","A",1);
130 clone_ssh_find_options();
131 url_proxy_options();
132
@@ -147,11 +150,11 @@
147 file_copy(g.url.name, g.argv[3]);
148 db_close(1);
149 db_open_repository(g.argv[3]);
150 db_record_repository_filename(g.argv[3]);
151 url_remember();
152 if( !bPrivate ) delete_private_content();
153 shun_artifacts();
154 db_create_default_users(1, zDefaultUser);
155 if( zDefaultUser ){
156 g.zLogin = zDefaultUser;
157 }else{
@@ -184,11 +187,11 @@
184 );
185 url_enable_proxy(0);
186 clone_ssh_db_set_options();
187 url_get_password_if_needed();
188 g.xlinkClusterOnly = 1;
189 nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
190 g.xlinkClusterOnly = 0;
191 verify_cancel();
192 db_end_transaction(0);
193 db_close(1);
194 if( nErr ){
195
--- src/clone.c
+++ src/clone.c
@@ -110,23 +110,26 @@
110 ** --once Don't save url.
111 ** --private Also clone private branches
112 ** --ssl-identity=filename Use the SSL identity if requested by the server
113 ** --ssh-command|-c 'command' Use this SSH command
114 ** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests
115 ** --verbose Show more statistics in output
116 **
117 ** See also: init
118 */
119 void clone_cmd(void){
120 char *zPassword;
121 const char *zDefaultUser; /* Optional name of the default user */
122 const char *zHttpAuth; /* HTTP Authorization user:pass information */
123 int nErr = 0;
 
124 int urlFlags = URL_PROMPT_PW | URL_REMEMBER;
125 int syncFlags = SYNC_CLONE;
126
127 /* Also clone private branches */
128 if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE;
129 if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
130 if( find_option("verbose",0,0)!=0) syncFlags |= SYNC_VERBOSE;
131 zHttpAuth = find_option("httpauth","B",1);
132 zDefaultUser = find_option("admin-user","A",1);
133 clone_ssh_find_options();
134 url_proxy_options();
135
@@ -147,11 +150,11 @@
150 file_copy(g.url.name, g.argv[3]);
151 db_close(1);
152 db_open_repository(g.argv[3]);
153 db_record_repository_filename(g.argv[3]);
154 url_remember();
155 if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content();
156 shun_artifacts();
157 db_create_default_users(1, zDefaultUser);
158 if( zDefaultUser ){
159 g.zLogin = zDefaultUser;
160 }else{
@@ -184,11 +187,11 @@
187 );
188 url_enable_proxy(0);
189 clone_ssh_db_set_options();
190 url_get_password_if_needed();
191 g.xlinkClusterOnly = 1;
192 nErr = client_sync(syncFlags,CONFIGSET_ALL,0);
193 g.xlinkClusterOnly = 0;
194 verify_cancel();
195 db_end_transaction(0);
196 db_close(1);
197 if( nErr ){
198
+29 -32
--- src/db.c
+++ src/db.c
@@ -958,30 +958,47 @@
958958
g.zConfigDbType = "configdb";
959959
}
960960
g.zConfigDbName = zDbName;
961961
}
962962
963
+/*
964
+** Return TRUE if zTable exists.
965
+*/
966
+int db_table_exists(
967
+ const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */
968
+ const char *zTable /* Name of table */
969
+){
970
+ return sqlite3_table_column_metadata(g.db,
971
+ zDb ? db_name(zDb) : 0, zTable, 0,
972
+ 0, 0, 0, 0, 0)==SQLITE_OK;
973
+}
974
+
975
+/*
976
+** Return TRUE if zTable exists and contains column zColumn.
977
+** Return FALSE if zTable does not exist or if zTable exists
978
+** but lacks zColumn.
979
+*/
980
+int db_table_has_column(
981
+ const char *zDb, /* One of: NULL, "config", "localdb", "repository" */
982
+ const char *zTable, /* Name of table */
983
+ const char *zColumn /* Name of column in table */
984
+){
985
+ return sqlite3_table_column_metadata(g.db,
986
+ zDb ? db_name(zDb) : 0, zTable, zColumn,
987
+ 0, 0, 0, 0, 0)==SQLITE_OK;
988
+}
963989
964990
/*
965991
** Returns TRUE if zTable exists in the local database but lacks column
966992
** zColumn
967993
*/
968994
static int db_local_table_exists_but_lacks_column(
969995
const char *zTable,
970996
const char *zColumn
971997
){
972
- char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
973
- " WHERE name==%Q /*scan*/",
974
- db_name("localdb"), zTable);
975
- int rc = 0;
976
- if( zDef ){
977
- char *zPattern = mprintf("* %s *", zColumn);
978
- rc = sqlite3_strglob(zPattern, zDef)!=0;
979
- fossil_free(zPattern);
980
- fossil_free(zDef);
981
- }
982
- return rc;
998
+ return db_table_exists(db_name("localdb"), zTable)
999
+ && !db_table_has_column(db_name("localdb"), zTable, zColumn);
9831000
}
9841001
9851002
/*
9861003
** If zDbName is a valid local database file, open it and return
9871004
** true. If it is not a valid local database file, return 0.
@@ -1255,10 +1272,11 @@
12551272
fossil_fatal("not in a local checkout");
12561273
return;
12571274
}
12581275
db_open_or_attach(zRepo, "test_repo", 0);
12591276
db_lset("repository", blob_str(&repo));
1277
+ db_record_repository_filename(blob_str(&repo));
12601278
db_close(1);
12611279
}
12621280
12631281
12641282
/*
@@ -2047,31 +2065,10 @@
20472065
}
20482066
void db_lset_int(const char *zName, int value){
20492067
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
20502068
}
20512069
2052
-/*
2053
-** Returns non-0 if the database (which must be open) table identified
2054
-** by zTableName has a column named zColName (case-sensitive), else
2055
-** returns 0.
2056
-*/
2057
-int db_table_has_column(const char *zTableName, const char *zColName){
2058
- Stmt q = empty_Stmt;
2059
- int rc = 0;
2060
- db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
2061
- while(SQLITE_ROW == db_step(&q)){
2062
- /* Columns: (cid, name, type, notnull, dflt_value, pk) */
2063
- const char *zCol = db_column_text(&q, 1);
2064
- if( 0==fossil_strcmp(zColName, zCol) ){
2065
- rc = 1;
2066
- break;
2067
- }
2068
- }
2069
- db_finalize(&q);
2070
- return rc;
2071
-}
2072
-
20732070
/*
20742071
** Record the name of a local repository in the global_config() database.
20752072
** The repository filename %s is recorded as an entry with a "name" field
20762073
** of the following form:
20772074
**
20782075
--- src/db.c
+++ src/db.c
@@ -958,30 +958,47 @@
958 g.zConfigDbType = "configdb";
959 }
960 g.zConfigDbName = zDbName;
961 }
962
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
963
964 /*
965 ** Returns TRUE if zTable exists in the local database but lacks column
966 ** zColumn
967 */
968 static int db_local_table_exists_but_lacks_column(
969 const char *zTable,
970 const char *zColumn
971 ){
972 char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
973 " WHERE name==%Q /*scan*/",
974 db_name("localdb"), zTable);
975 int rc = 0;
976 if( zDef ){
977 char *zPattern = mprintf("* %s *", zColumn);
978 rc = sqlite3_strglob(zPattern, zDef)!=0;
979 fossil_free(zPattern);
980 fossil_free(zDef);
981 }
982 return rc;
983 }
984
985 /*
986 ** If zDbName is a valid local database file, open it and return
987 ** true. If it is not a valid local database file, return 0.
@@ -1255,10 +1272,11 @@
1255 fossil_fatal("not in a local checkout");
1256 return;
1257 }
1258 db_open_or_attach(zRepo, "test_repo", 0);
1259 db_lset("repository", blob_str(&repo));
 
1260 db_close(1);
1261 }
1262
1263
1264 /*
@@ -2047,31 +2065,10 @@
2047 }
2048 void db_lset_int(const char *zName, int value){
2049 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
2050 }
2051
2052 /*
2053 ** Returns non-0 if the database (which must be open) table identified
2054 ** by zTableName has a column named zColName (case-sensitive), else
2055 ** returns 0.
2056 */
2057 int db_table_has_column(const char *zTableName, const char *zColName){
2058 Stmt q = empty_Stmt;
2059 int rc = 0;
2060 db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
2061 while(SQLITE_ROW == db_step(&q)){
2062 /* Columns: (cid, name, type, notnull, dflt_value, pk) */
2063 const char *zCol = db_column_text(&q, 1);
2064 if( 0==fossil_strcmp(zColName, zCol) ){
2065 rc = 1;
2066 break;
2067 }
2068 }
2069 db_finalize(&q);
2070 return rc;
2071 }
2072
2073 /*
2074 ** Record the name of a local repository in the global_config() database.
2075 ** The repository filename %s is recorded as an entry with a "name" field
2076 ** of the following form:
2077 **
2078
--- src/db.c
+++ src/db.c
@@ -958,30 +958,47 @@
958 g.zConfigDbType = "configdb";
959 }
960 g.zConfigDbName = zDbName;
961 }
962
963 /*
964 ** Return TRUE if zTable exists.
965 */
966 int db_table_exists(
967 const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */
968 const char *zTable /* Name of table */
969 ){
970 return sqlite3_table_column_metadata(g.db,
971 zDb ? db_name(zDb) : 0, zTable, 0,
972 0, 0, 0, 0, 0)==SQLITE_OK;
973 }
974
975 /*
976 ** Return TRUE if zTable exists and contains column zColumn.
977 ** Return FALSE if zTable does not exist or if zTable exists
978 ** but lacks zColumn.
979 */
980 int db_table_has_column(
981 const char *zDb, /* One of: NULL, "config", "localdb", "repository" */
982 const char *zTable, /* Name of table */
983 const char *zColumn /* Name of column in table */
984 ){
985 return sqlite3_table_column_metadata(g.db,
986 zDb ? db_name(zDb) : 0, zTable, zColumn,
987 0, 0, 0, 0, 0)==SQLITE_OK;
988 }
989
990 /*
991 ** Returns TRUE if zTable exists in the local database but lacks column
992 ** zColumn
993 */
994 static int db_local_table_exists_but_lacks_column(
995 const char *zTable,
996 const char *zColumn
997 ){
998 return db_table_exists(db_name("localdb"), zTable)
999 && !db_table_has_column(db_name("localdb"), zTable, zColumn);
 
 
 
 
 
 
 
 
 
1000 }
1001
1002 /*
1003 ** If zDbName is a valid local database file, open it and return
1004 ** true. If it is not a valid local database file, return 0.
@@ -1255,10 +1272,11 @@
1272 fossil_fatal("not in a local checkout");
1273 return;
1274 }
1275 db_open_or_attach(zRepo, "test_repo", 0);
1276 db_lset("repository", blob_str(&repo));
1277 db_record_repository_filename(blob_str(&repo));
1278 db_close(1);
1279 }
1280
1281
1282 /*
@@ -2047,31 +2065,10 @@
2065 }
2066 void db_lset_int(const char *zName, int value){
2067 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
2068 }
2069
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2070 /*
2071 ** Record the name of a local repository in the global_config() database.
2072 ** The repository filename %s is recorded as an entry with a "name" field
2073 ** of the following form:
2074 **
2075
+29 -32
--- src/db.c
+++ src/db.c
@@ -958,30 +958,47 @@
958958
g.zConfigDbType = "configdb";
959959
}
960960
g.zConfigDbName = zDbName;
961961
}
962962
963
+/*
964
+** Return TRUE if zTable exists.
965
+*/
966
+int db_table_exists(
967
+ const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */
968
+ const char *zTable /* Name of table */
969
+){
970
+ return sqlite3_table_column_metadata(g.db,
971
+ zDb ? db_name(zDb) : 0, zTable, 0,
972
+ 0, 0, 0, 0, 0)==SQLITE_OK;
973
+}
974
+
975
+/*
976
+** Return TRUE if zTable exists and contains column zColumn.
977
+** Return FALSE if zTable does not exist or if zTable exists
978
+** but lacks zColumn.
979
+*/
980
+int db_table_has_column(
981
+ const char *zDb, /* One of: NULL, "config", "localdb", "repository" */
982
+ const char *zTable, /* Name of table */
983
+ const char *zColumn /* Name of column in table */
984
+){
985
+ return sqlite3_table_column_metadata(g.db,
986
+ zDb ? db_name(zDb) : 0, zTable, zColumn,
987
+ 0, 0, 0, 0, 0)==SQLITE_OK;
988
+}
963989
964990
/*
965991
** Returns TRUE if zTable exists in the local database but lacks column
966992
** zColumn
967993
*/
968994
static int db_local_table_exists_but_lacks_column(
969995
const char *zTable,
970996
const char *zColumn
971997
){
972
- char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
973
- " WHERE name==%Q /*scan*/",
974
- db_name("localdb"), zTable);
975
- int rc = 0;
976
- if( zDef ){
977
- char *zPattern = mprintf("* %s *", zColumn);
978
- rc = sqlite3_strglob(zPattern, zDef)!=0;
979
- fossil_free(zPattern);
980
- fossil_free(zDef);
981
- }
982
- return rc;
998
+ return db_table_exists(db_name("localdb"), zTable)
999
+ && !db_table_has_column(db_name("localdb"), zTable, zColumn);
9831000
}
9841001
9851002
/*
9861003
** If zDbName is a valid local database file, open it and return
9871004
** true. If it is not a valid local database file, return 0.
@@ -1255,10 +1272,11 @@
12551272
fossil_fatal("not in a local checkout");
12561273
return;
12571274
}
12581275
db_open_or_attach(zRepo, "test_repo", 0);
12591276
db_lset("repository", blob_str(&repo));
1277
+ db_record_repository_filename(blob_str(&repo));
12601278
db_close(1);
12611279
}
12621280
12631281
12641282
/*
@@ -2047,31 +2065,10 @@
20472065
}
20482066
void db_lset_int(const char *zName, int value){
20492067
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
20502068
}
20512069
2052
-/*
2053
-** Returns non-0 if the database (which must be open) table identified
2054
-** by zTableName has a column named zColName (case-sensitive), else
2055
-** returns 0.
2056
-*/
2057
-int db_table_has_column(const char *zTableName, const char *zColName){
2058
- Stmt q = empty_Stmt;
2059
- int rc = 0;
2060
- db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
2061
- while(SQLITE_ROW == db_step(&q)){
2062
- /* Columns: (cid, name, type, notnull, dflt_value, pk) */
2063
- const char *zCol = db_column_text(&q, 1);
2064
- if( 0==fossil_strcmp(zColName, zCol) ){
2065
- rc = 1;
2066
- break;
2067
- }
2068
- }
2069
- db_finalize(&q);
2070
- return rc;
2071
-}
2072
-
20732070
/*
20742071
** Record the name of a local repository in the global_config() database.
20752072
** The repository filename %s is recorded as an entry with a "name" field
20762073
** of the following form:
20772074
**
20782075
--- src/db.c
+++ src/db.c
@@ -958,30 +958,47 @@
958 g.zConfigDbType = "configdb";
959 }
960 g.zConfigDbName = zDbName;
961 }
962
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
963
964 /*
965 ** Returns TRUE if zTable exists in the local database but lacks column
966 ** zColumn
967 */
968 static int db_local_table_exists_but_lacks_column(
969 const char *zTable,
970 const char *zColumn
971 ){
972 char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
973 " WHERE name==%Q /*scan*/",
974 db_name("localdb"), zTable);
975 int rc = 0;
976 if( zDef ){
977 char *zPattern = mprintf("* %s *", zColumn);
978 rc = sqlite3_strglob(zPattern, zDef)!=0;
979 fossil_free(zPattern);
980 fossil_free(zDef);
981 }
982 return rc;
983 }
984
985 /*
986 ** If zDbName is a valid local database file, open it and return
987 ** true. If it is not a valid local database file, return 0.
@@ -1255,10 +1272,11 @@
1255 fossil_fatal("not in a local checkout");
1256 return;
1257 }
1258 db_open_or_attach(zRepo, "test_repo", 0);
1259 db_lset("repository", blob_str(&repo));
 
1260 db_close(1);
1261 }
1262
1263
1264 /*
@@ -2047,31 +2065,10 @@
2047 }
2048 void db_lset_int(const char *zName, int value){
2049 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
2050 }
2051
2052 /*
2053 ** Returns non-0 if the database (which must be open) table identified
2054 ** by zTableName has a column named zColName (case-sensitive), else
2055 ** returns 0.
2056 */
2057 int db_table_has_column(const char *zTableName, const char *zColName){
2058 Stmt q = empty_Stmt;
2059 int rc = 0;
2060 db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
2061 while(SQLITE_ROW == db_step(&q)){
2062 /* Columns: (cid, name, type, notnull, dflt_value, pk) */
2063 const char *zCol = db_column_text(&q, 1);
2064 if( 0==fossil_strcmp(zColName, zCol) ){
2065 rc = 1;
2066 break;
2067 }
2068 }
2069 db_finalize(&q);
2070 return rc;
2071 }
2072
2073 /*
2074 ** Record the name of a local repository in the global_config() database.
2075 ** The repository filename %s is recorded as an entry with a "name" field
2076 ** of the following form:
2077 **
2078
--- src/db.c
+++ src/db.c
@@ -958,30 +958,47 @@
958 g.zConfigDbType = "configdb";
959 }
960 g.zConfigDbName = zDbName;
961 }
962
963 /*
964 ** Return TRUE if zTable exists.
965 */
966 int db_table_exists(
967 const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */
968 const char *zTable /* Name of table */
969 ){
970 return sqlite3_table_column_metadata(g.db,
971 zDb ? db_name(zDb) : 0, zTable, 0,
972 0, 0, 0, 0, 0)==SQLITE_OK;
973 }
974
975 /*
976 ** Return TRUE if zTable exists and contains column zColumn.
977 ** Return FALSE if zTable does not exist or if zTable exists
978 ** but lacks zColumn.
979 */
980 int db_table_has_column(
981 const char *zDb, /* One of: NULL, "config", "localdb", "repository" */
982 const char *zTable, /* Name of table */
983 const char *zColumn /* Name of column in table */
984 ){
985 return sqlite3_table_column_metadata(g.db,
986 zDb ? db_name(zDb) : 0, zTable, zColumn,
987 0, 0, 0, 0, 0)==SQLITE_OK;
988 }
989
990 /*
991 ** Returns TRUE if zTable exists in the local database but lacks column
992 ** zColumn
993 */
994 static int db_local_table_exists_but_lacks_column(
995 const char *zTable,
996 const char *zColumn
997 ){
998 return db_table_exists(db_name("localdb"), zTable)
999 && !db_table_has_column(db_name("localdb"), zTable, zColumn);
 
 
 
 
 
 
 
 
 
1000 }
1001
1002 /*
1003 ** If zDbName is a valid local database file, open it and return
1004 ** true. If it is not a valid local database file, return 0.
@@ -1255,10 +1272,11 @@
1272 fossil_fatal("not in a local checkout");
1273 return;
1274 }
1275 db_open_or_attach(zRepo, "test_repo", 0);
1276 db_lset("repository", blob_str(&repo));
1277 db_record_repository_filename(blob_str(&repo));
1278 db_close(1);
1279 }
1280
1281
1282 /*
@@ -2047,31 +2065,10 @@
2065 }
2066 void db_lset_int(const char *zName, int value){
2067 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
2068 }
2069
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2070 /*
2071 ** Record the name of a local repository in the global_config() database.
2072 ** The repository filename %s is recorded as an entry with a "name" field
2073 ** of the following form:
2074 **
2075
+2 -2
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -363,20 +363,20 @@
363363
"SELECT pathname, 0, 0, 1, 0, islink"
364364
" FROM vfile v2"
365365
" WHERE v2.vid=%d"
366366
" AND NOT EXISTS(SELECT 1 FROM vfile v1"
367367
" WHERE v1.vid=%d AND v1.pathname=v2.pathname)"
368
- " ORDER BY 1",
368
+ " ORDER BY 1 /*scan*/",
369369
rid, vid, rid, vid, vid, rid
370370
);
371371
}else{
372372
blob_append_sql(&sql,
373373
"SELECT pathname, deleted, chnged , rid==0, rid, islink"
374374
" FROM vfile"
375375
" WHERE vid=%d"
376376
" AND (deleted OR chnged OR rid==0)"
377
- " ORDER BY pathname",
377
+ " ORDER BY pathname /*scan*/",
378378
vid
379379
);
380380
}
381381
db_prepare(&q, "%s", blob_sql_text(&sql));
382382
while( db_step(&q)==SQLITE_ROW ){
383383
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -363,20 +363,20 @@
363 "SELECT pathname, 0, 0, 1, 0, islink"
364 " FROM vfile v2"
365 " WHERE v2.vid=%d"
366 " AND NOT EXISTS(SELECT 1 FROM vfile v1"
367 " WHERE v1.vid=%d AND v1.pathname=v2.pathname)"
368 " ORDER BY 1",
369 rid, vid, rid, vid, vid, rid
370 );
371 }else{
372 blob_append_sql(&sql,
373 "SELECT pathname, deleted, chnged , rid==0, rid, islink"
374 " FROM vfile"
375 " WHERE vid=%d"
376 " AND (deleted OR chnged OR rid==0)"
377 " ORDER BY pathname",
378 vid
379 );
380 }
381 db_prepare(&q, "%s", blob_sql_text(&sql));
382 while( db_step(&q)==SQLITE_ROW ){
383
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -363,20 +363,20 @@
363 "SELECT pathname, 0, 0, 1, 0, islink"
364 " FROM vfile v2"
365 " WHERE v2.vid=%d"
366 " AND NOT EXISTS(SELECT 1 FROM vfile v1"
367 " WHERE v1.vid=%d AND v1.pathname=v2.pathname)"
368 " ORDER BY 1 /*scan*/",
369 rid, vid, rid, vid, vid, rid
370 );
371 }else{
372 blob_append_sql(&sql,
373 "SELECT pathname, deleted, chnged , rid==0, rid, islink"
374 " FROM vfile"
375 " WHERE vid=%d"
376 " AND (deleted OR chnged OR rid==0)"
377 " ORDER BY pathname /*scan*/",
378 vid
379 );
380 }
381 db_prepare(&q, "%s", blob_sql_text(&sql));
382 while( db_step(&q)==SQLITE_ROW ){
383
+10 -6
--- src/foci.c
+++ src/foci.c
@@ -46,11 +46,12 @@
4646
sqlite3_vtab base; /* Base class - must be first */
4747
};
4848
struct FociCursor {
4949
sqlite3_vtab_cursor base; /* Base class - must be first */
5050
Manifest *pMan; /* Current manifest */
51
- int iFile; /* Index of current file */
51
+ ManifestFile *pFile; /* Current file */
52
+ int iFile; /* File index */
5253
};
5354
#endif /* INTERFACE */
5455
5556
5657
/*
@@ -127,17 +128,18 @@
127128
/*
128129
** Move a focivfs cursor to the next entry in the file.
129130
*/
130131
static int fociNext(sqlite3_vtab_cursor *pCursor){
131132
FociCursor *pCsr = (FociCursor *)pCursor;
133
+ pCsr->pFile = manifest_file_next(pCsr->pMan, 0);
132134
pCsr->iFile++;
133135
return SQLITE_OK;
134136
}
135137
136138
static int fociEof(sqlite3_vtab_cursor *pCursor){
137139
FociCursor *pCsr = (FociCursor *)pCursor;
138
- return pCsr->pMan==0 || pCsr->iFile>=pCsr->pMan->nFile;
140
+ return pCsr->pFile==0;
139141
}
140142
141143
static int fociFilter(
142144
sqlite3_vtab_cursor *pCursor,
143145
int idxNum, const char *idxStr,
@@ -146,10 +148,12 @@
146148
FociCursor *pCur = (FociCursor *)pCursor;
147149
manifest_destroy(pCur->pMan);
148150
if( idxNum ){
149151
pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
150152
pCur->iFile = 0;
153
+ manifest_file_rewind(pCur->pMan);
154
+ pCur->pFile = manifest_file_next(pCur->pMan, 0);
151155
}else{
152156
pCur->pMan = 0;
153157
pCur->iFile = 0;
154158
}
155159
return SQLITE_OK;
@@ -164,23 +168,23 @@
164168
switch( i ){
165169
case 0: /* checkinID */
166170
sqlite3_result_int(ctx, pCsr->pMan->rid);
167171
break;
168172
case 1: /* filename */
169
- sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zName, -1,
173
+ sqlite3_result_text(ctx, pCsr->pFile->zName, -1,
170174
SQLITE_TRANSIENT);
171175
break;
172176
case 2: /* uuid */
173
- sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zUuid, -1,
177
+ sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1,
174178
SQLITE_TRANSIENT);
175179
break;
176180
case 3: /* previousName */
177
- sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPrior, -1,
181
+ sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1,
178182
SQLITE_TRANSIENT);
179183
break;
180184
case 4: /* perm */
181
- sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPerm, -1,
185
+ sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1,
182186
SQLITE_TRANSIENT);
183187
break;
184188
}
185189
return SQLITE_OK;
186190
}
187191
--- src/foci.c
+++ src/foci.c
@@ -46,11 +46,12 @@
46 sqlite3_vtab base; /* Base class - must be first */
47 };
48 struct FociCursor {
49 sqlite3_vtab_cursor base; /* Base class - must be first */
50 Manifest *pMan; /* Current manifest */
51 int iFile; /* Index of current file */
 
52 };
53 #endif /* INTERFACE */
54
55
56 /*
@@ -127,17 +128,18 @@
127 /*
128 ** Move a focivfs cursor to the next entry in the file.
129 */
130 static int fociNext(sqlite3_vtab_cursor *pCursor){
131 FociCursor *pCsr = (FociCursor *)pCursor;
 
132 pCsr->iFile++;
133 return SQLITE_OK;
134 }
135
136 static int fociEof(sqlite3_vtab_cursor *pCursor){
137 FociCursor *pCsr = (FociCursor *)pCursor;
138 return pCsr->pMan==0 || pCsr->iFile>=pCsr->pMan->nFile;
139 }
140
141 static int fociFilter(
142 sqlite3_vtab_cursor *pCursor,
143 int idxNum, const char *idxStr,
@@ -146,10 +148,12 @@
146 FociCursor *pCur = (FociCursor *)pCursor;
147 manifest_destroy(pCur->pMan);
148 if( idxNum ){
149 pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
150 pCur->iFile = 0;
 
 
151 }else{
152 pCur->pMan = 0;
153 pCur->iFile = 0;
154 }
155 return SQLITE_OK;
@@ -164,23 +168,23 @@
164 switch( i ){
165 case 0: /* checkinID */
166 sqlite3_result_int(ctx, pCsr->pMan->rid);
167 break;
168 case 1: /* filename */
169 sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zName, -1,
170 SQLITE_TRANSIENT);
171 break;
172 case 2: /* uuid */
173 sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zUuid, -1,
174 SQLITE_TRANSIENT);
175 break;
176 case 3: /* previousName */
177 sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPrior, -1,
178 SQLITE_TRANSIENT);
179 break;
180 case 4: /* perm */
181 sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPerm, -1,
182 SQLITE_TRANSIENT);
183 break;
184 }
185 return SQLITE_OK;
186 }
187
--- src/foci.c
+++ src/foci.c
@@ -46,11 +46,12 @@
46 sqlite3_vtab base; /* Base class - must be first */
47 };
48 struct FociCursor {
49 sqlite3_vtab_cursor base; /* Base class - must be first */
50 Manifest *pMan; /* Current manifest */
51 ManifestFile *pFile; /* Current file */
52 int iFile; /* File index */
53 };
54 #endif /* INTERFACE */
55
56
57 /*
@@ -127,17 +128,18 @@
128 /*
129 ** Move a focivfs cursor to the next entry in the file.
130 */
131 static int fociNext(sqlite3_vtab_cursor *pCursor){
132 FociCursor *pCsr = (FociCursor *)pCursor;
133 pCsr->pFile = manifest_file_next(pCsr->pMan, 0);
134 pCsr->iFile++;
135 return SQLITE_OK;
136 }
137
138 static int fociEof(sqlite3_vtab_cursor *pCursor){
139 FociCursor *pCsr = (FociCursor *)pCursor;
140 return pCsr->pFile==0;
141 }
142
143 static int fociFilter(
144 sqlite3_vtab_cursor *pCursor,
145 int idxNum, const char *idxStr,
@@ -146,10 +148,12 @@
148 FociCursor *pCur = (FociCursor *)pCursor;
149 manifest_destroy(pCur->pMan);
150 if( idxNum ){
151 pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
152 pCur->iFile = 0;
153 manifest_file_rewind(pCur->pMan);
154 pCur->pFile = manifest_file_next(pCur->pMan, 0);
155 }else{
156 pCur->pMan = 0;
157 pCur->iFile = 0;
158 }
159 return SQLITE_OK;
@@ -164,23 +168,23 @@
168 switch( i ){
169 case 0: /* checkinID */
170 sqlite3_result_int(ctx, pCsr->pMan->rid);
171 break;
172 case 1: /* filename */
173 sqlite3_result_text(ctx, pCsr->pFile->zName, -1,
174 SQLITE_TRANSIENT);
175 break;
176 case 2: /* uuid */
177 sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1,
178 SQLITE_TRANSIENT);
179 break;
180 case 3: /* previousName */
181 sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1,
182 SQLITE_TRANSIENT);
183 break;
184 case 4: /* perm */
185 sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1,
186 SQLITE_TRANSIENT);
187 break;
188 }
189 return SQLITE_OK;
190 }
191
+8 -6
--- src/http.c
+++ src/http.c
@@ -285,11 +285,11 @@
285285
g.zHttpAuth = prompt_for_httpauth_creds();
286286
transport_close(&g.url);
287287
return http_exchange(pSend, pReply, useLogin, maxRedirect);
288288
}
289289
}
290
- if( rc!=200 && rc!=302 ){
290
+ if( rc!=200 && rc!=301 && rc!=302 ){
291291
int ii;
292292
for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
293293
while( zLine[ii]==' ' ) ii++;
294294
fossil_warning("server says: %s", &zLine[ii]);
295295
goto write_err;
@@ -299,11 +299,11 @@
299299
}else{
300300
closeConnection = 0;
301301
}
302302
}else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
303303
if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
304
- if( rc!=200 && rc!=302 ){
304
+ if( rc!=200 && rc!=301 && rc!=302 ){
305305
int ii;
306306
for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
307307
while( zLine[ii]==' ' ) ii++;
308308
fossil_warning("server says: %s", &zLine[ii]);
309309
goto write_err;
@@ -319,11 +319,12 @@
319319
if( c=='c' || c=='C' ){
320320
closeConnection = 1;
321321
}else if( c=='k' || c=='K' ){
322322
closeConnection = 0;
323323
}
324
- }else if( rc==302 && fossil_strnicmp(zLine, "location:", 9)==0 ){
324
+ }else if( ( rc==301 || rc==302 ) &&
325
+ fossil_strnicmp(zLine, "location:", 9)==0 ){
325326
int i, j;
326327
327328
if ( --maxRedirect == 0){
328329
fossil_warning("redirect limit exceeded");
329330
goto write_err;
@@ -336,16 +337,17 @@
336337
j = strlen(zLine) - 1;
337338
while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
338339
j -= 4;
339340
zLine[j] = 0;
340341
}
341
- fossil_print("redirect to %s\n", &zLine[i]);
342
+ transport_close(&g.url);
343
+ transport_global_shutdown(&g.url);
344
+ fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
342345
url_parse(&zLine[i], 0);
343346
fSeenHttpAuth = 0;
344347
if( g.zHttpAuth ) free(g.zHttpAuth);
345348
g.zHttpAuth = get_httpauth();
346
- transport_close(&g.url);
347349
return http_exchange(pSend, pReply, useLogin, maxRedirect);
348350
}else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
349351
if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
350352
isCompressed = 0;
351353
}else if( fossil_strnicmp(&zLine[14],
@@ -359,11 +361,11 @@
359361
if( iLength<0 ){
360362
fossil_warning("server did not reply");
361363
goto write_err;
362364
}
363365
if( rc!=200 ){
364
- fossil_warning("\"location:\" missing from 302 redirect reply");
366
+ fossil_warning("\"location:\" missing from %d redirect reply", rc);
365367
goto write_err;
366368
}
367369
368370
/*
369371
** Extract the reply payload that follows the header
370372
--- src/http.c
+++ src/http.c
@@ -285,11 +285,11 @@
285 g.zHttpAuth = prompt_for_httpauth_creds();
286 transport_close(&g.url);
287 return http_exchange(pSend, pReply, useLogin, maxRedirect);
288 }
289 }
290 if( rc!=200 && rc!=302 ){
291 int ii;
292 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
293 while( zLine[ii]==' ' ) ii++;
294 fossil_warning("server says: %s", &zLine[ii]);
295 goto write_err;
@@ -299,11 +299,11 @@
299 }else{
300 closeConnection = 0;
301 }
302 }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
303 if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
304 if( rc!=200 && rc!=302 ){
305 int ii;
306 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
307 while( zLine[ii]==' ' ) ii++;
308 fossil_warning("server says: %s", &zLine[ii]);
309 goto write_err;
@@ -319,11 +319,12 @@
319 if( c=='c' || c=='C' ){
320 closeConnection = 1;
321 }else if( c=='k' || c=='K' ){
322 closeConnection = 0;
323 }
324 }else if( rc==302 && fossil_strnicmp(zLine, "location:", 9)==0 ){
 
325 int i, j;
326
327 if ( --maxRedirect == 0){
328 fossil_warning("redirect limit exceeded");
329 goto write_err;
@@ -336,16 +337,17 @@
336 j = strlen(zLine) - 1;
337 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
338 j -= 4;
339 zLine[j] = 0;
340 }
341 fossil_print("redirect to %s\n", &zLine[i]);
 
 
342 url_parse(&zLine[i], 0);
343 fSeenHttpAuth = 0;
344 if( g.zHttpAuth ) free(g.zHttpAuth);
345 g.zHttpAuth = get_httpauth();
346 transport_close(&g.url);
347 return http_exchange(pSend, pReply, useLogin, maxRedirect);
348 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
349 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
350 isCompressed = 0;
351 }else if( fossil_strnicmp(&zLine[14],
@@ -359,11 +361,11 @@
359 if( iLength<0 ){
360 fossil_warning("server did not reply");
361 goto write_err;
362 }
363 if( rc!=200 ){
364 fossil_warning("\"location:\" missing from 302 redirect reply");
365 goto write_err;
366 }
367
368 /*
369 ** Extract the reply payload that follows the header
370
--- src/http.c
+++ src/http.c
@@ -285,11 +285,11 @@
285 g.zHttpAuth = prompt_for_httpauth_creds();
286 transport_close(&g.url);
287 return http_exchange(pSend, pReply, useLogin, maxRedirect);
288 }
289 }
290 if( rc!=200 && rc!=301 && rc!=302 ){
291 int ii;
292 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
293 while( zLine[ii]==' ' ) ii++;
294 fossil_warning("server says: %s", &zLine[ii]);
295 goto write_err;
@@ -299,11 +299,11 @@
299 }else{
300 closeConnection = 0;
301 }
302 }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
303 if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
304 if( rc!=200 && rc!=301 && rc!=302 ){
305 int ii;
306 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
307 while( zLine[ii]==' ' ) ii++;
308 fossil_warning("server says: %s", &zLine[ii]);
309 goto write_err;
@@ -319,11 +319,12 @@
319 if( c=='c' || c=='C' ){
320 closeConnection = 1;
321 }else if( c=='k' || c=='K' ){
322 closeConnection = 0;
323 }
324 }else if( ( rc==301 || rc==302 ) &&
325 fossil_strnicmp(zLine, "location:", 9)==0 ){
326 int i, j;
327
328 if ( --maxRedirect == 0){
329 fossil_warning("redirect limit exceeded");
330 goto write_err;
@@ -336,16 +337,17 @@
337 j = strlen(zLine) - 1;
338 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
339 j -= 4;
340 zLine[j] = 0;
341 }
342 transport_close(&g.url);
343 transport_global_shutdown(&g.url);
344 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
345 url_parse(&zLine[i], 0);
346 fSeenHttpAuth = 0;
347 if( g.zHttpAuth ) free(g.zHttpAuth);
348 g.zHttpAuth = get_httpauth();
 
349 return http_exchange(pSend, pReply, useLogin, maxRedirect);
350 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
351 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
352 isCompressed = 0;
353 }else if( fossil_strnicmp(&zLine[14],
@@ -359,11 +361,11 @@
361 if( iLength<0 ){
362 fossil_warning("server did not reply");
363 goto write_err;
364 }
365 if( rc!=200 ){
366 fossil_warning("\"location:\" missing from %d redirect reply", rc);
367 goto write_err;
368 }
369
370 /*
371 ** Extract the reply payload that follows the header
372
--- src/http_socket.c
+++ src/http_socket.c
@@ -45,10 +45,11 @@
4545
** There can only be a single socket connection open at a time.
4646
** State information about that socket is stored in the following
4747
** local variables:
4848
*/
4949
static int socketIsInit = 0; /* True after global initialization */
50
+static int addrIsInit = 0; /* True once addr is initialized */
5051
#if defined(_WIN32)
5152
static WSADATA socketInfo; /* Windows socket initialize data */
5253
#endif
5354
static int iSocket = -1; /* The socket on which we talk to the server */
5455
static char *socketErrMsg = 0; /* Text of most recent socket error */
@@ -105,10 +106,11 @@
105106
WSACleanup();
106107
#endif
107108
socket_clear_errmsg();
108109
socketIsInit = 0;
109110
}
111
+ addrIsInit = 0;
110112
}
111113
112114
/*
113115
** Close the currently open socket. If no socket is open, this routine
114116
** is a no-op.
@@ -133,14 +135,14 @@
133135
**
134136
** Return the number of errors.
135137
*/
136138
int socket_open(UrlData *pUrlData){
137139
static struct sockaddr_in addr; /* The server address */
138
- static int addrIsInit = 0; /* True once addr is initialized */
139140
140141
socket_global_init();
141142
if( !addrIsInit ){
143
+ memset(&addr, 0, sizeof(addr));
142144
addr.sin_family = AF_INET;
143145
addr.sin_port = htons(pUrlData->port);
144146
*(int*)&addr.sin_addr = inet_addr(pUrlData->name);
145147
if( -1 == *(int*)&addr.sin_addr ){
146148
#ifndef FOSSIL_STATIC_LINK
147149
--- src/http_socket.c
+++ src/http_socket.c
@@ -45,10 +45,11 @@
45 ** There can only be a single socket connection open at a time.
46 ** State information about that socket is stored in the following
47 ** local variables:
48 */
49 static int socketIsInit = 0; /* True after global initialization */
 
50 #if defined(_WIN32)
51 static WSADATA socketInfo; /* Windows socket initialize data */
52 #endif
53 static int iSocket = -1; /* The socket on which we talk to the server */
54 static char *socketErrMsg = 0; /* Text of most recent socket error */
@@ -105,10 +106,11 @@
105 WSACleanup();
106 #endif
107 socket_clear_errmsg();
108 socketIsInit = 0;
109 }
 
110 }
111
112 /*
113 ** Close the currently open socket. If no socket is open, this routine
114 ** is a no-op.
@@ -133,14 +135,14 @@
133 **
134 ** Return the number of errors.
135 */
136 int socket_open(UrlData *pUrlData){
137 static struct sockaddr_in addr; /* The server address */
138 static int addrIsInit = 0; /* True once addr is initialized */
139
140 socket_global_init();
141 if( !addrIsInit ){
 
142 addr.sin_family = AF_INET;
143 addr.sin_port = htons(pUrlData->port);
144 *(int*)&addr.sin_addr = inet_addr(pUrlData->name);
145 if( -1 == *(int*)&addr.sin_addr ){
146 #ifndef FOSSIL_STATIC_LINK
147
--- src/http_socket.c
+++ src/http_socket.c
@@ -45,10 +45,11 @@
45 ** There can only be a single socket connection open at a time.
46 ** State information about that socket is stored in the following
47 ** local variables:
48 */
49 static int socketIsInit = 0; /* True after global initialization */
50 static int addrIsInit = 0; /* True once addr is initialized */
51 #if defined(_WIN32)
52 static WSADATA socketInfo; /* Windows socket initialize data */
53 #endif
54 static int iSocket = -1; /* The socket on which we talk to the server */
55 static char *socketErrMsg = 0; /* Text of most recent socket error */
@@ -105,10 +106,11 @@
106 WSACleanup();
107 #endif
108 socket_clear_errmsg();
109 socketIsInit = 0;
110 }
111 addrIsInit = 0;
112 }
113
114 /*
115 ** Close the currently open socket. If no socket is open, this routine
116 ** is a no-op.
@@ -133,14 +135,14 @@
135 **
136 ** Return the number of errors.
137 */
138 int socket_open(UrlData *pUrlData){
139 static struct sockaddr_in addr; /* The server address */
 
140
141 socket_global_init();
142 if( !addrIsInit ){
143 memset(&addr, 0, sizeof(addr));
144 addr.sin_family = AF_INET;
145 addr.sin_port = htons(pUrlData->port);
146 *(int*)&addr.sin_addr = inet_addr(pUrlData->name);
147 if( -1 == *(int*)&addr.sin_addr ){
148 #ifndef FOSSIL_STATIC_LINK
149
+4 -3
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -41,11 +41,11 @@
4141
** There can only be a single OpenSSL IO connection open at a time.
4242
** State information about that IO is stored in the following
4343
** local variables:
4444
*/
4545
static int sslIsInit = 0; /* True after global initialization */
46
-static BIO *iBio; /* OpenSSL I/O abstraction */
46
+static BIO *iBio = 0; /* OpenSSL I/O abstraction */
4747
static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
4848
static SSL_CTX *sslCtx; /* SSL context */
4949
static SSL *ssl;
5050
5151
@@ -99,12 +99,12 @@
9999
SSL_library_init();
100100
SSL_load_error_strings();
101101
ERR_load_BIO_strings();
102102
OpenSSL_add_all_algorithms();
103103
sslCtx = SSL_CTX_new(SSLv23_client_method());
104
- /* Disable SSLv2 */
105
- SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2);
104
+ /* Disable SSLv2 and SSLv3 */
105
+ SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
106106
107107
/* Set up acceptable CA root certificates */
108108
zCaSetting = db_get("ssl-ca-location", 0);
109109
if( zCaSetting==0 || zCaSetting[0]=='\0' ){
110110
/* CA location not specified, use platform's default certificate store */
@@ -171,10 +171,11 @@
171171
*/
172172
void ssl_close(void){
173173
if( iBio!=NULL ){
174174
(void)BIO_reset(iBio);
175175
BIO_free_all(iBio);
176
+ iBio = NULL;
176177
}
177178
}
178179
179180
/* See RFC2817 for details */
180181
static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
181182
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -41,11 +41,11 @@
41 ** There can only be a single OpenSSL IO connection open at a time.
42 ** State information about that IO is stored in the following
43 ** local variables:
44 */
45 static int sslIsInit = 0; /* True after global initialization */
46 static BIO *iBio; /* OpenSSL I/O abstraction */
47 static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
48 static SSL_CTX *sslCtx; /* SSL context */
49 static SSL *ssl;
50
51
@@ -99,12 +99,12 @@
99 SSL_library_init();
100 SSL_load_error_strings();
101 ERR_load_BIO_strings();
102 OpenSSL_add_all_algorithms();
103 sslCtx = SSL_CTX_new(SSLv23_client_method());
104 /* Disable SSLv2 */
105 SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2);
106
107 /* Set up acceptable CA root certificates */
108 zCaSetting = db_get("ssl-ca-location", 0);
109 if( zCaSetting==0 || zCaSetting[0]=='\0' ){
110 /* CA location not specified, use platform's default certificate store */
@@ -171,10 +171,11 @@
171 */
172 void ssl_close(void){
173 if( iBio!=NULL ){
174 (void)BIO_reset(iBio);
175 BIO_free_all(iBio);
 
176 }
177 }
178
179 /* See RFC2817 for details */
180 static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
181
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -41,11 +41,11 @@
41 ** There can only be a single OpenSSL IO connection open at a time.
42 ** State information about that IO is stored in the following
43 ** local variables:
44 */
45 static int sslIsInit = 0; /* True after global initialization */
46 static BIO *iBio = 0; /* OpenSSL I/O abstraction */
47 static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
48 static SSL_CTX *sslCtx; /* SSL context */
49 static SSL *ssl;
50
51
@@ -99,12 +99,12 @@
99 SSL_library_init();
100 SSL_load_error_strings();
101 ERR_load_BIO_strings();
102 OpenSSL_add_all_algorithms();
103 sslCtx = SSL_CTX_new(SSLv23_client_method());
104 /* Disable SSLv2 and SSLv3 */
105 SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
106
107 /* Set up acceptable CA root certificates */
108 zCaSetting = db_get("ssl-ca-location", 0);
109 if( zCaSetting==0 || zCaSetting[0]=='\0' ){
110 /* CA location not specified, use platform's default certificate store */
@@ -171,10 +171,11 @@
171 */
172 void ssl_close(void){
173 if( iBio!=NULL ){
174 (void)BIO_reset(iBio);
175 BIO_free_all(iBio);
176 iBio = NULL;
177 }
178 }
179
180 /* See RFC2817 for details */
181 static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
182
+1 -1
--- src/info.c
+++ src/info.c
@@ -1919,11 +1919,11 @@
19191919
}
19201920
if( strcmp(zModAction,"approve")==0 ){
19211921
moderation_approve(rid);
19221922
}
19231923
}
1924
- zTktTitle = db_table_has_column( "ticket", "title" )
1924
+ zTktTitle = db_table_has_column("repository", "ticket", "title" )
19251925
? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
19261926
: 0;
19271927
style_header("Ticket Change Details");
19281928
style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid);
19291929
style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName);
19301930
--- src/info.c
+++ src/info.c
@@ -1919,11 +1919,11 @@
1919 }
1920 if( strcmp(zModAction,"approve")==0 ){
1921 moderation_approve(rid);
1922 }
1923 }
1924 zTktTitle = db_table_has_column( "ticket", "title" )
1925 ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
1926 : 0;
1927 style_header("Ticket Change Details");
1928 style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid);
1929 style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName);
1930
--- src/info.c
+++ src/info.c
@@ -1919,11 +1919,11 @@
1919 }
1920 if( strcmp(zModAction,"approve")==0 ){
1921 moderation_approve(rid);
1922 }
1923 }
1924 zTktTitle = db_table_has_column("repository", "ticket", "title" )
1925 ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
1926 : 0;
1927 style_header("Ticket Change Details");
1928 style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid);
1929 style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName);
1930
--- src/json_branch.c
+++ src/json_branch.c
@@ -66,11 +66,11 @@
6666
cson_value * payV;
6767
cson_object * pay;
6868
cson_value * listV;
6969
cson_array * list;
7070
char const * range = NULL;
71
- int which = 0;
71
+ int branchListFlags = BRL_OPEN_ONLY;
7272
char * sawConversionError = NULL;
7373
Stmt q;
7474
if( !g.perm.Read ){
7575
json_set_err(FSL_JSON_E_DENIED,
7676
"Requires 'o' permissions.");
@@ -102,19 +102,19 @@
102102
}
103103
/* Normalize range values... */
104104
switch(*range){
105105
case 'c':
106106
range = "closed";
107
- which = -1;
107
+ branchListFlags = BRL_CLOSED_ONLY;
108108
break;
109109
case 'a':
110110
range = "all";
111
- which = 1;
111
+ branchListFlags = BRL_BOTH;
112112
break;
113113
default:
114114
range = "open";
115
- which = 0;
115
+ branchListFlags = BRL_OPEN_ONLY;
116116
break;
117117
};
118118
cson_object_set(pay,"range",json_new_string(range));
119119
120120
if( g.localOpen ){ /* add "current" property (branch name). */
@@ -128,11 +128,11 @@
128128
cson_object_set(pay,"current",json_new_string(zCurrent));
129129
}
130130
}
131131
132132
133
- branch_prepare_list_query(&q, which);
133
+ branch_prepare_list_query(&q, branchListFlags);
134134
cson_object_set(pay,"branches",listV);
135135
while((SQLITE_ROW==db_step(&q))){
136136
cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0);
137137
if(v){
138138
cson_array_append(list,v);
139139
--- src/json_branch.c
+++ src/json_branch.c
@@ -66,11 +66,11 @@
66 cson_value * payV;
67 cson_object * pay;
68 cson_value * listV;
69 cson_array * list;
70 char const * range = NULL;
71 int which = 0;
72 char * sawConversionError = NULL;
73 Stmt q;
74 if( !g.perm.Read ){
75 json_set_err(FSL_JSON_E_DENIED,
76 "Requires 'o' permissions.");
@@ -102,19 +102,19 @@
102 }
103 /* Normalize range values... */
104 switch(*range){
105 case 'c':
106 range = "closed";
107 which = -1;
108 break;
109 case 'a':
110 range = "all";
111 which = 1;
112 break;
113 default:
114 range = "open";
115 which = 0;
116 break;
117 };
118 cson_object_set(pay,"range",json_new_string(range));
119
120 if( g.localOpen ){ /* add "current" property (branch name). */
@@ -128,11 +128,11 @@
128 cson_object_set(pay,"current",json_new_string(zCurrent));
129 }
130 }
131
132
133 branch_prepare_list_query(&q, which);
134 cson_object_set(pay,"branches",listV);
135 while((SQLITE_ROW==db_step(&q))){
136 cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0);
137 if(v){
138 cson_array_append(list,v);
139
--- src/json_branch.c
+++ src/json_branch.c
@@ -66,11 +66,11 @@
66 cson_value * payV;
67 cson_object * pay;
68 cson_value * listV;
69 cson_array * list;
70 char const * range = NULL;
71 int branchListFlags = BRL_OPEN_ONLY;
72 char * sawConversionError = NULL;
73 Stmt q;
74 if( !g.perm.Read ){
75 json_set_err(FSL_JSON_E_DENIED,
76 "Requires 'o' permissions.");
@@ -102,19 +102,19 @@
102 }
103 /* Normalize range values... */
104 switch(*range){
105 case 'c':
106 range = "closed";
107 branchListFlags = BRL_CLOSED_ONLY;
108 break;
109 case 'a':
110 range = "all";
111 branchListFlags = BRL_BOTH;
112 break;
113 default:
114 range = "open";
115 branchListFlags = BRL_OPEN_ONLY;
116 break;
117 };
118 cson_object_set(pay,"range",json_new_string(range));
119
120 if( g.localOpen ){ /* add "current" property (branch name). */
@@ -128,11 +128,11 @@
128 cson_object_set(pay,"current",json_new_string(zCurrent));
129 }
130 }
131
132
133 branch_prepare_list_query(&q, branchListFlags);
134 cson_object_set(pay,"branches",listV);
135 while((SQLITE_ROW==db_step(&q))){
136 cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0);
137 if(v){
138 cson_array_append(list,v);
139
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -88,20 +88,21 @@
8888
db_multi_exec("%s", zSql /*safe-for-%s*/);
8989
}
9090
9191
/*
9292
** Return a pointer to a constant string that forms the basis
93
-** for a timeline query for the JSON interface.
93
+** for a timeline query for the JSON interface. It MUST NOT
94
+** be used in a formatted string argument.
9495
*/
9596
char const * json_timeline_query(void){
9697
/* Field order MUST match that from json_timeline_temp_table()!!! */
9798
static const char zBaseSql[] =
9899
@ SELECT
99100
@ NULL,
100101
@ blob.rid,
101102
@ uuid,
102
- @ CAST(strftime('%%s',event.mtime) AS INTEGER),
103
+ @ CAST(strftime('%s',event.mtime) AS INTEGER),
103104
@ datetime(event.mtime),
104105
@ coalesce(ecomment, comment),
105106
@ coalesce(euser, user),
106107
@ blob.rid IN leaf,
107108
@ bgcolor,
@@ -544,12 +545,11 @@
544545
goto error;
545546
}
546547
547548
#if 0
548549
/* only for testing! */
549
- tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
550
- SET("timelineSql");
550
+ cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))));
551551
#endif
552552
db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/);
553553
blob_reset(&sql);
554554
db_prepare(&q, "SELECT"
555555
" uuid AS uuid,"
556556
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -88,20 +88,21 @@
88 db_multi_exec("%s", zSql /*safe-for-%s*/);
89 }
90
91 /*
92 ** Return a pointer to a constant string that forms the basis
93 ** for a timeline query for the JSON interface.
 
94 */
95 char const * json_timeline_query(void){
96 /* Field order MUST match that from json_timeline_temp_table()!!! */
97 static const char zBaseSql[] =
98 @ SELECT
99 @ NULL,
100 @ blob.rid,
101 @ uuid,
102 @ CAST(strftime('%%s',event.mtime) AS INTEGER),
103 @ datetime(event.mtime),
104 @ coalesce(ecomment, comment),
105 @ coalesce(euser, user),
106 @ blob.rid IN leaf,
107 @ bgcolor,
@@ -544,12 +545,11 @@
544 goto error;
545 }
546
547 #if 0
548 /* only for testing! */
549 tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
550 SET("timelineSql");
551 #endif
552 db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/);
553 blob_reset(&sql);
554 db_prepare(&q, "SELECT"
555 " uuid AS uuid,"
556
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -88,20 +88,21 @@
88 db_multi_exec("%s", zSql /*safe-for-%s*/);
89 }
90
91 /*
92 ** Return a pointer to a constant string that forms the basis
93 ** for a timeline query for the JSON interface. It MUST NOT
94 ** be used in a formatted string argument.
95 */
96 char const * json_timeline_query(void){
97 /* Field order MUST match that from json_timeline_temp_table()!!! */
98 static const char zBaseSql[] =
99 @ SELECT
100 @ NULL,
101 @ blob.rid,
102 @ uuid,
103 @ CAST(strftime('%s',event.mtime) AS INTEGER),
104 @ datetime(event.mtime),
105 @ coalesce(ecomment, comment),
106 @ coalesce(euser, user),
107 @ blob.rid IN leaf,
108 @ bgcolor,
@@ -544,12 +545,11 @@
545 goto error;
546 }
547
548 #if 0
549 /* only for testing! */
550 cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))));
 
551 #endif
552 db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/);
553 blob_reset(&sql);
554 db_prepare(&q, "SELECT"
555 " uuid AS uuid,"
556
+12
--- src/main.mk
+++ src/main.mk
@@ -99,10 +99,11 @@
9999
$(SRCDIR)/schema.c \
100100
$(SRCDIR)/search.c \
101101
$(SRCDIR)/setup.c \
102102
$(SRCDIR)/sha1.c \
103103
$(SRCDIR)/shun.c \
104
+ $(SRCDIR)/sitemap.c \
104105
$(SRCDIR)/skins.c \
105106
$(SRCDIR)/sqlcmd.c \
106107
$(SRCDIR)/stash.c \
107108
$(SRCDIR)/stat.c \
108109
$(SRCDIR)/style.c \
@@ -220,10 +221,11 @@
220221
$(OBJDIR)/schema_.c \
221222
$(OBJDIR)/search_.c \
222223
$(OBJDIR)/setup_.c \
223224
$(OBJDIR)/sha1_.c \
224225
$(OBJDIR)/shun_.c \
226
+ $(OBJDIR)/sitemap_.c \
225227
$(OBJDIR)/skins_.c \
226228
$(OBJDIR)/sqlcmd_.c \
227229
$(OBJDIR)/stash_.c \
228230
$(OBJDIR)/stat_.c \
229231
$(OBJDIR)/style_.c \
@@ -338,10 +340,11 @@
338340
$(OBJDIR)/schema.o \
339341
$(OBJDIR)/search.o \
340342
$(OBJDIR)/setup.o \
341343
$(OBJDIR)/sha1.o \
342344
$(OBJDIR)/shun.o \
345
+ $(OBJDIR)/sitemap.o \
343346
$(OBJDIR)/skins.o \
344347
$(OBJDIR)/sqlcmd.o \
345348
$(OBJDIR)/stash.o \
346349
$(OBJDIR)/stat.o \
347350
$(OBJDIR)/style.o \
@@ -565,10 +568,11 @@
565568
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
566569
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
567570
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
568571
$(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
569572
$(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
573
+ $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
570574
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
571575
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
572576
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
573577
$(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
574578
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1296,10 +1300,18 @@
12961300
12971301
$(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
12981302
$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
12991303
13001304
$(OBJDIR)/shun.h: $(OBJDIR)/headers
1305
+
1306
+$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(OBJDIR)/translate
1307
+ $(OBJDIR)/translate $(SRCDIR)/sitemap.c >$@
1308
+
1309
+$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h
1310
+ $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c
1311
+
1312
+$(OBJDIR)/sitemap.h: $(OBJDIR)/headers
13011313
13021314
$(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate
13031315
$(OBJDIR)/translate $(SRCDIR)/skins.c >$@
13041316
13051317
$(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
13061318
--- src/main.mk
+++ src/main.mk
@@ -99,10 +99,11 @@
99 $(SRCDIR)/schema.c \
100 $(SRCDIR)/search.c \
101 $(SRCDIR)/setup.c \
102 $(SRCDIR)/sha1.c \
103 $(SRCDIR)/shun.c \
 
104 $(SRCDIR)/skins.c \
105 $(SRCDIR)/sqlcmd.c \
106 $(SRCDIR)/stash.c \
107 $(SRCDIR)/stat.c \
108 $(SRCDIR)/style.c \
@@ -220,10 +221,11 @@
220 $(OBJDIR)/schema_.c \
221 $(OBJDIR)/search_.c \
222 $(OBJDIR)/setup_.c \
223 $(OBJDIR)/sha1_.c \
224 $(OBJDIR)/shun_.c \
 
225 $(OBJDIR)/skins_.c \
226 $(OBJDIR)/sqlcmd_.c \
227 $(OBJDIR)/stash_.c \
228 $(OBJDIR)/stat_.c \
229 $(OBJDIR)/style_.c \
@@ -338,10 +340,11 @@
338 $(OBJDIR)/schema.o \
339 $(OBJDIR)/search.o \
340 $(OBJDIR)/setup.o \
341 $(OBJDIR)/sha1.o \
342 $(OBJDIR)/shun.o \
 
343 $(OBJDIR)/skins.o \
344 $(OBJDIR)/sqlcmd.o \
345 $(OBJDIR)/stash.o \
346 $(OBJDIR)/stat.o \
347 $(OBJDIR)/style.o \
@@ -565,10 +568,11 @@
565 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
566 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
567 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
568 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
569 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
 
570 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
571 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
572 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
573 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
574 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1296,10 +1300,18 @@
1296
1297 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1298 $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
1299
1300 $(OBJDIR)/shun.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1301
1302 $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate
1303 $(OBJDIR)/translate $(SRCDIR)/skins.c >$@
1304
1305 $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
1306
--- src/main.mk
+++ src/main.mk
@@ -99,10 +99,11 @@
99 $(SRCDIR)/schema.c \
100 $(SRCDIR)/search.c \
101 $(SRCDIR)/setup.c \
102 $(SRCDIR)/sha1.c \
103 $(SRCDIR)/shun.c \
104 $(SRCDIR)/sitemap.c \
105 $(SRCDIR)/skins.c \
106 $(SRCDIR)/sqlcmd.c \
107 $(SRCDIR)/stash.c \
108 $(SRCDIR)/stat.c \
109 $(SRCDIR)/style.c \
@@ -220,10 +221,11 @@
221 $(OBJDIR)/schema_.c \
222 $(OBJDIR)/search_.c \
223 $(OBJDIR)/setup_.c \
224 $(OBJDIR)/sha1_.c \
225 $(OBJDIR)/shun_.c \
226 $(OBJDIR)/sitemap_.c \
227 $(OBJDIR)/skins_.c \
228 $(OBJDIR)/sqlcmd_.c \
229 $(OBJDIR)/stash_.c \
230 $(OBJDIR)/stat_.c \
231 $(OBJDIR)/style_.c \
@@ -338,10 +340,11 @@
340 $(OBJDIR)/schema.o \
341 $(OBJDIR)/search.o \
342 $(OBJDIR)/setup.o \
343 $(OBJDIR)/sha1.o \
344 $(OBJDIR)/shun.o \
345 $(OBJDIR)/sitemap.o \
346 $(OBJDIR)/skins.o \
347 $(OBJDIR)/sqlcmd.o \
348 $(OBJDIR)/stash.o \
349 $(OBJDIR)/stat.o \
350 $(OBJDIR)/style.o \
@@ -565,10 +568,11 @@
568 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
569 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
570 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
571 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
572 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
573 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
574 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
575 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
576 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
577 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
578 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1296,10 +1300,18 @@
1300
1301 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1302 $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
1303
1304 $(OBJDIR)/shun.h: $(OBJDIR)/headers
1305
1306 $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(OBJDIR)/translate
1307 $(OBJDIR)/translate $(SRCDIR)/sitemap.c >$@
1308
1309 $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h
1310 $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c
1311
1312 $(OBJDIR)/sitemap.h: $(OBJDIR)/headers
1313
1314 $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate
1315 $(OBJDIR)/translate $(SRCDIR)/skins.c >$@
1316
1317 $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
1318
+38 -7
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -105,10 +105,11 @@
105105
schema
106106
search
107107
setup
108108
sha1
109109
shun
110
+ sitemap
110111
skins
111112
sqlcmd
112113
stash
113114
stat
114115
style
@@ -513,11 +514,12 @@
513514
# This is useful when Tcl has been compiled statically with MinGW.
514515
#
515516
FOSSIL_TCL_SOURCE = 1
516517
517518
#### Check if the workaround for the MinGW command line handling needs to
518
-# be enabled by default.
519
+# be enabled by default. This check may be somewhat fragile due to the
520
+# use of "findstring".
519521
#
520522
ifndef MINGW_IS_32BIT_ONLY
521523
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
522524
MINGW_IS_32BIT_ONLY = 1
523525
endif
@@ -526,26 +528,46 @@
526528
#### The directories where the zlib include and library files are located.
527529
#
528530
ZINCDIR = $(SRCDIR)/../compat/zlib
529531
ZLIBDIR = $(SRCDIR)/../compat/zlib
530532
533
+#### Make an attempt to detect if Fossil is being built for the x64 processor
534
+# architecture. This check may be somewhat fragile due to "findstring".
535
+#
531536
ifndef X64
532537
ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
533538
X64 = 1
534539
endif
535540
endif
536541
542
+#### Determine if the optimized assembly routines provided with zlib should be
543
+# used, taking into account whether zlib is actually enabled and the target
544
+# processor architecture.
545
+#
537546
ifndef X64
538547
SSLCONFIG = mingw
548
+ifndef FOSSIL_ENABLE_MINIZ
539549
ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
540550
LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
551
+else
552
+ZLIBCONFIG =
553
+LIBTARGETS =
554
+endif
541555
else
542556
SSLCONFIG = mingw64
543
-ZLIBCONFIG =
557
+ZLIBCONFIG =
544558
LIBTARGETS =
545559
endif
546560
561
+#### Disable creation of the OpenSSL shared libraries. Also, disable support
562
+# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS).
563
+#
564
+SSLCONFIG += no-ssl2 no-ssl3 no-shared
565
+
566
+#### When using zlib, make sure that OpenSSL is configured to use the zlib
567
+# that Fossil knows about (i.e. the one within the source tree).
568
+#
547569
ifndef FOSSIL_ENABLE_MINIZ
548570
SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
549571
endif
550572
551573
#### The directories where the OpenSSL include and library files are located.
@@ -1290,23 +1312,32 @@
12901312
SSLLIBDIR = $(SSLDIR)\out32
12911313
SSLLFLAGS = /nologo /opt:ref /debug
12921314
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
12931315
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
12941316
!message Using 'x64' platform for OpenSSL...
1295
-SSLCONFIG = VC-WIN64A no-asm
1317
+# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
1318
+# SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared
1319
+SSLCONFIG = VC-WIN64A no-asm no-shared
12961320
SSLSETUP = ms\do_win64a.bat
12971321
SSLNMAKE = ms\nt.mak all
1322
+SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
12981323
!elseif "$(PLATFORM)"=="ia64"
12991324
!message Using 'ia64' platform for OpenSSL...
1300
-SSLCONFIG = VC-WIN64I no-asm
1325
+# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
1326
+# SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared
1327
+SSLCONFIG = VC-WIN64I no-asm no-shared
13011328
SSLSETUP = ms\do_win64i.bat
13021329
SSLNMAKE = ms\nt.mak all
1330
+SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
13031331
!else
13041332
!message Assuming 'x86' platform for OpenSSL...
1305
-SSLCONFIG = VC-WIN32 no-asm
1333
+# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
1334
+# SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared
1335
+SSLCONFIG = VC-WIN32 no-asm no-shared
13061336
SSLSETUP = ms\do_ms.bat
13071337
SSLNMAKE = ms\nt.mak all
1338
+SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
13081339
!endif
13091340
!endif
13101341
13111342
!ifdef FOSSIL_ENABLE_TCL
13121343
TCLDIR = $(B)\compat\tcl-8.6
@@ -1475,13 +1506,13 @@
14751506
@set PATH=$(PERLDIR);$(PATH)
14761507
!endif
14771508
@pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
14781509
@pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
14791510
!ifdef FOSSIL_ENABLE_WINXP
1480
- @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
1511
+ @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
14811512
!else
1482
- @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd
1513
+ @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd
14831514
!endif
14841515
!endif
14851516
14861517
!ifndef FOSSIL_ENABLE_MINIZ
14871518
APPTARGETS = $(APPTARGETS) zlib
14881519
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -105,10 +105,11 @@
105 schema
106 search
107 setup
108 sha1
109 shun
 
110 skins
111 sqlcmd
112 stash
113 stat
114 style
@@ -513,11 +514,12 @@
513 # This is useful when Tcl has been compiled statically with MinGW.
514 #
515 FOSSIL_TCL_SOURCE = 1
516
517 #### Check if the workaround for the MinGW command line handling needs to
518 # be enabled by default.
 
519 #
520 ifndef MINGW_IS_32BIT_ONLY
521 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
522 MINGW_IS_32BIT_ONLY = 1
523 endif
@@ -526,26 +528,46 @@
526 #### The directories where the zlib include and library files are located.
527 #
528 ZINCDIR = $(SRCDIR)/../compat/zlib
529 ZLIBDIR = $(SRCDIR)/../compat/zlib
530
 
 
 
531 ifndef X64
532 ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
533 X64 = 1
534 endif
535 endif
536
 
 
 
 
537 ifndef X64
538 SSLCONFIG = mingw
 
539 ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
540 LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
 
 
 
 
541 else
542 SSLCONFIG = mingw64
543 ZLIBCONFIG =
544 LIBTARGETS =
545 endif
546
 
 
 
 
 
 
 
 
547 ifndef FOSSIL_ENABLE_MINIZ
548 SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
549 endif
550
551 #### The directories where the OpenSSL include and library files are located.
@@ -1290,23 +1312,32 @@
1290 SSLLIBDIR = $(SSLDIR)\out32
1291 SSLLFLAGS = /nologo /opt:ref /debug
1292 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
1293 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
1294 !message Using 'x64' platform for OpenSSL...
1295 SSLCONFIG = VC-WIN64A no-asm
 
 
1296 SSLSETUP = ms\do_win64a.bat
1297 SSLNMAKE = ms\nt.mak all
 
1298 !elseif "$(PLATFORM)"=="ia64"
1299 !message Using 'ia64' platform for OpenSSL...
1300 SSLCONFIG = VC-WIN64I no-asm
 
 
1301 SSLSETUP = ms\do_win64i.bat
1302 SSLNMAKE = ms\nt.mak all
 
1303 !else
1304 !message Assuming 'x86' platform for OpenSSL...
1305 SSLCONFIG = VC-WIN32 no-asm
 
 
1306 SSLSETUP = ms\do_ms.bat
1307 SSLNMAKE = ms\nt.mak all
 
1308 !endif
1309 !endif
1310
1311 !ifdef FOSSIL_ENABLE_TCL
1312 TCLDIR = $(B)\compat\tcl-8.6
@@ -1475,13 +1506,13 @@
1475 @set PATH=$(PERLDIR);$(PATH)
1476 !endif
1477 @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
1478 @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
1479 !ifdef FOSSIL_ENABLE_WINXP
1480 @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
1481 !else
1482 @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd
1483 !endif
1484 !endif
1485
1486 !ifndef FOSSIL_ENABLE_MINIZ
1487 APPTARGETS = $(APPTARGETS) zlib
1488
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -105,10 +105,11 @@
105 schema
106 search
107 setup
108 sha1
109 shun
110 sitemap
111 skins
112 sqlcmd
113 stash
114 stat
115 style
@@ -513,11 +514,12 @@
514 # This is useful when Tcl has been compiled statically with MinGW.
515 #
516 FOSSIL_TCL_SOURCE = 1
517
518 #### Check if the workaround for the MinGW command line handling needs to
519 # be enabled by default. This check may be somewhat fragile due to the
520 # use of "findstring".
521 #
522 ifndef MINGW_IS_32BIT_ONLY
523 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
524 MINGW_IS_32BIT_ONLY = 1
525 endif
@@ -526,26 +528,46 @@
528 #### The directories where the zlib include and library files are located.
529 #
530 ZINCDIR = $(SRCDIR)/../compat/zlib
531 ZLIBDIR = $(SRCDIR)/../compat/zlib
532
533 #### Make an attempt to detect if Fossil is being built for the x64 processor
534 # architecture. This check may be somewhat fragile due to "findstring".
535 #
536 ifndef X64
537 ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
538 X64 = 1
539 endif
540 endif
541
542 #### Determine if the optimized assembly routines provided with zlib should be
543 # used, taking into account whether zlib is actually enabled and the target
544 # processor architecture.
545 #
546 ifndef X64
547 SSLCONFIG = mingw
548 ifndef FOSSIL_ENABLE_MINIZ
549 ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
550 LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
551 else
552 ZLIBCONFIG =
553 LIBTARGETS =
554 endif
555 else
556 SSLCONFIG = mingw64
557 ZLIBCONFIG =
558 LIBTARGETS =
559 endif
560
561 #### Disable creation of the OpenSSL shared libraries. Also, disable support
562 # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS).
563 #
564 SSLCONFIG += no-ssl2 no-ssl3 no-shared
565
566 #### When using zlib, make sure that OpenSSL is configured to use the zlib
567 # that Fossil knows about (i.e. the one within the source tree).
568 #
569 ifndef FOSSIL_ENABLE_MINIZ
570 SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
571 endif
572
573 #### The directories where the OpenSSL include and library files are located.
@@ -1290,23 +1312,32 @@
1312 SSLLIBDIR = $(SSLDIR)\out32
1313 SSLLFLAGS = /nologo /opt:ref /debug
1314 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
1315 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
1316 !message Using 'x64' platform for OpenSSL...
1317 # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
1318 # SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared
1319 SSLCONFIG = VC-WIN64A no-asm no-shared
1320 SSLSETUP = ms\do_win64a.bat
1321 SSLNMAKE = ms\nt.mak all
1322 SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
1323 !elseif "$(PLATFORM)"=="ia64"
1324 !message Using 'ia64' platform for OpenSSL...
1325 # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
1326 # SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared
1327 SSLCONFIG = VC-WIN64I no-asm no-shared
1328 SSLSETUP = ms\do_win64i.bat
1329 SSLNMAKE = ms\nt.mak all
1330 SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
1331 !else
1332 !message Assuming 'x86' platform for OpenSSL...
1333 # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
1334 # SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared
1335 SSLCONFIG = VC-WIN32 no-asm no-shared
1336 SSLSETUP = ms\do_ms.bat
1337 SSLNMAKE = ms\nt.mak all
1338 SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
1339 !endif
1340 !endif
1341
1342 !ifdef FOSSIL_ENABLE_TCL
1343 TCLDIR = $(B)\compat\tcl-8.6
@@ -1475,13 +1506,13 @@
1506 @set PATH=$(PERLDIR);$(PATH)
1507 !endif
1508 @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
1509 @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
1510 !ifdef FOSSIL_ENABLE_WINXP
1511 @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
1512 !else
1513 @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd
1514 !endif
1515 !endif
1516
1517 !ifndef FOSSIL_ENABLE_MINIZ
1518 APPTARGETS = $(APPTARGETS) zlib
1519
+1 -1
--- src/markdown.c
+++ src/markdown.c
@@ -2155,11 +2155,11 @@
21552155
struct Blob *ib, /* input blob in markdown */
21562156
const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */
21572157
){
21582158
struct link_ref *lr;
21592159
struct Blob text = BLOB_INITIALIZER;
2160
- size_t i, beg, end;
2160
+ size_t i, beg, end = 0;
21612161
struct render rndr;
21622162
char *ib_data;
21632163
21642164
/* filling the render structure */
21652165
if( !rndrer ) return;
21662166
--- src/markdown.c
+++ src/markdown.c
@@ -2155,11 +2155,11 @@
2155 struct Blob *ib, /* input blob in markdown */
2156 const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */
2157 ){
2158 struct link_ref *lr;
2159 struct Blob text = BLOB_INITIALIZER;
2160 size_t i, beg, end;
2161 struct render rndr;
2162 char *ib_data;
2163
2164 /* filling the render structure */
2165 if( !rndrer ) return;
2166
--- src/markdown.c
+++ src/markdown.c
@@ -2155,11 +2155,11 @@
2155 struct Blob *ib, /* input blob in markdown */
2156 const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */
2157 ){
2158 struct link_ref *lr;
2159 struct Blob text = BLOB_INITIALIZER;
2160 size_t i, beg, end = 0;
2161 struct render rndr;
2162 char *ib_data;
2163
2164 /* filling the render structure */
2165 if( !rndrer ) return;
2166
+1 -6
--- src/moderate.c
+++ src/moderate.c
@@ -38,16 +38,11 @@
3838
3939
/*
4040
** Return TRUE if the modreq table exists
4141
*/
4242
int moderation_table_exists(void){
43
- static int modreqExists = -1;
44
- if( modreqExists<0 ){
45
- modreqExists = db_exists("SELECT 1 FROM %s.sqlite_master"
46
- " WHERE name='modreq'", db_name("repository"));
47
- }
48
- return modreqExists;
43
+ return db_table_exists("repository", "modreq");
4944
}
5045
5146
/*
5247
** Return TRUE if the object specified is being held for moderation.
5348
*/
5449
--- src/moderate.c
+++ src/moderate.c
@@ -38,16 +38,11 @@
38
39 /*
40 ** Return TRUE if the modreq table exists
41 */
42 int moderation_table_exists(void){
43 static int modreqExists = -1;
44 if( modreqExists<0 ){
45 modreqExists = db_exists("SELECT 1 FROM %s.sqlite_master"
46 " WHERE name='modreq'", db_name("repository"));
47 }
48 return modreqExists;
49 }
50
51 /*
52 ** Return TRUE if the object specified is being held for moderation.
53 */
54
--- src/moderate.c
+++ src/moderate.c
@@ -38,16 +38,11 @@
38
39 /*
40 ** Return TRUE if the modreq table exists
41 */
42 int moderation_table_exists(void){
43 return db_table_exists("repository", "modreq");
 
 
 
 
 
44 }
45
46 /*
47 ** Return TRUE if the object specified is being held for moderation.
48 */
49
+100 -29
--- src/name.c
+++ src/name.c
@@ -346,30 +346,25 @@
346346
** name_collisions searches through events, blobs, and tickets for
347347
** collisions of a given UUID based on its length on UUIDs no shorter
348348
** than 4 characters in length.
349349
*/
350350
int name_collisions(const char *zName){
351
- Stmt q;
352351
int c = 0; /* count of collisions for zName */
353352
int nLen; /* length of zName */
354353
nLen = strlen(zName);
355354
if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){
356
- db_prepare(&q,
357
- "SELECT count(uuid) FROM"
358
- " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket"
359
- " UNION ALL SELECT * FROM"
360
- " (SELECT substr(tagname, 7, %d) FROM"
361
- " tag WHERE tagname GLOB 'event-*')"
362
- " UNION ALL SELECT * FROM"
363
- " (SELECT substr(uuid, 1, %d) FROM blob))"
364
- " WHERE uuid GLOB '%q*'"
365
- " GROUP BY uuid HAVING count(uuid) > 1;",
366
- nLen, nLen, nLen, zName);
367
- if( db_step(&q)==SQLITE_ROW ){
368
- c = db_column_int(&q, 0);
369
- }
370
- db_finalize(&q);
355
+ c = db_int(0,
356
+ "SELECT"
357
+ " (SELECT count(*) FROM ticket"
358
+ " WHERE tkt_uuid GLOB '%q*') +"
359
+ " (SELECT count(*) FROM tag"
360
+ " WHERE tagname GLOB 'event-%q*') +"
361
+ " (SELECT count(*) FROM blob"
362
+ " WHERE uuid GLOB '%q*');",
363
+ zName, zName, zName
364
+ );
365
+ if( c<2 ) c = 0;
371366
}
372367
return c;
373368
}
374369
375370
/*
@@ -808,21 +803,21 @@
808803
db_multi_exec(
809804
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
810805
"SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n"
811806
" 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n"
812807
" FROM event, blob\n"
813
- " WHERE event.objid %s AND event.type='ci'\n"
808
+ " WHERE (event.objid %s) AND event.type='ci'\n"
814809
" AND event.objid=blob.rid;",
815810
zWhere /*safe-for-%s*/
816811
);
817812
818813
/* Describe files */
819814
db_multi_exec(
820815
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
821816
"SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n"
822817
" FROM mlink, blob, event, filename\n"
823
- " WHERE mlink.fid %s\n"
818
+ " WHERE (mlink.fid %s)\n"
824819
" AND mlink.mid=event.objid\n"
825820
" AND filename.fnid=mlink.fnid\n"
826821
" AND mlink.fid=blob.rid;",
827822
zWhere /*safe-for-%s*/
828823
);
@@ -831,21 +826,21 @@
831826
db_multi_exec(
832827
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
833828
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n"
834829
" 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n"
835830
" FROM tagxref, blob\n"
836
- " WHERE tagxref.srcid %s AND tagxref.srcid!=tagxref.rid\n"
831
+ " WHERE (tagxref.srcid %s) AND tagxref.srcid!=tagxref.rid\n"
837832
" AND tagxref.srcid=blob.rid;",
838833
zWhere /*safe-for-%s*/
839834
);
840835
841836
/* Cluster artifacts */
842837
db_multi_exec(
843838
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
844839
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n"
845840
" FROM tagxref, blob\n"
846
- " WHERE tagxref.rid %s\n"
841
+ " WHERE (tagxref.rid %s)\n"
847842
" AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n"
848843
" AND blob.rid=tagxref.rid;",
849844
zWhere /*safe-for-%s*/
850845
);
851846
@@ -853,11 +848,11 @@
853848
db_multi_exec(
854849
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
855850
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n"
856851
" 'ticket '||substr(tag.tagname,5,21)\n"
857852
" FROM tagxref, tag, blob\n"
858
- " WHERE tagxref.rid %s\n"
853
+ " WHERE (tagxref.rid %s)\n"
859854
" AND tag.tagid=tagxref.tagid\n"
860855
" AND tag.tagname GLOB 'tkt-*'"
861856
" AND blob.rid=tagxref.rid;",
862857
zWhere /*safe-for-%s*/
863858
);
@@ -866,11 +861,11 @@
866861
db_multi_exec(
867862
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
868863
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n"
869864
" printf('wiki \"%%s\"',substr(tag.tagname,6))\n"
870865
" FROM tagxref, tag, blob\n"
871
- " WHERE tagxref.rid %s\n"
866
+ " WHERE (tagxref.rid %s)\n"
872867
" AND tag.tagid=tagxref.tagid\n"
873868
" AND tag.tagname GLOB 'wiki-*'"
874869
" AND blob.rid=tagxref.rid;",
875870
zWhere /*safe-for-%s*/
876871
);
@@ -879,35 +874,45 @@
879874
db_multi_exec(
880875
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
881876
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n"
882877
" 'event '||substr(tag.tagname,7)\n"
883878
" FROM tagxref, tag, blob\n"
884
- " WHERE tagxref.rid %s\n"
879
+ " WHERE (tagxref.rid %s)\n"
885880
" AND tag.tagid=tagxref.tagid\n"
886881
" AND tag.tagname GLOB 'event-*'"
887882
" AND blob.rid=tagxref.rid;",
888883
zWhere /*safe-for-%s*/
889884
);
890885
891886
/* Attachments */
892887
db_multi_exec(
893
- "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,detail)\n"
888
+ "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
889
+ "SELECT blob.rid, blob.uuid, attachment.mtime, 'attach-control',\n"
890
+ " 'attachment-control for '||attachment.filename\n"
891
+ " FROM attachment, blob\n"
892
+ " WHERE (attachment.attachid %s)\n"
893
+ " AND blob.rid=attachment.attachid",
894
+ zWhere /*safe-for-%s*/
895
+ );
896
+ db_multi_exec(
897
+ "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
894898
"SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n"
895899
" 'attachment '||attachment.filename\n"
896900
" FROM attachment, blob\n"
897
- " WHERE attachment.src %s\n"
898
- " AND blob.rid=attachment.src;",
901
+ " WHERE (blob.rid %s)\n"
902
+ " AND blob.rid NOT IN (SELECT rid FROM description)\n"
903
+ " AND blob.uuid=attachment.src",
899904
zWhere /*safe-for-%s*/
900905
);
901906
902907
/* Everything else */
903908
db_multi_exec(
904909
"INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n"
905910
"SELECT blob.rid, blob.uuid,"
906911
" CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n"
907912
" 'unknown'\n"
908
- " FROM blob WHERE blob.rid %s;",
913
+ " FROM blob WHERE (blob.rid %s);",
909914
zWhere /*safe-for-%s*/
910915
);
911916
912917
/* Mark private elements */
913918
db_multi_exec(
@@ -943,17 +948,83 @@
943948
}
944949
945950
/*
946951
** COMMAND: test-describe-artifacts
947952
**
948
-** Usage: %fossil test-describe-artifacts
953
+** Usage: %fossil test-describe-artifacts [--from S] [--count N]
949954
**
950955
** Display a one-line description of every artifact.
951956
*/
952957
void test_describe_artifacts_cmd(void){
958
+ int iFrom = 0;
959
+ int iCnt = 1000000;
960
+ const char *z;
961
+ char *zRange;
953962
db_find_and_open_repository(0,0);
954
- describe_artifacts_to_stdout("IN (SELECT rid FROM blob)", 0);
963
+ z = find_option("from",0,1);
964
+ if( z ) iFrom = atoi(z);
965
+ z = find_option("count",0,1);
966
+ if( z ) iCnt = atoi(z);
967
+ zRange = mprintf("BETWEEN %d AND %d", iFrom, iFrom+iCnt-1);
968
+ describe_artifacts_to_stdout(zRange, 0);
969
+}
970
+
971
+/*
972
+** WEBPAGE: bloblist
973
+**
974
+** Return a page showing all artifacts in the repository. Query parameters:
975
+**
976
+** n=N Show N artifacts
977
+** s=S Start with artifact number S
978
+*/
979
+void bloblist_page(void){
980
+ Stmt q;
981
+ int s = atoi(PD("s","0"));
982
+ int n = atoi(PD("n","5000"));
983
+ int mx = db_int(0, "SELECT max(rid) FROM blob");
984
+ char *zRange;
985
+
986
+ login_check_credentials();
987
+ if( !g.perm.Read ){ login_needed(); return; }
988
+ style_header("List Of Artifacts");
989
+ if( mx>n && P("s")==0 ){
990
+ int i;
991
+ @ <p>Select a range of artifacts to view:</p>
992
+ @ <ul>
993
+ for(i=1; i<=mx; i+=n){
994
+ @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n))
995
+ @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a>
996
+ }
997
+ @ </ul>
998
+ style_footer();
999
+ return;
1000
+ }
1001
+ if( mx>n ){
1002
+ style_submenu_element("Index", "Index", "bloblist");
1003
+ }
1004
+ zRange = mprintf("BETWEEN %d AND %d", s, s+n-1);
1005
+ describe_artifacts(zRange);
1006
+ db_prepare(&q,
1007
+ "SELECT rid, uuid, summary, isPrivate FROM description ORDER BY rid"
1008
+ );
1009
+ @ <table cellpadding="0" cellspacing="0">
1010
+ while( db_step(&q)==SQLITE_ROW ){
1011
+ int rid = db_column_int(&q,0);
1012
+ const char *zUuid = db_column_text(&q, 1);
1013
+ const char *zDesc = db_column_text(&q, 2);
1014
+ int isPriv = db_column_int(&q,2);
1015
+ @ <tr><td align="right">%d(rid)</td>
1016
+ @ <td>&nbsp;%z(href("%R/info/%s",zUuid))%s(zUuid)</a>&nbsp;</td>
1017
+ @ <td align="left">%h(zDesc)</td>
1018
+ if( isPriv ){
1019
+ @ <td>(unpublished)</td>
1020
+ }
1021
+ @ </tr>
1022
+ }
1023
+ @ </table>
1024
+ db_finalize(&q);
1025
+ style_footer();
9551026
}
9561027
9571028
/*
9581029
** COMMAND: test-unsent
9591030
**
9601031
--- src/name.c
+++ src/name.c
@@ -346,30 +346,25 @@
346 ** name_collisions searches through events, blobs, and tickets for
347 ** collisions of a given UUID based on its length on UUIDs no shorter
348 ** than 4 characters in length.
349 */
350 int name_collisions(const char *zName){
351 Stmt q;
352 int c = 0; /* count of collisions for zName */
353 int nLen; /* length of zName */
354 nLen = strlen(zName);
355 if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){
356 db_prepare(&q,
357 "SELECT count(uuid) FROM"
358 " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket"
359 " UNION ALL SELECT * FROM"
360 " (SELECT substr(tagname, 7, %d) FROM"
361 " tag WHERE tagname GLOB 'event-*')"
362 " UNION ALL SELECT * FROM"
363 " (SELECT substr(uuid, 1, %d) FROM blob))"
364 " WHERE uuid GLOB '%q*'"
365 " GROUP BY uuid HAVING count(uuid) > 1;",
366 nLen, nLen, nLen, zName);
367 if( db_step(&q)==SQLITE_ROW ){
368 c = db_column_int(&q, 0);
369 }
370 db_finalize(&q);
371 }
372 return c;
373 }
374
375 /*
@@ -808,21 +803,21 @@
808 db_multi_exec(
809 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
810 "SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n"
811 " 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n"
812 " FROM event, blob\n"
813 " WHERE event.objid %s AND event.type='ci'\n"
814 " AND event.objid=blob.rid;",
815 zWhere /*safe-for-%s*/
816 );
817
818 /* Describe files */
819 db_multi_exec(
820 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
821 "SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n"
822 " FROM mlink, blob, event, filename\n"
823 " WHERE mlink.fid %s\n"
824 " AND mlink.mid=event.objid\n"
825 " AND filename.fnid=mlink.fnid\n"
826 " AND mlink.fid=blob.rid;",
827 zWhere /*safe-for-%s*/
828 );
@@ -831,21 +826,21 @@
831 db_multi_exec(
832 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
833 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n"
834 " 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n"
835 " FROM tagxref, blob\n"
836 " WHERE tagxref.srcid %s AND tagxref.srcid!=tagxref.rid\n"
837 " AND tagxref.srcid=blob.rid;",
838 zWhere /*safe-for-%s*/
839 );
840
841 /* Cluster artifacts */
842 db_multi_exec(
843 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
844 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n"
845 " FROM tagxref, blob\n"
846 " WHERE tagxref.rid %s\n"
847 " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n"
848 " AND blob.rid=tagxref.rid;",
849 zWhere /*safe-for-%s*/
850 );
851
@@ -853,11 +848,11 @@
853 db_multi_exec(
854 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
855 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n"
856 " 'ticket '||substr(tag.tagname,5,21)\n"
857 " FROM tagxref, tag, blob\n"
858 " WHERE tagxref.rid %s\n"
859 " AND tag.tagid=tagxref.tagid\n"
860 " AND tag.tagname GLOB 'tkt-*'"
861 " AND blob.rid=tagxref.rid;",
862 zWhere /*safe-for-%s*/
863 );
@@ -866,11 +861,11 @@
866 db_multi_exec(
867 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
868 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n"
869 " printf('wiki \"%%s\"',substr(tag.tagname,6))\n"
870 " FROM tagxref, tag, blob\n"
871 " WHERE tagxref.rid %s\n"
872 " AND tag.tagid=tagxref.tagid\n"
873 " AND tag.tagname GLOB 'wiki-*'"
874 " AND blob.rid=tagxref.rid;",
875 zWhere /*safe-for-%s*/
876 );
@@ -879,35 +874,45 @@
879 db_multi_exec(
880 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
881 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n"
882 " 'event '||substr(tag.tagname,7)\n"
883 " FROM tagxref, tag, blob\n"
884 " WHERE tagxref.rid %s\n"
885 " AND tag.tagid=tagxref.tagid\n"
886 " AND tag.tagname GLOB 'event-*'"
887 " AND blob.rid=tagxref.rid;",
888 zWhere /*safe-for-%s*/
889 );
890
891 /* Attachments */
892 db_multi_exec(
893 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,detail)\n"
 
 
 
 
 
 
 
 
 
894 "SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n"
895 " 'attachment '||attachment.filename\n"
896 " FROM attachment, blob\n"
897 " WHERE attachment.src %s\n"
898 " AND blob.rid=attachment.src;",
 
899 zWhere /*safe-for-%s*/
900 );
901
902 /* Everything else */
903 db_multi_exec(
904 "INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n"
905 "SELECT blob.rid, blob.uuid,"
906 " CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n"
907 " 'unknown'\n"
908 " FROM blob WHERE blob.rid %s;",
909 zWhere /*safe-for-%s*/
910 );
911
912 /* Mark private elements */
913 db_multi_exec(
@@ -943,17 +948,83 @@
943 }
944
945 /*
946 ** COMMAND: test-describe-artifacts
947 **
948 ** Usage: %fossil test-describe-artifacts
949 **
950 ** Display a one-line description of every artifact.
951 */
952 void test_describe_artifacts_cmd(void){
 
 
 
 
953 db_find_and_open_repository(0,0);
954 describe_artifacts_to_stdout("IN (SELECT rid FROM blob)", 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
955 }
956
957 /*
958 ** COMMAND: test-unsent
959 **
960
--- src/name.c
+++ src/name.c
@@ -346,30 +346,25 @@
346 ** name_collisions searches through events, blobs, and tickets for
347 ** collisions of a given UUID based on its length on UUIDs no shorter
348 ** than 4 characters in length.
349 */
350 int name_collisions(const char *zName){
 
351 int c = 0; /* count of collisions for zName */
352 int nLen; /* length of zName */
353 nLen = strlen(zName);
354 if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){
355 c = db_int(0,
356 "SELECT"
357 " (SELECT count(*) FROM ticket"
358 " WHERE tkt_uuid GLOB '%q*') +"
359 " (SELECT count(*) FROM tag"
360 " WHERE tagname GLOB 'event-%q*') +"
361 " (SELECT count(*) FROM blob"
362 " WHERE uuid GLOB '%q*');",
363 zName, zName, zName
364 );
365 if( c<2 ) c = 0;
 
 
 
 
366 }
367 return c;
368 }
369
370 /*
@@ -808,21 +803,21 @@
803 db_multi_exec(
804 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
805 "SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n"
806 " 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n"
807 " FROM event, blob\n"
808 " WHERE (event.objid %s) AND event.type='ci'\n"
809 " AND event.objid=blob.rid;",
810 zWhere /*safe-for-%s*/
811 );
812
813 /* Describe files */
814 db_multi_exec(
815 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
816 "SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n"
817 " FROM mlink, blob, event, filename\n"
818 " WHERE (mlink.fid %s)\n"
819 " AND mlink.mid=event.objid\n"
820 " AND filename.fnid=mlink.fnid\n"
821 " AND mlink.fid=blob.rid;",
822 zWhere /*safe-for-%s*/
823 );
@@ -831,21 +826,21 @@
826 db_multi_exec(
827 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
828 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n"
829 " 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n"
830 " FROM tagxref, blob\n"
831 " WHERE (tagxref.srcid %s) AND tagxref.srcid!=tagxref.rid\n"
832 " AND tagxref.srcid=blob.rid;",
833 zWhere /*safe-for-%s*/
834 );
835
836 /* Cluster artifacts */
837 db_multi_exec(
838 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
839 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n"
840 " FROM tagxref, blob\n"
841 " WHERE (tagxref.rid %s)\n"
842 " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n"
843 " AND blob.rid=tagxref.rid;",
844 zWhere /*safe-for-%s*/
845 );
846
@@ -853,11 +848,11 @@
848 db_multi_exec(
849 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
850 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n"
851 " 'ticket '||substr(tag.tagname,5,21)\n"
852 " FROM tagxref, tag, blob\n"
853 " WHERE (tagxref.rid %s)\n"
854 " AND tag.tagid=tagxref.tagid\n"
855 " AND tag.tagname GLOB 'tkt-*'"
856 " AND blob.rid=tagxref.rid;",
857 zWhere /*safe-for-%s*/
858 );
@@ -866,11 +861,11 @@
861 db_multi_exec(
862 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
863 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n"
864 " printf('wiki \"%%s\"',substr(tag.tagname,6))\n"
865 " FROM tagxref, tag, blob\n"
866 " WHERE (tagxref.rid %s)\n"
867 " AND tag.tagid=tagxref.tagid\n"
868 " AND tag.tagname GLOB 'wiki-*'"
869 " AND blob.rid=tagxref.rid;",
870 zWhere /*safe-for-%s*/
871 );
@@ -879,35 +874,45 @@
874 db_multi_exec(
875 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
876 "SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n"
877 " 'event '||substr(tag.tagname,7)\n"
878 " FROM tagxref, tag, blob\n"
879 " WHERE (tagxref.rid %s)\n"
880 " AND tag.tagid=tagxref.tagid\n"
881 " AND tag.tagname GLOB 'event-*'"
882 " AND blob.rid=tagxref.rid;",
883 zWhere /*safe-for-%s*/
884 );
885
886 /* Attachments */
887 db_multi_exec(
888 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
889 "SELECT blob.rid, blob.uuid, attachment.mtime, 'attach-control',\n"
890 " 'attachment-control for '||attachment.filename\n"
891 " FROM attachment, blob\n"
892 " WHERE (attachment.attachid %s)\n"
893 " AND blob.rid=attachment.attachid",
894 zWhere /*safe-for-%s*/
895 );
896 db_multi_exec(
897 "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
898 "SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n"
899 " 'attachment '||attachment.filename\n"
900 " FROM attachment, blob\n"
901 " WHERE (blob.rid %s)\n"
902 " AND blob.rid NOT IN (SELECT rid FROM description)\n"
903 " AND blob.uuid=attachment.src",
904 zWhere /*safe-for-%s*/
905 );
906
907 /* Everything else */
908 db_multi_exec(
909 "INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n"
910 "SELECT blob.rid, blob.uuid,"
911 " CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n"
912 " 'unknown'\n"
913 " FROM blob WHERE (blob.rid %s);",
914 zWhere /*safe-for-%s*/
915 );
916
917 /* Mark private elements */
918 db_multi_exec(
@@ -943,17 +948,83 @@
948 }
949
950 /*
951 ** COMMAND: test-describe-artifacts
952 **
953 ** Usage: %fossil test-describe-artifacts [--from S] [--count N]
954 **
955 ** Display a one-line description of every artifact.
956 */
957 void test_describe_artifacts_cmd(void){
958 int iFrom = 0;
959 int iCnt = 1000000;
960 const char *z;
961 char *zRange;
962 db_find_and_open_repository(0,0);
963 z = find_option("from",0,1);
964 if( z ) iFrom = atoi(z);
965 z = find_option("count",0,1);
966 if( z ) iCnt = atoi(z);
967 zRange = mprintf("BETWEEN %d AND %d", iFrom, iFrom+iCnt-1);
968 describe_artifacts_to_stdout(zRange, 0);
969 }
970
971 /*
972 ** WEBPAGE: bloblist
973 **
974 ** Return a page showing all artifacts in the repository. Query parameters:
975 **
976 ** n=N Show N artifacts
977 ** s=S Start with artifact number S
978 */
979 void bloblist_page(void){
980 Stmt q;
981 int s = atoi(PD("s","0"));
982 int n = atoi(PD("n","5000"));
983 int mx = db_int(0, "SELECT max(rid) FROM blob");
984 char *zRange;
985
986 login_check_credentials();
987 if( !g.perm.Read ){ login_needed(); return; }
988 style_header("List Of Artifacts");
989 if( mx>n && P("s")==0 ){
990 int i;
991 @ <p>Select a range of artifacts to view:</p>
992 @ <ul>
993 for(i=1; i<=mx; i+=n){
994 @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n))
995 @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a>
996 }
997 @ </ul>
998 style_footer();
999 return;
1000 }
1001 if( mx>n ){
1002 style_submenu_element("Index", "Index", "bloblist");
1003 }
1004 zRange = mprintf("BETWEEN %d AND %d", s, s+n-1);
1005 describe_artifacts(zRange);
1006 db_prepare(&q,
1007 "SELECT rid, uuid, summary, isPrivate FROM description ORDER BY rid"
1008 );
1009 @ <table cellpadding="0" cellspacing="0">
1010 while( db_step(&q)==SQLITE_ROW ){
1011 int rid = db_column_int(&q,0);
1012 const char *zUuid = db_column_text(&q, 1);
1013 const char *zDesc = db_column_text(&q, 2);
1014 int isPriv = db_column_int(&q,2);
1015 @ <tr><td align="right">%d(rid)</td>
1016 @ <td>&nbsp;%z(href("%R/info/%s",zUuid))%s(zUuid)</a>&nbsp;</td>
1017 @ <td align="left">%h(zDesc)</td>
1018 if( isPriv ){
1019 @ <td>(unpublished)</td>
1020 }
1021 @ </tr>
1022 }
1023 @ </table>
1024 db_finalize(&q);
1025 style_footer();
1026 }
1027
1028 /*
1029 ** COMMAND: test-unsent
1030 **
1031
+2 -3
--- src/purge.c
+++ src/purge.c
@@ -205,12 +205,11 @@
205205
** are about to be deleted or otherwise made inaccessible. This routine
206206
** is checking to ensure that purging the checkins in zTab will not delete
207207
** a baseline manifest out from under a delta.
208208
*/
209209
int purge_baseline_out_from_under_delta(const char *zTab){
210
- if( !db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='plink'"
211
- " AND sql GLOB '* baseid *'", db_name("repository")) ){
210
+ if( !db_table_has_column("repository","plink","baseid") ){
212211
/* Skip this check if the current database is an older schema that
213212
** does not contain the PLINK.BASEID field. */
214213
return 0;
215214
}else{
216215
return db_int(0,
@@ -492,11 +491,11 @@
492491
}
493492
/* The "checkins" subcommand goes here in alphabetical order, but it must
494493
** be moved to the end since it is the default case */
495494
}else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){
496495
int showDetail = find_option("l","l",0)!=0;
497
- if( db_int(-1,"PRAGMA table_info('purgeevent')")<0 ) return;
496
+ if( !db_table_exists("repository","purgeevent") ) return;
498497
db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')"
499498
" FROM purgeevent");
500499
while( db_step(&q)==SQLITE_ROW ){
501500
fossil_print("%4d on %s\n", db_column_int(&q,0), db_column_text(&q,1));
502501
if( showDetail ){
503502
--- src/purge.c
+++ src/purge.c
@@ -205,12 +205,11 @@
205 ** are about to be deleted or otherwise made inaccessible. This routine
206 ** is checking to ensure that purging the checkins in zTab will not delete
207 ** a baseline manifest out from under a delta.
208 */
209 int purge_baseline_out_from_under_delta(const char *zTab){
210 if( !db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='plink'"
211 " AND sql GLOB '* baseid *'", db_name("repository")) ){
212 /* Skip this check if the current database is an older schema that
213 ** does not contain the PLINK.BASEID field. */
214 return 0;
215 }else{
216 return db_int(0,
@@ -492,11 +491,11 @@
492 }
493 /* The "checkins" subcommand goes here in alphabetical order, but it must
494 ** be moved to the end since it is the default case */
495 }else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){
496 int showDetail = find_option("l","l",0)!=0;
497 if( db_int(-1,"PRAGMA table_info('purgeevent')")<0 ) return;
498 db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')"
499 " FROM purgeevent");
500 while( db_step(&q)==SQLITE_ROW ){
501 fossil_print("%4d on %s\n", db_column_int(&q,0), db_column_text(&q,1));
502 if( showDetail ){
503
--- src/purge.c
+++ src/purge.c
@@ -205,12 +205,11 @@
205 ** are about to be deleted or otherwise made inaccessible. This routine
206 ** is checking to ensure that purging the checkins in zTab will not delete
207 ** a baseline manifest out from under a delta.
208 */
209 int purge_baseline_out_from_under_delta(const char *zTab){
210 if( !db_table_has_column("repository","plink","baseid") ){
 
211 /* Skip this check if the current database is an older schema that
212 ** does not contain the PLINK.BASEID field. */
213 return 0;
214 }else{
215 return db_int(0,
@@ -492,11 +491,11 @@
491 }
492 /* The "checkins" subcommand goes here in alphabetical order, but it must
493 ** be moved to the end since it is the default case */
494 }else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){
495 int showDetail = find_option("l","l",0)!=0;
496 if( !db_table_exists("repository","purgeevent") ) return;
497 db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')"
498 " FROM purgeevent");
499 while( db_step(&q)==SQLITE_ROW ){
500 fossil_print("%4d on %s\n", db_column_int(&q,0), db_column_text(&q,1));
501 if( showDetail ){
502
+77 -21
--- src/report.c
+++ src/report.c
@@ -922,42 +922,85 @@
922922
923923
/*
924924
** Output Javascript code that will enables sorting of the table with
925925
** the id zTableId by clicking.
926926
**
927
-** The javascript is derived from:
927
+** The javascript was originally derived from:
928928
**
929929
** http://www.webtoolkit.info/sortable-html-table.html
930
+**
931
+** But there have been extensive modifications.
930932
**
931933
** This variation allows column types to be expressed using the second
932934
** argument. Each character of the second argument represent a column.
933
-** "t" means sort as text. "n" means sort numerically. "x" means do not
934
-** sort on this column. If there are fewer characters in zColumnTypes[] than
935
-** their are columns, the all extra columns assume type "t" (text).
935
+**
936
+** t Sort by text
937
+** n Sort numerically
938
+** k Sort by the data-sortkey property
939
+** x This column is not sortable
940
+**
941
+** If there are fewer characters in zColumnTypes[] than their are columns,
942
+** the all extra columns assume type "t" (text).
943
+**
944
+** The third parameter is the column that was initially sorted (using 1-based
945
+** column numbers, like SQL). Make this value 0 if none of the columns are
946
+** initially sorted. Make the value negative if the column is initially sorted
947
+** in reverse order.
948
+**
949
+** Clicking on the same column header twice in a row inverts the sort.
936950
*/
937
-void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){
951
+void output_table_sorting_javascript(
952
+ const char *zTableId, /* ID of table to sort */
953
+ const char *zColumnTypes, /* String for column types */
954
+ int iInitSort /* Initially sorted column. Leftmost is 1. 0 for NONE */
955
+){
938956
@ <script>
939
- @ function SortableTable(tableEl,columnTypes){
957
+ @ function SortableTable(tableEl,columnTypes,initSort){
940958
@ this.tbody = tableEl.getElementsByTagName('tbody');
959
+ @ this.columnTypes = columnTypes;
941960
@ this.sort = function (cell) {
942961
@ var column = cell.cellIndex;
943
- @ var sortFn = cell.sortType=="n" ? this.sortNumeric : this.sortText;
962
+ @ var sortFn;
963
+ @ switch( cell.sortType ){
964
+ @ case "n": sortFn = this.sortNumeric; break;
965
+ @ case "t": sortFn = this.sortText; break;
966
+ @ case "k": sortFn = this.sortKey; break;
967
+ @ case "x": return;
968
+ @ }
944969
@ this.sortIndex = column;
945970
@ var newRows = new Array();
946971
@ for (j = 0; j < this.tbody[0].rows.length; j++) {
947972
@ newRows[j] = this.tbody[0].rows[j];
948973
@ }
949
- @ newRows.sort(sortFn);
950
- @ if (cell.getAttribute("sortdir") == 'down') {
951
- @ newRows.reverse();
952
- @ cell.setAttribute('sortdir','up');
953
- @ } else {
954
- @ cell.setAttribute('sortdir','down');
974
+ @ if( this.sortIndex==Math.abs(this.prevColumn)-1 ){
975
+ @ newRows.reverse();
976
+ @ this.prevColumn = -this.prevColumn;
977
+ @ }else{
978
+ @ newRows.sort(sortFn);
979
+ @ this.prevColumn = this.sortIndex+1;
955980
@ }
956981
@ for (i=0;i<newRows.length;i++) {
957982
@ this.tbody[0].appendChild(newRows[i]);
958983
@ }
984
+ @ this.setHdrIcons();
985
+ @ }
986
+ @ this.setHdrIcons = function() {
987
+ @ for (var i=0; i<this.hdrRow.cells.length; i++) {
988
+ @ if( this.columnTypes[i]=='x' ) continue;
989
+ @ var sortType;
990
+ @ if( this.prevColumn==i+1 ){
991
+ @ sortType = 'asc';
992
+ @ }else if( this.prevColumn==(-1-i) ){
993
+ @ sortType = 'desc'
994
+ @ }else{
995
+ @ sortType = 'none';
996
+ @ }
997
+ @ var hdrCell = this.hdrRow.cells[i];
998
+ @ var clsName = hdrCell.className.replace(/\s*\bsort\s*\w+/, '');
999
+ @ clsName += ' sort ' + sortType;
1000
+ @ hdrCell.className = clsName;
1001
+ @ }
9591002
@ }
9601003
@ this.sortText = function(a,b) {
9611004
@ var i = thisObject.sortIndex;
9621005
@ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
9631006
@ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
@@ -971,30 +1014,43 @@
9711014
@ if (isNaN(aa)) aa = 0;
9721015
@ bb = parseFloat(b.cells[i].textContent);
9731016
@ if (isNaN(bb)) bb = 0;
9741017
@ return aa-bb;
9751018
@ }
976
- @ var thisObject = this;
1019
+ @ this.sortKey = function(a,b) {
1020
+ @ var i = thisObject.sortIndex;
1021
+ @ aa = a.cells[i].getAttribute("data-sortkey");
1022
+ @ bb = b.cells[i].getAttribute("data-sortkey");
1023
+ @ if(aa==bb) return 0;
1024
+ @ if(aa<bb) return -1;
1025
+ @ return 1;
1026
+ @ }
9771027
@ var x = tableEl.getElementsByTagName('thead');
9781028
@ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
9791029
@ return;
9801030
@ }
9811031
@ if(x && x[0].rows && x[0].rows.length > 0) {
982
- @ var sortRow = x[0].rows[0];
1032
+ @ this.hdrRow = x[0].rows[0];
9831033
@ } else {
9841034
@ return;
9851035
@ }
986
- @ for (var i=0; i<sortRow.cells.length; i++) {
987
- @ sortRow.cells[i].sTable = this;
988
- @ sortRow.cells[i].sortType = columnTypes[i] || 't';
989
- @ sortRow.cells[i].onclick = function () {
1036
+ @ var thisObject = this;
1037
+ @ this.prevColumn = initSort;
1038
+ @ for (var i=0; i<this.hdrRow.cells.length; i++) {
1039
+ @ if( columnTypes[i]=='x' ) continue;
1040
+ @ var hdrcell = this.hdrRow.cells[i];
1041
+ @ hdrcell.sTable = this;
1042
+ @ hdrcell.style.cursor = "pointer";
1043
+ @ hdrcell.sortType = columnTypes[i] || 't';
1044
+ @ hdrcell.onclick = function () {
9901045
@ this.sTable.sort(this);
9911046
@ return false;
9921047
@ }
9931048
@ }
1049
+ @ this.setHdrIcons()
9941050
@ }
995
- @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)");
1051
+ @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)",%d(iInitSort));
9961052
@ </script>
9971053
}
9981054
9991055
10001056
/*
@@ -1086,11 +1142,11 @@
10861142
if( zErr1 ){
10871143
@ <p class="reportError">Error: %h(zErr1)</p>
10881144
}else if( zErr2 ){
10891145
@ <p class="reportError">Error: %h(zErr2)</p>
10901146
}
1091
- output_table_sorting_javascript("reportTable","");
1147
+ output_table_sorting_javascript("reportTable","",0);
10921148
style_footer();
10931149
}else{
10941150
report_restrict_sql(&zErr1);
10951151
db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
10961152
report_unrestrict_sql();
10971153
--- src/report.c
+++ src/report.c
@@ -922,42 +922,85 @@
922
923 /*
924 ** Output Javascript code that will enables sorting of the table with
925 ** the id zTableId by clicking.
926 **
927 ** The javascript is derived from:
928 **
929 ** http://www.webtoolkit.info/sortable-html-table.html
 
 
930 **
931 ** This variation allows column types to be expressed using the second
932 ** argument. Each character of the second argument represent a column.
933 ** "t" means sort as text. "n" means sort numerically. "x" means do not
934 ** sort on this column. If there are fewer characters in zColumnTypes[] than
935 ** their are columns, the all extra columns assume type "t" (text).
 
 
 
 
 
 
 
 
 
 
 
 
936 */
937 void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){
 
 
 
 
938 @ <script>
939 @ function SortableTable(tableEl,columnTypes){
940 @ this.tbody = tableEl.getElementsByTagName('tbody');
 
941 @ this.sort = function (cell) {
942 @ var column = cell.cellIndex;
943 @ var sortFn = cell.sortType=="n" ? this.sortNumeric : this.sortText;
 
 
 
 
 
 
944 @ this.sortIndex = column;
945 @ var newRows = new Array();
946 @ for (j = 0; j < this.tbody[0].rows.length; j++) {
947 @ newRows[j] = this.tbody[0].rows[j];
948 @ }
949 @ newRows.sort(sortFn);
950 @ if (cell.getAttribute("sortdir") == 'down') {
951 @ newRows.reverse();
952 @ cell.setAttribute('sortdir','up');
953 @ } else {
954 @ cell.setAttribute('sortdir','down');
955 @ }
956 @ for (i=0;i<newRows.length;i++) {
957 @ this.tbody[0].appendChild(newRows[i]);
958 @ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
959 @ }
960 @ this.sortText = function(a,b) {
961 @ var i = thisObject.sortIndex;
962 @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
963 @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
@@ -971,30 +1014,43 @@
971 @ if (isNaN(aa)) aa = 0;
972 @ bb = parseFloat(b.cells[i].textContent);
973 @ if (isNaN(bb)) bb = 0;
974 @ return aa-bb;
975 @ }
976 @ var thisObject = this;
 
 
 
 
 
 
 
977 @ var x = tableEl.getElementsByTagName('thead');
978 @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
979 @ return;
980 @ }
981 @ if(x && x[0].rows && x[0].rows.length > 0) {
982 @ var sortRow = x[0].rows[0];
983 @ } else {
984 @ return;
985 @ }
986 @ for (var i=0; i<sortRow.cells.length; i++) {
987 @ sortRow.cells[i].sTable = this;
988 @ sortRow.cells[i].sortType = columnTypes[i] || 't';
989 @ sortRow.cells[i].onclick = function () {
 
 
 
 
 
990 @ this.sTable.sort(this);
991 @ return false;
992 @ }
993 @ }
 
994 @ }
995 @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)");
996 @ </script>
997 }
998
999
1000 /*
@@ -1086,11 +1142,11 @@
1086 if( zErr1 ){
1087 @ <p class="reportError">Error: %h(zErr1)</p>
1088 }else if( zErr2 ){
1089 @ <p class="reportError">Error: %h(zErr2)</p>
1090 }
1091 output_table_sorting_javascript("reportTable","");
1092 style_footer();
1093 }else{
1094 report_restrict_sql(&zErr1);
1095 db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
1096 report_unrestrict_sql();
1097
--- src/report.c
+++ src/report.c
@@ -922,42 +922,85 @@
922
923 /*
924 ** Output Javascript code that will enables sorting of the table with
925 ** the id zTableId by clicking.
926 **
927 ** The javascript was originally derived from:
928 **
929 ** http://www.webtoolkit.info/sortable-html-table.html
930 **
931 ** But there have been extensive modifications.
932 **
933 ** This variation allows column types to be expressed using the second
934 ** argument. Each character of the second argument represent a column.
935 **
936 ** t Sort by text
937 ** n Sort numerically
938 ** k Sort by the data-sortkey property
939 ** x This column is not sortable
940 **
941 ** If there are fewer characters in zColumnTypes[] than their are columns,
942 ** the all extra columns assume type "t" (text).
943 **
944 ** The third parameter is the column that was initially sorted (using 1-based
945 ** column numbers, like SQL). Make this value 0 if none of the columns are
946 ** initially sorted. Make the value negative if the column is initially sorted
947 ** in reverse order.
948 **
949 ** Clicking on the same column header twice in a row inverts the sort.
950 */
951 void output_table_sorting_javascript(
952 const char *zTableId, /* ID of table to sort */
953 const char *zColumnTypes, /* String for column types */
954 int iInitSort /* Initially sorted column. Leftmost is 1. 0 for NONE */
955 ){
956 @ <script>
957 @ function SortableTable(tableEl,columnTypes,initSort){
958 @ this.tbody = tableEl.getElementsByTagName('tbody');
959 @ this.columnTypes = columnTypes;
960 @ this.sort = function (cell) {
961 @ var column = cell.cellIndex;
962 @ var sortFn;
963 @ switch( cell.sortType ){
964 @ case "n": sortFn = this.sortNumeric; break;
965 @ case "t": sortFn = this.sortText; break;
966 @ case "k": sortFn = this.sortKey; break;
967 @ case "x": return;
968 @ }
969 @ this.sortIndex = column;
970 @ var newRows = new Array();
971 @ for (j = 0; j < this.tbody[0].rows.length; j++) {
972 @ newRows[j] = this.tbody[0].rows[j];
973 @ }
974 @ if( this.sortIndex==Math.abs(this.prevColumn)-1 ){
975 @ newRows.reverse();
976 @ this.prevColumn = -this.prevColumn;
977 @ }else{
978 @ newRows.sort(sortFn);
979 @ this.prevColumn = this.sortIndex+1;
980 @ }
981 @ for (i=0;i<newRows.length;i++) {
982 @ this.tbody[0].appendChild(newRows[i]);
983 @ }
984 @ this.setHdrIcons();
985 @ }
986 @ this.setHdrIcons = function() {
987 @ for (var i=0; i<this.hdrRow.cells.length; i++) {
988 @ if( this.columnTypes[i]=='x' ) continue;
989 @ var sortType;
990 @ if( this.prevColumn==i+1 ){
991 @ sortType = 'asc';
992 @ }else if( this.prevColumn==(-1-i) ){
993 @ sortType = 'desc'
994 @ }else{
995 @ sortType = 'none';
996 @ }
997 @ var hdrCell = this.hdrRow.cells[i];
998 @ var clsName = hdrCell.className.replace(/\s*\bsort\s*\w+/, '');
999 @ clsName += ' sort ' + sortType;
1000 @ hdrCell.className = clsName;
1001 @ }
1002 @ }
1003 @ this.sortText = function(a,b) {
1004 @ var i = thisObject.sortIndex;
1005 @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
1006 @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
@@ -971,30 +1014,43 @@
1014 @ if (isNaN(aa)) aa = 0;
1015 @ bb = parseFloat(b.cells[i].textContent);
1016 @ if (isNaN(bb)) bb = 0;
1017 @ return aa-bb;
1018 @ }
1019 @ this.sortKey = function(a,b) {
1020 @ var i = thisObject.sortIndex;
1021 @ aa = a.cells[i].getAttribute("data-sortkey");
1022 @ bb = b.cells[i].getAttribute("data-sortkey");
1023 @ if(aa==bb) return 0;
1024 @ if(aa<bb) return -1;
1025 @ return 1;
1026 @ }
1027 @ var x = tableEl.getElementsByTagName('thead');
1028 @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
1029 @ return;
1030 @ }
1031 @ if(x && x[0].rows && x[0].rows.length > 0) {
1032 @ this.hdrRow = x[0].rows[0];
1033 @ } else {
1034 @ return;
1035 @ }
1036 @ var thisObject = this;
1037 @ this.prevColumn = initSort;
1038 @ for (var i=0; i<this.hdrRow.cells.length; i++) {
1039 @ if( columnTypes[i]=='x' ) continue;
1040 @ var hdrcell = this.hdrRow.cells[i];
1041 @ hdrcell.sTable = this;
1042 @ hdrcell.style.cursor = "pointer";
1043 @ hdrcell.sortType = columnTypes[i] || 't';
1044 @ hdrcell.onclick = function () {
1045 @ this.sTable.sort(this);
1046 @ return false;
1047 @ }
1048 @ }
1049 @ this.setHdrIcons()
1050 @ }
1051 @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)",%d(iInitSort));
1052 @ </script>
1053 }
1054
1055
1056 /*
@@ -1086,11 +1142,11 @@
1142 if( zErr1 ){
1143 @ <p class="reportError">Error: %h(zErr1)</p>
1144 }else if( zErr2 ){
1145 @ <p class="reportError">Error: %h(zErr2)</p>
1146 }
1147 output_table_sorting_javascript("reportTable","",0);
1148 style_footer();
1149 }else{
1150 report_restrict_sql(&zErr1);
1151 db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
1152 report_unrestrict_sql();
1153
+53 -37
--- src/search.c
+++ src/search.c
@@ -13,27 +13,32 @@
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
18
-** This file contains code to implement the "/doc" web page and related
19
-** pages.
18
+** This file contains code to implement a very simple search function
19
+** against timeline comments, checkin content, wiki pages, and/or tickets.
20
+**
21
+** The search is full-text like in that it is looking for words and ignores
22
+** punctuation and capitalization. But it is more akin to "grep" in that
23
+** it scans the entire corpus for the search, and it does not support the
24
+** full functionality of FTS4.
2025
*/
2126
#include "config.h"
2227
#include "search.h"
2328
#include <assert.h>
2429
2530
#if INTERFACE
2631
/*
27
-** A compiled search patter
32
+** A compiled search pattern
2833
*/
2934
struct Search {
30
- int nTerm;
31
- struct srchTerm {
32
- char *z;
33
- int n;
34
- } a[8];
35
+ int nTerm; /* Number of search terms */
36
+ struct srchTerm { /* For each search term */
37
+ char *z; /* Text */
38
+ int n; /* length */
39
+ } a[8];
3540
};
3641
#endif
3742
3843
/*
3944
** Compile a search pattern
@@ -98,43 +103,47 @@
98103
** * 10 bonus points if the first occurrence is an exact match
99104
** * 1 additional point for each subsequent match of the same word
100105
** * Extra points of two consecutive words of the pattern are consecutive
101106
** in the document
102107
*/
103
-int search_score(Search *p, const char *zDoc){
108
+int search_score(Search *p, int nDoc, const char **azDoc){
104109
int iPrev = 999;
105110
int score = 10;
106111
int iBonus = 0;
107
- int i, j;
112
+ int i, j, k;
113
+ const char *zDoc;
108114
unsigned char seen[8];
109115
110116
memset(seen, 0, sizeof(seen));
111
- if( zDoc==0 ) return score;
112
- for(i=0; zDoc[i]; i++){
113
- char c = zDoc[i];
114
- if( isBoundary[c&0xff] ) continue;
115
- for(j=0; j<p->nTerm; j++){
116
- int n = p->a[j].n;
117
- if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
118
- score += 1;
119
- if( !seen[j] ){
120
- if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
121
- seen[j] = 1;
122
- }
123
- if( j==iPrev+1 ){
124
- score += iBonus;
125
- }
126
- i += n-1;
127
- iPrev = j;
128
- iBonus = 50;
129
- break;
130
- }
131
- }
132
- iBonus /= 2;
133
- while( !isBoundary[zDoc[i]&0xff] ){ i++; }
134
- }
135
-
117
+ for(k=0; k<nDoc; k++){
118
+ zDoc = azDoc[k];
119
+ if( zDoc==0 ) continue;
120
+ for(i=0; zDoc[i]; i++){
121
+ char c = zDoc[i];
122
+ if( isBoundary[c&0xff] ) continue;
123
+ for(j=0; j<p->nTerm; j++){
124
+ int n = p->a[j].n;
125
+ if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
126
+ score += 1;
127
+ if( !seen[j] ){
128
+ if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
129
+ seen[j] = 1;
130
+ }
131
+ if( j==iPrev+1 ){
132
+ score += iBonus;
133
+ }
134
+ i += n-1;
135
+ iPrev = j;
136
+ iBonus = 50;
137
+ break;
138
+ }
139
+ }
140
+ iBonus /= 2;
141
+ while( !isBoundary[zDoc[i]&0xff] ){ i++; }
142
+ }
143
+ }
144
+
136145
/* Every term must be seen or else the score is zero */
137146
for(j=0; j<p->nTerm; j++){
138147
if( !seen[j] ) return 0;
139148
}
140149
@@ -149,21 +158,28 @@
149158
sqlite3_context *context,
150159
int argc,
151160
sqlite3_value **argv
152161
){
153162
Search *p = (Search*)sqlite3_user_data(context);
154
- int score = search_score(p, (const char*)sqlite3_value_text(argv[0]));
163
+ const char **azDoc;
164
+ int score;
165
+ int i;
166
+
167
+ azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
168
+ for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
169
+ score = search_score(p, argc, azDoc);
170
+ fossil_free(azDoc);
155171
sqlite3_result_int(context, score);
156172
}
157173
158174
/*
159175
** Register the "score()" SQL function to score its input text
160176
** using the given Search object. Once this function is registered,
161177
** do not delete the Search object.
162178
*/
163179
void search_sql_setup(Search *p){
164
- sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
180
+ sqlite3_create_function(g.db, "score", -1, SQLITE_UTF8, p,
165181
search_score_sqlfunc, 0, 0);
166182
}
167183
168184
/*
169185
** Testing the search function.
170186
171187
ADDED src/sitemap.c
--- src/search.c
+++ src/search.c
@@ -13,27 +13,32 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to implement the "/doc" web page and related
19 ** pages.
 
 
 
 
 
20 */
21 #include "config.h"
22 #include "search.h"
23 #include <assert.h>
24
25 #if INTERFACE
26 /*
27 ** A compiled search patter
28 */
29 struct Search {
30 int nTerm;
31 struct srchTerm {
32 char *z;
33 int n;
34 } a[8];
35 };
36 #endif
37
38 /*
39 ** Compile a search pattern
@@ -98,43 +103,47 @@
98 ** * 10 bonus points if the first occurrence is an exact match
99 ** * 1 additional point for each subsequent match of the same word
100 ** * Extra points of two consecutive words of the pattern are consecutive
101 ** in the document
102 */
103 int search_score(Search *p, const char *zDoc){
104 int iPrev = 999;
105 int score = 10;
106 int iBonus = 0;
107 int i, j;
 
108 unsigned char seen[8];
109
110 memset(seen, 0, sizeof(seen));
111 if( zDoc==0 ) return score;
112 for(i=0; zDoc[i]; i++){
113 char c = zDoc[i];
114 if( isBoundary[c&0xff] ) continue;
115 for(j=0; j<p->nTerm; j++){
116 int n = p->a[j].n;
117 if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
118 score += 1;
119 if( !seen[j] ){
120 if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
121 seen[j] = 1;
122 }
123 if( j==iPrev+1 ){
124 score += iBonus;
125 }
126 i += n-1;
127 iPrev = j;
128 iBonus = 50;
129 break;
130 }
131 }
132 iBonus /= 2;
133 while( !isBoundary[zDoc[i]&0xff] ){ i++; }
134 }
135
 
 
 
136 /* Every term must be seen or else the score is zero */
137 for(j=0; j<p->nTerm; j++){
138 if( !seen[j] ) return 0;
139 }
140
@@ -149,21 +158,28 @@
149 sqlite3_context *context,
150 int argc,
151 sqlite3_value **argv
152 ){
153 Search *p = (Search*)sqlite3_user_data(context);
154 int score = search_score(p, (const char*)sqlite3_value_text(argv[0]));
 
 
 
 
 
 
 
155 sqlite3_result_int(context, score);
156 }
157
158 /*
159 ** Register the "score()" SQL function to score its input text
160 ** using the given Search object. Once this function is registered,
161 ** do not delete the Search object.
162 */
163 void search_sql_setup(Search *p){
164 sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
165 search_score_sqlfunc, 0, 0);
166 }
167
168 /*
169 ** Testing the search function.
170
171 DDED src/sitemap.c
--- src/search.c
+++ src/search.c
@@ -13,27 +13,32 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to implement a very simple search function
19 ** against timeline comments, checkin content, wiki pages, and/or tickets.
20 **
21 ** The search is full-text like in that it is looking for words and ignores
22 ** punctuation and capitalization. But it is more akin to "grep" in that
23 ** it scans the entire corpus for the search, and it does not support the
24 ** full functionality of FTS4.
25 */
26 #include "config.h"
27 #include "search.h"
28 #include <assert.h>
29
30 #if INTERFACE
31 /*
32 ** A compiled search pattern
33 */
34 struct Search {
35 int nTerm; /* Number of search terms */
36 struct srchTerm { /* For each search term */
37 char *z; /* Text */
38 int n; /* length */
39 } a[8];
40 };
41 #endif
42
43 /*
44 ** Compile a search pattern
@@ -98,43 +103,47 @@
103 ** * 10 bonus points if the first occurrence is an exact match
104 ** * 1 additional point for each subsequent match of the same word
105 ** * Extra points of two consecutive words of the pattern are consecutive
106 ** in the document
107 */
108 int search_score(Search *p, int nDoc, const char **azDoc){
109 int iPrev = 999;
110 int score = 10;
111 int iBonus = 0;
112 int i, j, k;
113 const char *zDoc;
114 unsigned char seen[8];
115
116 memset(seen, 0, sizeof(seen));
117 for(k=0; k<nDoc; k++){
118 zDoc = azDoc[k];
119 if( zDoc==0 ) continue;
120 for(i=0; zDoc[i]; i++){
121 char c = zDoc[i];
122 if( isBoundary[c&0xff] ) continue;
123 for(j=0; j<p->nTerm; j++){
124 int n = p->a[j].n;
125 if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
126 score += 1;
127 if( !seen[j] ){
128 if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
129 seen[j] = 1;
130 }
131 if( j==iPrev+1 ){
132 score += iBonus;
133 }
134 i += n-1;
135 iPrev = j;
136 iBonus = 50;
137 break;
138 }
139 }
140 iBonus /= 2;
141 while( !isBoundary[zDoc[i]&0xff] ){ i++; }
142 }
143 }
144
145 /* Every term must be seen or else the score is zero */
146 for(j=0; j<p->nTerm; j++){
147 if( !seen[j] ) return 0;
148 }
149
@@ -149,21 +158,28 @@
158 sqlite3_context *context,
159 int argc,
160 sqlite3_value **argv
161 ){
162 Search *p = (Search*)sqlite3_user_data(context);
163 const char **azDoc;
164 int score;
165 int i;
166
167 azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
168 for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
169 score = search_score(p, argc, azDoc);
170 fossil_free(azDoc);
171 sqlite3_result_int(context, score);
172 }
173
174 /*
175 ** Register the "score()" SQL function to score its input text
176 ** using the given Search object. Once this function is registered,
177 ** do not delete the Search object.
178 */
179 void search_sql_setup(Search *p){
180 sqlite3_create_function(g.db, "score", -1, SQLITE_UTF8, p,
181 search_score_sqlfunc, 0, 0);
182 }
183
184 /*
185 ** Testing the search function.
186
187 DDED src/sitemap.c
--- a/src/sitemap.c
+++ b/src/sitemap.c
@@ -0,0 +1,43 @@
1
+avtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap");
2
+ }
3
+}
4
+footer();
5
+ }
6
+}
7
+?name=Sandbox"))SandboxHelphelp"))List of All Commands and Web@mimetype map1style_header("Site Map");
8
+style_footer();
9
+}
10
+divul id="sitemap">
11
+</div>
12
+ style_footer();
13
+}
14
+</librlist"))Branchesaglist"))TagsdTktli>
15
+ style_footer();
16
+}
17
+?n=200}
18
+line?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap");
19
+ }
20
+}
21
+footer();
22
+ }
23
+}
24
+?name=Sandboxavtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap");
25
+ }
26
+}
27
+footer();
28
+ @ </p>
29
+ @
30
+#endifq@N6,W@Rh,X@1B~,b:docsrch"))Search Project DocumeShow an incomplete list of@Uy,q@gW,7O@aw,c@linkest_li>
31
+ @ <ul>docsrc@ </@@ @ warps"))List of "Timewaavtimeline?n=all&imeline?n=aln=all&namechng"))All check-in@ </@@ </ul>
32
+ @ </liwi</a>
33
+ @ <ul>
34
+q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul>
35
+ @ </li@ </ul>
36
+ @ </liblobrtifacts</a></li>
37
+ in<ultree?Branches and Tags</a>
38
+ @ <uls"))List of "avtimelinew@ @ @ @ @ </ul>
39
+ @ </li@ </ul>
40
+ @ </liblobrtifactseline?n=aln=all&namechng"))All cul>
41
+q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul>
42
+ @ </li@ </ul>
43
+ @ </liblobrtifactsstat"))Status SummaAdministration0
--- a/src/sitemap.c
+++ b/src/sitemap.c
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/sitemap.c
+++ b/src/sitemap.c
@@ -0,0 +1,43 @@
1 avtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap");
2 }
3 }
4 footer();
5 }
6 }
7 ?name=Sandbox"))SandboxHelphelp"))List of All Commands and Web@mimetype map1style_header("Site Map");
8 style_footer();
9 }
10 divul id="sitemap">
11 </div>
12 style_footer();
13 }
14 </librlist"))Branchesaglist"))TagsdTktli>
15 style_footer();
16 }
17 ?n=200}
18 line?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap");
19 }
20 }
21 footer();
22 }
23 }
24 ?name=Sandboxavtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap");
25 }
26 }
27 footer();
28 @ </p>
29 @
30 #endifq@N6,W@Rh,X@1B~,b:docsrch"))Search Project DocumeShow an incomplete list of@Uy,q@gW,7O@aw,c@linkest_li>
31 @ <ul>docsrc@ </@@ @ warps"))List of "Timewaavtimeline?n=all&imeline?n=aln=all&namechng"))All check-in@ </@@ </ul>
32 @ </liwi</a>
33 @ <ul>
34 q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul>
35 @ </li@ </ul>
36 @ </liblobrtifacts</a></li>
37 in<ultree?Branches and Tags</a>
38 @ <uls"))List of "avtimelinew@ @ @ @ @ </ul>
39 @ </li@ </ul>
40 @ </liblobrtifactseline?n=aln=all&namechng"))All cul>
41 q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul>
42 @ </li@ </ul>
43 @ </liblobrtifactsstat"))Status SummaAdministration0
+328 -234
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -231,11 +231,11 @@
231231
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
232232
** [sqlite_version()] and [sqlite_source_id()].
233233
*/
234234
#define SQLITE_VERSION "3.8.8"
235235
#define SQLITE_VERSION_NUMBER 3008008
236
-#define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0"
236
+#define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6"
237237
238238
/*
239239
** CAPI3REF: Run-Time Library Version Numbers
240240
** KEYWORDS: sqlite3_version, sqlite3_sourceid
241241
**
@@ -323,11 +323,11 @@
323323
** This interface only reports on the compile-time mutex setting
324324
** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
325325
** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
326326
** can be fully or partially disabled using a call to [sqlite3_config()]
327327
** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
328
-** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the
328
+** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the
329329
** sqlite3_threadsafe() function shows only the compile-time setting of
330330
** thread safety, not any run-time changes to that setting made by
331331
** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
332332
** is unchanged by calls to sqlite3_config().)^
333333
**
@@ -1692,11 +1692,11 @@
16921692
** configuration option.
16931693
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
16941694
** 8-byte aligned
16951695
** memory, the size of each page buffer (sz), and the number of pages (N).
16961696
** The sz argument should be the size of the largest database page
1697
-** (a power of two between 512 and 32768) plus some extra bytes for each
1697
+** (a power of two between 512 and 65536) plus some extra bytes for each
16981698
** page header. ^The number of extra bytes needed by the page header
16991699
** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
17001700
** to [sqlite3_config()].
17011701
** ^It is harmless, apart from the wasted memory,
17021702
** for the sz parameter to be larger than necessary. The first
@@ -1872,10 +1872,21 @@
18721872
** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
18731873
** is a pointer to an integer and writes into that integer the number of extra
18741874
** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
18751875
** The amount of extra space required can change depending on the compiler,
18761876
** target platform, and SQLite version.
1877
+**
1878
+** [[SQLITE_CONFIG_PMASZ]]
1879
+** <dt>SQLITE_CONFIG_PMASZ
1880
+** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which
1881
+** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded
1882
+** sorter to that integer. The default minimum PMA Size is set by the
1883
+** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched
1884
+** to help with sort operations when multithreaded sorting
1885
+** is enabled (using the [PRAGMA threads] command) and the amount of content
1886
+** to be sorted exceeds the page size times the minimum of the
1887
+** [PRAGMA cache_size] setting and this value.
18771888
** </dl>
18781889
*/
18791890
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
18801891
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
18811892
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1898,10 +1909,11 @@
18981909
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
18991910
#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
19001911
#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
19011912
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
19021913
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
1914
+#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
19031915
19041916
/*
19051917
** CAPI3REF: Database Connection Configuration Options
19061918
**
19071919
** These constants are the available integer configuration options that
@@ -5279,24 +5291,31 @@
52795291
52805292
52815293
/*
52825294
** CAPI3REF: Extract Metadata About A Column Of A Table
52835295
**
5284
-** ^This routine returns metadata about a specific column of a specific
5285
-** database table accessible using the [database connection] handle
5286
-** passed as the first function argument.
5296
+** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
5297
+** information about column C of table T in database D
5298
+** on [database connection] X.)^ ^The sqlite3_table_column_metadata()
5299
+** interface returns SQLITE_OK and fills in the non-NULL pointers in
5300
+** the final five arguments with appropriate values if the specified
5301
+** column exists. ^The sqlite3_table_column_metadata() interface returns
5302
+** SQLITE_ERROR and if the specified column does not exist.
5303
+** ^If the column-name parameter to sqlite3_table_column_metadata() is a
5304
+** NULL pointer, then this routine simply checks for the existance of the
5305
+** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
5306
+** does not.
52875307
**
52885308
** ^The column is identified by the second, third and fourth parameters to
5289
-** this function. ^The second parameter is either the name of the database
5309
+** this function. ^(The second parameter is either the name of the database
52905310
** (i.e. "main", "temp", or an attached database) containing the specified
5291
-** table or NULL. ^If it is NULL, then all attached databases are searched
5311
+** table or NULL.)^ ^If it is NULL, then all attached databases are searched
52925312
** for the table using the same algorithm used by the database engine to
52935313
** resolve unqualified table references.
52945314
**
52955315
** ^The third and fourth parameters to this function are the table and column
5296
-** name of the desired column, respectively. Neither of these parameters
5297
-** may be NULL.
5316
+** name of the desired column, respectively.
52985317
**
52995318
** ^Metadata is returned by writing to the memory locations passed as the 5th
53005319
** and subsequent parameters to this function. ^Any of these arguments may be
53015320
** NULL, in which case the corresponding element of metadata is omitted.
53025321
**
@@ -5311,36 +5330,33 @@
53115330
** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
53125331
** </table>
53135332
** </blockquote>)^
53145333
**
53155334
** ^The memory pointed to by the character pointers returned for the
5316
-** declaration type and collation sequence is valid only until the next
5335
+** declaration type and collation sequence is valid until the next
53175336
** call to any SQLite API function.
53185337
**
53195338
** ^If the specified table is actually a view, an [error code] is returned.
53205339
**
5321
-** ^If the specified column is "rowid", "oid" or "_rowid_" and an
5340
+** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
5341
+** is not a [WITHOUT ROWID] table and an
53225342
** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
53235343
** parameters are set for the explicitly declared column. ^(If there is no
5324
-** explicitly declared [INTEGER PRIMARY KEY] column, then the output
5325
-** parameters are set as follows:
5344
+** [INTEGER PRIMARY KEY] column, then the outputs
5345
+** for the [rowid] are set as follows:
53265346
**
53275347
** <pre>
53285348
** data type: "INTEGER"
53295349
** collation sequence: "BINARY"
53305350
** not null: 0
53315351
** primary key: 1
53325352
** auto increment: 0
53335353
** </pre>)^
53345354
**
5335
-** ^(This function may load one or more schemas from database files. If an
5336
-** error occurs during this process, or if the requested table or column
5337
-** cannot be found, an [error code] is returned and an error message left
5338
-** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^
5339
-**
5340
-** ^This API is only available if the library was compiled with the
5341
-** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
5355
+** ^This function causes all database schemas to be read from disk and
5356
+** parsed, if that has not already been done, and returns an error if
5357
+** any errors are encountered while loading the schema.
53425358
*/
53435359
SQLITE_API int sqlite3_table_column_metadata(
53445360
sqlite3 *db, /* Connection handle */
53455361
const char *zDbName, /* Database name or NULL */
53465362
const char *zTableName, /* Table name */
@@ -7303,16 +7319,14 @@
73037319
73047320
/*
73057321
** CAPI3REF: Write-Ahead Log Commit Hook
73067322
**
73077323
** ^The [sqlite3_wal_hook()] function is used to register a callback that
7308
-** will be invoked each time a database connection commits data to a
7309
-** [write-ahead log] (i.e. whenever a transaction is committed in
7310
-** [journal_mode | journal_mode=WAL mode]).
7324
+** is invoked each time data is committed to a database in wal mode.
73117325
**
7312
-** ^The callback is invoked by SQLite after the commit has taken place and
7313
-** the associated write-lock on the database released, so the implementation
7326
+** ^(The callback is invoked by SQLite after the commit has taken place and
7327
+** the associated write-lock on the database released)^, so the implementation
73147328
** may read, write or [checkpoint] the database as required.
73157329
**
73167330
** ^The first parameter passed to the callback function when it is invoked
73177331
** is a copy of the third parameter passed to sqlite3_wal_hook() when
73187332
** registering the callback. ^The second is a copy of the database handle.
@@ -9096,11 +9110,11 @@
90969110
#define _BTREE_H_
90979111
90989112
/* TODO: This definition is just included so other modules compile. It
90999113
** needs to be revisited.
91009114
*/
9101
-#define SQLITE_N_BTREE_META 10
9115
+#define SQLITE_N_BTREE_META 16
91029116
91039117
/*
91049118
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
91059119
** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
91069120
*/
@@ -9211,10 +9225,15 @@
92119225
** offset = 36 + (idx * 4)
92129226
**
92139227
** For example, the free-page-count field is located at byte offset 36 of
92149228
** the database file header. The incr-vacuum-flag field is located at
92159229
** byte offset 64 (== 36+4*7).
9230
+**
9231
+** The BTREE_DATA_VERSION value is not really a value stored in the header.
9232
+** It is a read-only number computed by the pager. But we merge it with
9233
+** the header value access routines since its access pattern is the same.
9234
+** Call it a "virtual meta value".
92169235
*/
92179236
#define BTREE_FREE_PAGE_COUNT 0
92189237
#define BTREE_SCHEMA_VERSION 1
92199238
#define BTREE_FILE_FORMAT 2
92209239
#define BTREE_DEFAULT_CACHE_SIZE 3
@@ -9221,10 +9240,11 @@
92219240
#define BTREE_LARGEST_ROOT_PAGE 4
92229241
#define BTREE_TEXT_ENCODING 5
92239242
#define BTREE_USER_VERSION 6
92249243
#define BTREE_INCR_VACUUM 7
92259244
#define BTREE_APPLICATION_ID 8
9245
+#define BTREE_DATA_VERSION 15 /* A virtual meta-value */
92269246
92279247
/*
92289248
** Values that may be OR'd together to form the second argument of an
92299249
** sqlite3BtreeCursorHints() call.
92309250
*/
@@ -10002,10 +10022,11 @@
1000210022
SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
1000310023
#endif
1000410024
1000510025
/* Functions used to query pager state and configuration. */
1000610026
SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
10027
+SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*);
1000710028
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
1000810029
SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
1000910030
SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
1001010031
SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
1001110032
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
@@ -10743,10 +10764,11 @@
1074310764
i64 szMmap; /* Default mmap_size setting */
1074410765
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
1074510766
int errCode; /* Most recent error code (SQLITE_*) */
1074610767
int errMask; /* & result codes with this before returning */
1074710768
u16 dbOptFlags; /* Flags to enable/disable optimizations */
10769
+ u8 enc; /* Text encoding */
1074810770
u8 autoCommit; /* The auto-commit flag. */
1074910771
u8 temp_store; /* 1: file 2: memory 0: default */
1075010772
u8 mallocFailed; /* True if we have seen a malloc failure */
1075110773
u8 dfltLockMode; /* Default locking-mode for attached dbs */
1075210774
signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
@@ -10844,11 +10866,12 @@
1084410866
};
1084510867
1084610868
/*
1084710869
** A macro to discover the encoding of a database.
1084810870
*/
10849
-#define ENC(db) ((db)->aDb[0].pSchema->enc)
10871
+#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
10872
+#define ENC(db) ((db)->enc)
1085010873
1085110874
/*
1085210875
** Possible values for the sqlite3.flags.
1085310876
*/
1085410877
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
@@ -11468,11 +11491,10 @@
1146811491
Index *pNext; /* The next index associated with the same table */
1146911492
Schema *pSchema; /* Schema containing this index */
1147011493
u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
1147111494
char **azColl; /* Array of collation sequence names for index */
1147211495
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
11473
- KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */
1147411496
int tnum; /* DB Page containing root of this index */
1147511497
LogEst szIdxRow; /* Estimated average row size in bytes */
1147611498
u16 nKeyCol; /* Number of columns forming the key */
1147711499
u16 nColumn; /* Number of columns stored in the index */
1147811500
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
@@ -12522,10 +12544,11 @@
1252212544
void *pPage; /* Page cache memory */
1252312545
int szPage; /* Size of each page in pPage[] */
1252412546
int nPage; /* Number of pages in pPage[] */
1252512547
int mxParserStack; /* maximum depth of the parser stack */
1252612548
int sharedCacheEnabled; /* true if shared-cache mode enabled */
12549
+ u32 szPma; /* Maximum Sorter PMA size */
1252712550
/* The above might be initialized to non-zero. The following need to always
1252812551
** initially be zero, however. */
1252912552
int isInit; /* True after initialization has finished */
1253012553
int inProgress; /* True while initialization in progress */
1253112554
int isMutexInit; /* True after mutexes are initialized */
@@ -13444,11 +13467,11 @@
1344413467
** print I/O tracing messages.
1344513468
*/
1344613469
#ifdef SQLITE_ENABLE_IOTRACE
1344713470
# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
1344813471
SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*);
13449
-SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...);
13472
+void (*sqlite3IoTrace)(const char*,...);
1345013473
#else
1345113474
# define IOTRACE(A)
1345213475
# define sqlite3VdbeIOTraceSql(X)
1345313476
#endif
1345413477
@@ -13657,10 +13680,17 @@
1365713680
*/
1365813681
#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
1365913682
# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
1366013683
#endif
1366113684
13685
+/* The minimum PMA size is set to this value multiplied by the database
13686
+** page size in bytes.
13687
+*/
13688
+#ifndef SQLITE_SORTER_PMASZ
13689
+# define SQLITE_SORTER_PMASZ 250
13690
+#endif
13691
+
1366213692
/*
1366313693
** The following singleton contains the global configuration for
1366413694
** the SQLite library.
1366513695
*/
1366613696
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
@@ -13687,10 +13717,11 @@
1368713717
(void*)0, /* pPage */
1368813718
0, /* szPage */
1368913719
0, /* nPage */
1369013720
0, /* mxParserStack */
1369113721
0, /* sharedCacheEnabled */
13722
+ SQLITE_SORTER_PMASZ, /* szPma */
1369213723
/* All the rest should always be initialized to zero */
1369313724
0, /* isInit */
1369413725
0, /* inProgress */
1369513726
0, /* isMutexInit */
1369613727
0, /* isMallocInit */
@@ -19972,10 +20003,16 @@
1997220003
#endif
1997320004
}
1997420005
break;
1997520006
}
1997620007
default: {
20008
+#ifdef SQLITE_ENABLE_API_ARMOR
20009
+ if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
20010
+ (void)SQLITE_MISUSE_BKPT;
20011
+ return 0;
20012
+ }
20013
+#endif
1997720014
assert( iType-2 >= 0 );
1997820015
assert( iType-2 < ArraySize(winMutex_staticMutexes) );
1997920016
assert( winMutex_isInit==1 );
1998020017
p = &winMutex_staticMutexes[iType-2];
1998120018
#ifdef SQLITE_DEBUG
@@ -28779,28 +28816,31 @@
2877928816
do{
2878028817
err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
2878128818
}while( err==EINTR );
2878228819
if( err ) return SQLITE_IOERR_WRITE;
2878328820
#else
28784
- /* If the OS does not have posix_fallocate(), fake it. First use
28785
- ** ftruncate() to set the file size, then write a single byte to
28786
- ** the last byte in each block within the extended region. This
28787
- ** is the same technique used by glibc to implement posix_fallocate()
28788
- ** on systems that do not have a real fallocate() system call.
28821
+ /* If the OS does not have posix_fallocate(), fake it. Write a
28822
+ ** single byte to the last byte in each block that falls entirely
28823
+ ** within the extended region. Then, if required, a single byte
28824
+ ** at offset (nSize-1), to set the size of the file correctly.
28825
+ ** This is a similar technique to that used by glibc on systems
28826
+ ** that do not have a real fallocate() call.
2878928827
*/
2879028828
int nBlk = buf.st_blksize; /* File-system block size */
2879128829
i64 iWrite; /* Next offset to write to */
2879228830
28793
- if( robust_ftruncate(pFile->h, nSize) ){
28794
- pFile->lastErrno = errno;
28795
- return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
28796
- }
2879728831
iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
28798
- while( iWrite<nSize ){
28832
+ assert( iWrite>=buf.st_size );
28833
+ assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) );
28834
+ assert( ((iWrite+1)%nBlk)==0 );
28835
+ for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){
2879928836
int nWrite = seekAndWrite(pFile, iWrite, "", 1);
2880028837
if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
28801
- iWrite += nBlk;
28838
+ }
28839
+ if( nSize%nBlk ){
28840
+ int nWrite = seekAndWrite(pFile, nSize-1, "", 1);
28841
+ if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
2880228842
}
2880328843
#endif
2880428844
}
2880528845
}
2880628846
@@ -34014,12 +34054,12 @@
3401434054
*/
3401534055
SQLITE_API int sqlite3_win32_reset_heap(){
3401634056
int rc;
3401734057
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
3401834058
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
34019
- MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
34020
- MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
34059
+ MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); )
34060
+ MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); )
3402134061
sqlite3_mutex_enter(pMaster);
3402234062
sqlite3_mutex_enter(pMem);
3402334063
winMemAssertMagic();
3402434064
if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
3402534065
/*
@@ -35290,11 +35330,11 @@
3529035330
sqlite3_file *id, /* File to read from */
3529135331
void *pBuf, /* Write content into this buffer */
3529235332
int amt, /* Number of bytes to read */
3529335333
sqlite3_int64 offset /* Begin reading at this offset */
3529435334
){
35295
-#if !SQLITE_OS_WINCE
35335
+#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
3529635336
OVERLAPPED overlapped; /* The offset for ReadFile. */
3529735337
#endif
3529835338
winFile *pFile = (winFile*)id; /* file handle */
3529935339
DWORD nRead; /* Number of bytes actually read from file */
3530035340
int nRetry = 0; /* Number of retrys */
@@ -35322,11 +35362,11 @@
3532235362
offset += nCopy;
3532335363
}
3532435364
}
3532535365
#endif
3532635366
35327
-#if SQLITE_OS_WINCE
35367
+#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
3532835368
if( winSeekFile(pFile, offset) ){
3532935369
OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
3533035370
return SQLITE_FULL;
3533135371
}
3533235372
while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
@@ -35394,32 +35434,32 @@
3539435434
offset += nCopy;
3539535435
}
3539635436
}
3539735437
#endif
3539835438
35399
-#if SQLITE_OS_WINCE
35439
+#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
3540035440
rc = winSeekFile(pFile, offset);
3540135441
if( rc==0 ){
3540235442
#else
3540335443
{
3540435444
#endif
35405
-#if !SQLITE_OS_WINCE
35445
+#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
3540635446
OVERLAPPED overlapped; /* The offset for WriteFile. */
3540735447
#endif
3540835448
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
3540935449
int nRem = amt; /* Number of bytes yet to be written */
3541035450
DWORD nWrite; /* Bytes written by each WriteFile() call */
3541135451
DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
3541235452
35413
-#if !SQLITE_OS_WINCE
35453
+#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
3541435454
memset(&overlapped, 0, sizeof(OVERLAPPED));
3541535455
overlapped.Offset = (LONG)(offset & 0xffffffff);
3541635456
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
3541735457
#endif
3541835458
3541935459
while( nRem>0 ){
35420
-#if SQLITE_OS_WINCE
35460
+#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
3542135461
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
3542235462
#else
3542335463
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
3542435464
#endif
3542535465
if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
@@ -35428,11 +35468,11 @@
3542835468
assert( nWrite==0 || nWrite<=(DWORD)nRem );
3542935469
if( nWrite==0 || nWrite>(DWORD)nRem ){
3543035470
lastErrno = osGetLastError();
3543135471
break;
3543235472
}
35433
-#if !SQLITE_OS_WINCE
35473
+#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
3543435474
offset += nWrite;
3543535475
overlapped.Offset = (LONG)(offset & 0xffffffff);
3543635476
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
3543735477
#endif
3543835478
aRem += nWrite;
@@ -38974,11 +39014,12 @@
3897439014
SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
3897539015
assert( pCache->nRef==0 && pCache->pDirty==0 );
3897639016
if( pCache->szPage ){
3897739017
sqlite3_pcache *pNew;
3897839018
pNew = sqlite3GlobalConfig.pcache2.xCreate(
38979
- szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
39019
+ szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)),
39020
+ pCache->bPurgeable
3898039021
);
3898139022
if( pNew==0 ) return SQLITE_NOMEM;
3898239023
sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
3898339024
if( pCache->pCache ){
3898439025
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
@@ -39433,11 +39474,11 @@
3943339474
3943439475
/*
3943539476
** Return the size of the header added by this middleware layer
3943639477
** in the page-cache hierarchy.
3943739478
*/
39438
-SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); }
39479
+SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
3943939480
3944039481
3944139482
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
3944239483
/*
3944339484
** For all dirty pages currently in the cache, invoke the specified
@@ -39749,11 +39790,11 @@
3974939790
pcache1Free(pPg);
3975039791
sqlite3_free(p);
3975139792
pPg = 0;
3975239793
}
3975339794
#else
39754
- pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
39795
+ pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra);
3975539796
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
3975639797
#endif
3975739798
pcache1EnterMutex(pCache->pGroup);
3975839799
3975939800
if( pPg ){
@@ -40437,11 +40478,11 @@
4043740478
}
4043840479
4043940480
/*
4044040481
** Return the size of the header on each page of this PCACHE implementation.
4044140482
*/
40442
-SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); }
40483
+SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
4044340484
4044440485
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
4044540486
/*
4044640487
** This function is called to free superfluous dynamically allocated memory
4044740488
** held by the pager system. Memory in use by any SQLite pager allocated
@@ -41795,10 +41836,12 @@
4179541836
u8 eLock; /* Current lock held on database file */
4179641837
u8 changeCountDone; /* Set after incrementing the change-counter */
4179741838
u8 setMaster; /* True if a m-j name has been written to jrnl */
4179841839
u8 doNotSpill; /* Do not spill the cache when non-zero */
4179941840
u8 subjInMemory; /* True to use in-memory sub-journals */
41841
+ u8 bUseFetch; /* True to use xFetch() */
41842
+ u8 hasBeenUsed; /* True if any content previously read from this pager*/
4180041843
Pgno dbSize; /* Number of pages in the database */
4180141844
Pgno dbOrigSize; /* dbSize before the current transaction */
4180241845
Pgno dbFileSize; /* Number of pages in the database file */
4180341846
Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */
4180441847
int errCode; /* One of several kinds of errors */
@@ -41812,13 +41855,13 @@
4181241855
i64 journalOff; /* Current write offset in the journal file */
4181341856
i64 journalHdr; /* Byte offset to previous journal header */
4181441857
sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
4181541858
PagerSavepoint *aSavepoint; /* Array of active savepoints */
4181641859
int nSavepoint; /* Number of elements in aSavepoint[] */
41860
+ u32 iDataVersion; /* Changes whenever database content changes */
4181741861
char dbFileVers[16]; /* Changes whenever database file changes */
4181841862
41819
- u8 bUseFetch; /* True to use xFetch() */
4182041863
int nMmapOut; /* Number of mmap pages currently outstanding */
4182141864
sqlite3_int64 szMmap; /* Desired maximum mmap size */
4182241865
PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */
4182341866
/*
4182441867
** End of the routinely-changing class members
@@ -42830,13 +42873,22 @@
4283042873
4283142874
/*
4283242875
** Discard the entire contents of the in-memory page-cache.
4283342876
*/
4283442877
static void pager_reset(Pager *pPager){
42878
+ pPager->iDataVersion++;
4283542879
sqlite3BackupRestart(pPager->pBackup);
4283642880
sqlite3PcacheClear(pPager->pPCache);
4283742881
}
42882
+
42883
+/*
42884
+** Return the pPager->iDataVersion value
42885
+*/
42886
+SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){
42887
+ assert( pPager->eState>PAGER_OPEN );
42888
+ return pPager->iDataVersion;
42889
+}
4283842890
4283942891
/*
4284042892
** Free all structures in the Pager.aSavepoint[] array and set both
4284142893
** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
4284242894
** if it is open and the pager is not in exclusive mode.
@@ -45036,11 +45088,11 @@
4503645088
Pgno pgno, /* Page number */
4503745089
void *pData, /* xFetch()'d data for this page */
4503845090
PgHdr **ppPage /* OUT: Acquired page object */
4503945091
){
4504045092
PgHdr *p; /* Memory mapped page to return */
45041
-
45093
+
4504245094
if( pPager->pMmapFreelist ){
4504345095
*ppPage = p = pPager->pMmapFreelist;
4504445096
pPager->pMmapFreelist = p->pDirty;
4504545097
p->pDirty = 0;
4504645098
memset(p->pExtra, 0, pPager->nExtra);
@@ -46267,20 +46319,16 @@
4626746319
assert( (pPager->eLock==SHARED_LOCK)
4626846320
|| (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
4626946321
);
4627046322
}
4627146323
46272
- if( !pPager->tempFile && (
46273
- pPager->pBackup
46274
- || sqlite3PcachePagecount(pPager->pPCache)>0
46275
- || USEFETCH(pPager)
46276
- )){
46277
- /* The shared-lock has just been acquired on the database file
46278
- ** and there are already pages in the cache (from a previous
46279
- ** read or write transaction). Check to see if the database
46280
- ** has been modified. If the database has changed, flush the
46281
- ** cache.
46324
+ if( !pPager->tempFile && pPager->hasBeenUsed ){
46325
+ /* The shared-lock has just been acquired then check to
46326
+ ** see if the database has been modified. If the database has changed,
46327
+ ** flush the cache. The pPager->hasBeenUsed flag prevents this from
46328
+ ** occurring on the very first access to a file, in order to save a
46329
+ ** single unnecessary sqlite3OsRead() call at the start-up.
4628246330
**
4628346331
** Database changes is detected by looking at 15 bytes beginning
4628446332
** at offset 24 into the file. The first 4 of these 16 bytes are
4628546333
** a 32-bit counter that is incremented with each change. The
4628646334
** other bytes change randomly with each file change when
@@ -46441,10 +46489,11 @@
4644146489
assert( noContent==0 || bMmapOk==0 );
4644246490
4644346491
if( pgno==0 ){
4644446492
return SQLITE_CORRUPT_BKPT;
4644546493
}
46494
+ pPager->hasBeenUsed = 1;
4644646495
4644746496
/* If the pager is in the error state, return an error immediately.
4644846497
** Otherwise, request the page from the PCache layer. */
4644946498
if( pPager->errCode!=SQLITE_OK ){
4645046499
rc = pPager->errCode;
@@ -46590,10 +46639,11 @@
4659046639
sqlite3_pcache_page *pPage;
4659146640
assert( pPager!=0 );
4659246641
assert( pgno!=0 );
4659346642
assert( pPager->pPCache!=0 );
4659446643
pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);
46644
+ assert( pPage==0 || pPager->hasBeenUsed );
4659546645
return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
4659646646
}
4659746647
4659846648
/*
4659946649
** Release a page reference.
@@ -47456,10 +47506,11 @@
4745647506
pPager->eState = PAGER_READER;
4745747507
return SQLITE_OK;
4745847508
}
4745947509
4746047510
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
47511
+ pPager->iDataVersion++;
4746147512
rc = pager_end_transaction(pPager, pPager->setMaster, 1);
4746247513
return pager_error(pPager, rc);
4746347514
}
4746447515
4746547516
/*
@@ -50825,11 +50876,11 @@
5082550876
}
5082650877
nCollide = HASHTABLE_NSLOT;
5082750878
for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
5082850879
u32 iFrame = aHash[iKey] + iZero;
5082950880
if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){
50830
- /* assert( iFrame>iRead ); -- not true if there is corruption */
50881
+ assert( iFrame>iRead || CORRUPT_DB );
5083150882
iRead = iFrame;
5083250883
}
5083350884
if( (nCollide--)==0 ){
5083450885
return SQLITE_CORRUPT_BKPT;
5083550886
}
@@ -51931,10 +51982,11 @@
5193151982
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
5193251983
u8 sharable; /* True if we can share pBt with another db */
5193351984
u8 locked; /* True if db currently has pBt locked */
5193451985
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
5193551986
int nBackup; /* Number of backup operations reading this btree */
51987
+ u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
5193651988
Btree *pNext; /* List of other sharable Btrees from the same db */
5193751989
Btree *pPrev; /* Back pointer of the same list */
5193851990
#ifndef SQLITE_OMIT_SHARED_CACHE
5193951991
BtLock lock; /* Object used to lock page 1 */
5194051992
#endif
@@ -56094,10 +56146,11 @@
5609456146
rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
5609556147
if( rc!=SQLITE_OK && bCleanup==0 ){
5609656148
sqlite3BtreeLeave(p);
5609756149
return rc;
5609856150
}
56151
+ p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
5609956152
pBt->inTransaction = TRANS_READ;
5610056153
btreeClearHasContent(pBt);
5610156154
}
5610256155
5610356156
btreeEndTransaction(p);
@@ -56457,11 +56510,11 @@
5645756510
}
5645856511
for(i=0; i<=pCur->iPage; i++){
5645956512
releasePage(pCur->apPage[i]);
5646056513
}
5646156514
unlockBtreeIfUnused(pBt);
56462
- sqlite3DbFree(pBtree->db, pCur->aOverflow);
56515
+ sqlite3_free(pCur->aOverflow);
5646356516
/* sqlite3_free(pCur); */
5646456517
sqlite3BtreeLeave(pBtree);
5646556518
}
5646656519
return SQLITE_OK;
5646756520
}
@@ -56751,10 +56804,11 @@
5675156804
pBuf += a;
5675256805
amt -= a;
5675356806
}else{
5675456807
offset -= pCur->info.nLocal;
5675556808
}
56809
+
5675656810
5675756811
if( rc==SQLITE_OK && amt>0 ){
5675856812
const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
5675956813
Pgno nextPage;
5676056814
@@ -56769,12 +56823,12 @@
5676956823
** means "not yet known" (the cache is lazily populated).
5677056824
*/
5677156825
if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
5677256826
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
5677356827
if( nOvfl>pCur->nOvflAlloc ){
56774
- Pgno *aNew = (Pgno*)sqlite3DbRealloc(
56775
- pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno)
56828
+ Pgno *aNew = (Pgno*)sqlite3Realloc(
56829
+ pCur->aOverflow, nOvfl*2*sizeof(Pgno)
5677656830
);
5677756831
if( aNew==0 ){
5677856832
rc = SQLITE_NOMEM;
5677956833
}else{
5678056834
pCur->nOvflAlloc = nOvfl*2;
@@ -56817,10 +56871,11 @@
5681756871
** Note that the aOverflow[] array must be allocated because eOp!=2
5681856872
** here. If eOp==2, then offset==0 and this branch is never taken.
5681956873
*/
5682056874
assert( eOp!=2 );
5682156875
assert( pCur->curFlags & BTCF_ValidOvfl );
56876
+ assert( pCur->pBtree->db==pBt->db );
5682256877
if( pCur->aOverflow[iIdx+1] ){
5682356878
nextPage = pCur->aOverflow[iIdx+1];
5682456879
}else{
5682556880
rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
5682656881
}
@@ -59329,11 +59384,11 @@
5932959384
+ nMaxCells*sizeof(u16) /* szCell */
5933059385
+ pBt->pageSize; /* aSpace1 */
5933159386
5933259387
/* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer
5933359388
** that is more than 6 times the database page size. */
59334
- assert( szScratch<=6*pBt->pageSize );
59389
+ assert( szScratch<=6*(int)pBt->pageSize );
5933559390
apCell = sqlite3ScratchMalloc( szScratch );
5933659391
if( apCell==0 ){
5933759392
rc = SQLITE_NOMEM;
5933859393
goto balance_cleanup;
5933959394
}
@@ -59406,12 +59461,12 @@
5940659461
assert( leafCorrection==4 );
5940759462
if( szCell[nCell]<4 ){
5940859463
/* Do not allow any cells smaller than 4 bytes. If a smaller cell
5940959464
** does exist, pad it with 0x00 bytes. */
5941059465
assert( szCell[nCell]==3 );
59411
- assert( apCell[nCell]==&pTemp[iSpace1-3] );
59412
- pTemp[iSpace1++] = 0x00;
59466
+ assert( apCell[nCell]==&aSpace1[iSpace1-3] );
59467
+ aSpace1[iSpace1++] = 0x00;
5941359468
szCell[nCell] = 4;
5941459469
}
5941559470
}
5941659471
nCell++;
5941759472
}
@@ -60719,10 +60774,17 @@
6071960774
** is read-only, the others are read/write.
6072060775
**
6072160776
** The schema layer numbers meta values differently. At the schema
6072260777
** layer (and the SetCookie and ReadCookie opcodes) the number of
6072360778
** free pages is not visible. So Cookie[0] is the same as Meta[1].
60779
+**
60780
+** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead
60781
+** of reading the value out of the header, it instead loads the "DataVersion"
60782
+** from the pager. The BTREE_DATA_VERSION value is not actually stored in the
60783
+** database file. It is a number computed by the pager. But its access
60784
+** pattern is the same as header meta values, and so it is convenient to
60785
+** read it from this routine.
6072460786
*/
6072560787
SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
6072660788
BtShared *pBt = p->pBt;
6072760789
6072860790
sqlite3BtreeEnter(p);
@@ -60729,11 +60791,15 @@
6072960791
assert( p->inTrans>TRANS_NONE );
6073060792
assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
6073160793
assert( pBt->pPage1 );
6073260794
assert( idx>=0 && idx<=15 );
6073360795
60734
- *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
60796
+ if( idx==BTREE_DATA_VERSION ){
60797
+ *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
60798
+ }else{
60799
+ *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
60800
+ }
6073560801
6073660802
/* If auto-vacuum is disabled in this build and this is an auto-vacuum
6073760803
** database, mark the database as read-only. */
6073860804
#ifdef SQLITE_OMIT_AUTOVACUUM
6073960805
if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
@@ -60820,11 +60886,11 @@
6082060886
if( pPage->leaf ){
6082160887
do {
6082260888
if( pCur->iPage==0 ){
6082360889
/* All pages of the b-tree have been visited. Return successfully. */
6082460890
*pnEntry = nEntry;
60825
- return SQLITE_OK;
60891
+ return moveToRoot(pCur);
6082660892
}
6082760893
moveToParent(pCur);
6082860894
}while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
6082960895
6083060896
pCur->aiIdx[pCur->iPage]++;
@@ -61676,11 +61742,11 @@
6167661742
}
6167761743
6167861744
/*
6167961745
** Return the size of the header added to each page by this module.
6168061746
*/
61681
-SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); }
61747
+SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
6168261748
6168361749
/************** End of btree.c ***********************************************/
6168461750
/************** Begin file backup.c ******************************************/
6168561751
/*
6168661752
** 2009 January 28
@@ -64440,36 +64506,39 @@
6444064506
**
6444164507
** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
6444264508
*/
6444364509
SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
6444464510
int hasAbort = 0;
64511
+ int hasFkCounter = 0;
6444564512
Op *pOp;
6444664513
VdbeOpIter sIter;
6444764514
memset(&sIter, 0, sizeof(sIter));
6444864515
sIter.v = v;
6444964516
6445064517
while( (pOp = opIterNext(&sIter))!=0 ){
6445164518
int opcode = pOp->opcode;
6445264519
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
64453
-#ifndef SQLITE_OMIT_FOREIGN_KEY
64454
- || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
64455
-#endif
6445664520
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
6445764521
&& ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
6445864522
){
6445964523
hasAbort = 1;
6446064524
break;
6446164525
}
64526
+#ifndef SQLITE_OMIT_FOREIGN_KEY
64527
+ if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
64528
+ hasFkCounter = 1;
64529
+ }
64530
+#endif
6446264531
}
6446364532
sqlite3DbFree(v->db, sIter.apSub);
6446464533
6446564534
/* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
6446664535
** If malloc failed, then the while() loop above may not have iterated
6446764536
** through all opcodes and hasAbort may be set incorrectly. Return
6446864537
** true for this case to prevent the assert() in the callers frame
6446964538
** from failing. */
64470
- return ( v->db->mallocFailed || hasAbort==mayAbort );
64539
+ return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter );
6447164540
}
6447264541
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
6447364542
6447464543
/*
6447564544
** Loop through the program looking for P2 values that are negative
@@ -68589,11 +68658,14 @@
6858968658
#ifndef SQLITE_OMIT_WAL
6859068659
int i;
6859168660
for(i=0; i<db->nDb; i++){
6859268661
Btree *pBt = db->aDb[i].pBt;
6859368662
if( pBt ){
68594
- int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
68663
+ int nEntry;
68664
+ sqlite3BtreeEnter(pBt);
68665
+ nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
68666
+ sqlite3BtreeLeave(pBt);
6859568667
if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
6859668668
rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
6859768669
}
6859868670
}
6859968671
}
@@ -68769,11 +68841,10 @@
6876968841
** program counter to 0 to ensure that when the statement is
6877068842
** finalized or reset the parser error message is available via
6877168843
** sqlite3_errmsg() and sqlite3_errcode().
6877268844
*/
6877368845
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
68774
- assert( zErr!=0 || db->mallocFailed );
6877568846
sqlite3DbFree(db, v->zErrMsg);
6877668847
if( !db->mallocFailed ){
6877768848
v->zErrMsg = sqlite3DbStrDup(db, zErr);
6877868849
v->rc = rc2;
6877968850
} else {
@@ -77131,11 +77202,11 @@
7713177202
/*
7713277203
** Hard-coded maximum amount of data to accumulate in memory before flushing
7713377204
** to a level 0 PMA. The purpose of this limit is to prevent various integer
7713477205
** overflows. 512MiB.
7713577206
*/
77136
-#define SQLITE_MAX_MXPMASIZE (1<<29)
77207
+#define SQLITE_MAX_PMASZ (1<<29)
7713777208
7713877209
/*
7713977210
** Private objects used by the sorter
7714077211
*/
7714177212
typedef struct MergeEngine MergeEngine; /* Merge PMAs together */
@@ -77427,13 +77498,10 @@
7742777498
**
7742877499
** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; }
7742977500
*/
7743077501
#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1))
7743177502
77432
-/* The minimum PMA size is set to this value multiplied by the database
77433
-** page size in bytes. */
77434
-#define SORTER_MIN_WORKING 10
7743577503
7743677504
/* Maximum number of PMAs that a single MergeEngine can merge */
7743777505
#define SORTER_MAX_MERGE_COUNT 16
7743877506
7743977507
static int vdbeIncrSwap(IncrMerger*);
@@ -77828,14 +77896,15 @@
7782877896
SortSubtask *pTask = &pSorter->aTask[i];
7782977897
pTask->pSorter = pSorter;
7783077898
}
7783177899
7783277900
if( !sqlite3TempInMemory(db) ){
77833
- pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
77901
+ u32 szPma = sqlite3GlobalConfig.szPma;
77902
+ pSorter->mnPmaSize = szPma * pgsz;
7783477903
mxCache = db->aDb[0].pSchema->cache_size;
77835
- if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
77836
- pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_MXPMASIZE);
77904
+ if( mxCache<(int)szPma ) mxCache = (int)szPma;
77905
+ pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);
7783777906
7783877907
/* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
7783977908
** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
7784077909
** large heap allocations.
7784177910
*/
@@ -78109,16 +78178,16 @@
7810978178
** Whether or not the file does end up memory mapped of course depends on
7811078179
** the specific VFS implementation.
7811178180
*/
7811278181
static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
7811378182
if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
78114
- int rc = sqlite3OsTruncate(pFd, nByte);
78115
- if( rc==SQLITE_OK ){
78116
- void *p = 0;
78117
- sqlite3OsFetch(pFd, 0, (int)nByte, &p);
78118
- sqlite3OsUnfetch(pFd, 0, p);
78119
- }
78183
+ void *p = 0;
78184
+ int chunksize = 4*1024;
78185
+ sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
78186
+ sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
78187
+ sqlite3OsFetch(pFd, 0, (int)nByte, &p);
78188
+ sqlite3OsUnfetch(pFd, 0, p);
7812078189
}
7812178190
}
7812278191
#else
7812378192
# define vdbeSorterExtendFile(x,y,z)
7812478193
#endif
@@ -87296,11 +87365,11 @@
8729687365
8729787366
p->iGet = -1;
8729887367
p->mxSample = mxSample;
8729987368
p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
8730087369
p->current.anLt = &p->current.anEq[nColUp];
87301
- p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565;
87370
+ p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
8730287371
8730387372
/* Set up the Stat4Accum.a[] and aBest[] arrays */
8730487373
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
8730587374
p->aBest = &p->a[mxSample];
8730687375
pSpace = (u8*)(&p->a[mxSample+nCol]);
@@ -88889,17 +88958,19 @@
8888988958
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
8889088959
zErrDyn = sqlite3MPrintf(db,
8889188960
"attached databases must use the same text encoding as main database");
8889288961
rc = SQLITE_ERROR;
8889388962
}
88963
+ sqlite3BtreeEnter(aNew->pBt);
8889488964
pPager = sqlite3BtreePager(aNew->pBt);
8889588965
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
8889688966
sqlite3BtreeSecureDelete(aNew->pBt,
8889788967
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
8889888968
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
8889988969
sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
8890088970
#endif
88971
+ sqlite3BtreeLeave(aNew->pBt);
8890188972
}
8890288973
aNew->safety_level = 3;
8890388974
aNew->zName = sqlite3DbStrDup(db, zName);
8890488975
if( rc==SQLITE_OK && aNew->zName==0 ){
8890588976
rc = SQLITE_NOMEM;
@@ -90021,11 +90092,10 @@
9002190092
*/
9002290093
static void freeIndex(sqlite3 *db, Index *p){
9002390094
#ifndef SQLITE_OMIT_ANALYZE
9002490095
sqlite3DeleteIndexSamples(db, p);
9002590096
#endif
90026
- if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo);
9002790097
sqlite3ExprDelete(db, p->pPartIdxWhere);
9002890098
sqlite3DbFree(db, p->zColAff);
9002990099
if( p->isResized ) sqlite3DbFree(db, p->azColl);
9003090100
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
9003190101
sqlite3_free(p->aiRowEst);
@@ -91300,10 +91370,23 @@
9130091370
if( pPk==0 ) return;
9130191371
pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
9130291372
pTab->iPKey = -1;
9130391373
}else{
9130491374
pPk = sqlite3PrimaryKeyIndex(pTab);
91375
+ /*
91376
+ ** Remove all redundant columns from the PRIMARY KEY. For example, change
91377
+ ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
91378
+ ** code assumes the PRIMARY KEY contains no repeated columns.
91379
+ */
91380
+ for(i=j=1; i<pPk->nKeyCol; i++){
91381
+ if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){
91382
+ pPk->nColumn--;
91383
+ }else{
91384
+ pPk->aiColumn[j++] = pPk->aiColumn[i];
91385
+ }
91386
+ }
91387
+ pPk->nKeyCol = j;
9130591388
}
9130691389
pPk->isCovering = 1;
9130791390
assert( pPk!=0 );
9130891391
nPk = pPk->nKeyCol;
9130991392
@@ -93776,44 +93859,35 @@
9377693859
**
9377793860
** The caller should invoke sqlite3KeyInfoUnref() on the returned object
9377893861
** when it has finished using it.
9377993862
*/
9378093863
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
93864
+ int i;
93865
+ int nCol = pIdx->nColumn;
93866
+ int nKey = pIdx->nKeyCol;
93867
+ KeyInfo *pKey;
9378193868
if( pParse->nErr ) return 0;
93782
-#ifndef SQLITE_OMIT_SHARED_CACHE
93783
- if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){
93784
- sqlite3KeyInfoUnref(pIdx->pKeyInfo);
93785
- pIdx->pKeyInfo = 0;
93786
- }
93787
-#endif
93788
- if( pIdx->pKeyInfo==0 ){
93789
- int i;
93790
- int nCol = pIdx->nColumn;
93791
- int nKey = pIdx->nKeyCol;
93792
- KeyInfo *pKey;
93793
- if( pIdx->uniqNotNull ){
93794
- pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
93795
- }else{
93796
- pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
93797
- }
93798
- if( pKey ){
93799
- assert( sqlite3KeyInfoIsWriteable(pKey) );
93800
- for(i=0; i<nCol; i++){
93801
- char *zColl = pIdx->azColl[i];
93802
- assert( zColl!=0 );
93803
- pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
93804
- sqlite3LocateCollSeq(pParse, zColl);
93805
- pKey->aSortOrder[i] = pIdx->aSortOrder[i];
93806
- }
93807
- if( pParse->nErr ){
93808
- sqlite3KeyInfoUnref(pKey);
93809
- }else{
93810
- pIdx->pKeyInfo = pKey;
93811
- }
93812
- }
93813
- }
93814
- return sqlite3KeyInfoRef(pIdx->pKeyInfo);
93869
+ if( pIdx->uniqNotNull ){
93870
+ pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
93871
+ }else{
93872
+ pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
93873
+ }
93874
+ if( pKey ){
93875
+ assert( sqlite3KeyInfoIsWriteable(pKey) );
93876
+ for(i=0; i<nCol; i++){
93877
+ char *zColl = pIdx->azColl[i];
93878
+ assert( zColl!=0 );
93879
+ pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
93880
+ sqlite3LocateCollSeq(pParse, zColl);
93881
+ pKey->aSortOrder[i] = pIdx->aSortOrder[i];
93882
+ }
93883
+ if( pParse->nErr ){
93884
+ sqlite3KeyInfoUnref(pKey);
93885
+ pKey = 0;
93886
+ }
93887
+ }
93888
+ return pKey;
9381593889
}
9381693890
9381793891
#ifndef SQLITE_OMIT_CTE
9381893892
/*
9381993893
** This routine is invoked once per CTE by the parser while parsing a
@@ -97430,11 +97504,11 @@
9743097504
assert( nIncr==1 );
9743197505
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
9743297506
OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
9743397507
}else{
9743497508
if( nIncr>0 && pFKey->isDeferred==0 ){
97435
- sqlite3ParseToplevel(pParse)->mayAbort = 1;
97509
+ sqlite3MayAbort(pParse);
9743697510
}
9743797511
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
9743897512
}
9743997513
9744097514
sqlite3VdbeResolveLabel(v, iOk);
@@ -97501,10 +97575,14 @@
9750197575
** This function is called to generate code executed when a row is deleted
9750297576
** from the parent table of foreign key constraint pFKey and, if pFKey is
9750397577
** deferred, when a row is inserted into the same table. When generating
9750497578
** code for an SQL UPDATE operation, this function may be called twice -
9750597579
** once to "delete" the old row and once to "insert" the new row.
97580
+**
97581
+** Parameter nIncr is passed -1 when inserting a row (as this may decrease
97582
+** the number of FK violations in the db) or +1 when deleting one (as this
97583
+** may increase the number of FK constraint problems).
9750697584
**
9750797585
** The code generated by this function scans through the rows in the child
9750897586
** table that correspond to the parent table row being deleted or inserted.
9750997587
** For each child row found, one of the following actions is taken:
9751097588
**
@@ -97618,17 +97696,13 @@
9761897696
sNameContext.pSrcList = pSrc;
9761997697
sNameContext.pParse = pParse;
9762097698
sqlite3ResolveExprNames(&sNameContext, pWhere);
9762197699
9762297700
/* Create VDBE to loop through the entries in pSrc that match the WHERE
97623
- ** clause. If the constraint is not deferred, throw an exception for
97624
- ** each row found. Otherwise, for deferred constraints, increment the
97625
- ** deferred constraint counter by nIncr for each row selected. */
97701
+ ** clause. For each row found, increment either the deferred or immediate
97702
+ ** foreign key constraint counter. */
9762697703
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
97627
- if( nIncr>0 && pFKey->isDeferred==0 ){
97628
- sqlite3ParseToplevel(pParse)->mayAbort = 1;
97629
- }
9763097704
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
9763197705
if( pWInfo ){
9763297706
sqlite3WhereEnd(pWInfo);
9763397707
}
9763497708
@@ -97802,10 +97876,28 @@
9780297876
}
9780397877
}
9780497878
}
9780597879
return 0;
9780697880
}
97881
+
97882
+/*
97883
+** Return true if the parser passed as the first argument is being
97884
+** used to code a trigger that is really a "SET NULL" action belonging
97885
+** to trigger pFKey.
97886
+*/
97887
+static int isSetNullAction(Parse *pParse, FKey *pFKey){
97888
+ Parse *pTop = sqlite3ParseToplevel(pParse);
97889
+ if( pTop->pTriggerPrg ){
97890
+ Trigger *p = pTop->pTriggerPrg->pTrigger;
97891
+ if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull)
97892
+ || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull)
97893
+ ){
97894
+ return 1;
97895
+ }
97896
+ }
97897
+ return 0;
97898
+}
9780797899
9780897900
/*
9780997901
** This function is called when inserting, deleting or updating a row of
9781097902
** table pTab to generate VDBE code to perform foreign key constraint
9781197903
** processing for the operation.
@@ -97855,11 +97947,11 @@
9785597947
Index *pIdx = 0; /* Index on key columns in pTo */
9785697948
int *aiFree = 0;
9785797949
int *aiCol;
9785897950
int iCol;
9785997951
int i;
97860
- int isIgnore = 0;
97952
+ int bIgnore = 0;
9786197953
9786297954
if( aChange
9786397955
&& sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
9786497956
&& fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0
9786597957
){
@@ -97914,11 +98006,11 @@
9791498006
** values read from the parent table are NULL. */
9791598007
if( db->xAuth ){
9791698008
int rcauth;
9791798009
char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
9791898010
rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
97919
- isIgnore = (rcauth==SQLITE_IGNORE);
98011
+ bIgnore = (rcauth==SQLITE_IGNORE);
9792098012
}
9792198013
#endif
9792298014
}
9792398015
9792498016
/* Take a shared-cache advisory read-lock on the parent table. Allocate
@@ -97929,16 +98021,22 @@
9792998021
9793098022
if( regOld!=0 ){
9793198023
/* A row is being removed from the child table. Search for the parent.
9793298024
** If the parent does not exist, removing the child row resolves an
9793398025
** outstanding foreign key constraint violation. */
97934
- fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
98026
+ fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore);
9793598027
}
97936
- if( regNew!=0 ){
98028
+ if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){
9793798029
/* A row is being added to the child table. If a parent row cannot
97938
- ** be found, adding the child row has violated the FK constraint. */
97939
- fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
98030
+ ** be found, adding the child row has violated the FK constraint.
98031
+ **
98032
+ ** If this operation is being performed as part of a trigger program
98033
+ ** that is actually a "SET NULL" action belonging to this very
98034
+ ** foreign key, then omit this scan altogether. As all child key
98035
+ ** values are guaranteed to be NULL, it is not possible for adding
98036
+ ** this row to cause an FK violation. */
98037
+ fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore);
9794098038
}
9794198039
9794298040
sqlite3DbFree(db, aiFree);
9794398041
}
9794498042
@@ -97955,12 +98053,12 @@
9795598053
9795698054
if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs)
9795798055
&& !pParse->pToplevel && !pParse->isMultiWrite
9795898056
){
9795998057
assert( regOld==0 && regNew!=0 );
97960
- /* Inserting a single row into a parent table cannot cause an immediate
97961
- ** foreign key violation. So do nothing in this case. */
98058
+ /* Inserting a single row into a parent table cannot cause (or fix)
98059
+ ** an immediate foreign key violation. So do nothing in this case. */
9796298060
continue;
9796398061
}
9796498062
9796598063
if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
9796698064
if( !isIgnoreErrors || db->mallocFailed ) return;
@@ -97980,17 +98078,32 @@
9798098078
9798198079
if( regNew!=0 ){
9798298080
fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
9798398081
}
9798498082
if( regOld!=0 ){
97985
- /* If there is a RESTRICT action configured for the current operation
97986
- ** on the parent table of this FK, then throw an exception
97987
- ** immediately if the FK constraint is violated, even if this is a
97988
- ** deferred trigger. That's what RESTRICT means. To defer checking
97989
- ** the constraint, the FK should specify NO ACTION (represented
97990
- ** using OE_None). NO ACTION is the default. */
98083
+ int eAction = pFKey->aAction[aChange!=0];
9799198084
fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);
98085
+ /* If this is a deferred FK constraint, or a CASCADE or SET NULL
98086
+ ** action applies, then any foreign key violations caused by
98087
+ ** removing the parent key will be rectified by the action trigger.
98088
+ ** So do not set the "may-abort" flag in this case.
98089
+ **
98090
+ ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the
98091
+ ** may-abort flag will eventually be set on this statement anyway
98092
+ ** (when this function is called as part of processing the UPDATE
98093
+ ** within the action trigger).
98094
+ **
98095
+ ** Note 2: At first glance it may seem like SQLite could simply omit
98096
+ ** all OP_FkCounter related scans when either CASCADE or SET NULL
98097
+ ** applies. The trouble starts if the CASCADE or SET NULL action
98098
+ ** trigger causes other triggers or action rules attached to the
98099
+ ** child table to fire. In these cases the fk constraint counters
98100
+ ** might be set incorrectly if any OP_FkCounter related scans are
98101
+ ** omitted. */
98102
+ if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){
98103
+ sqlite3MayAbort(pParse);
98104
+ }
9799298105
}
9799398106
pItem->zName = 0;
9799498107
sqlite3SrcListDelete(db, pSrc);
9799598108
}
9799698109
sqlite3DbFree(db, aiCol);
@@ -101080,11 +101193,10 @@
101080101193
# define sqlite3_column_database_name16 0
101081101194
# define sqlite3_column_table_name 0
101082101195
# define sqlite3_column_table_name16 0
101083101196
# define sqlite3_column_origin_name 0
101084101197
# define sqlite3_column_origin_name16 0
101085
-# define sqlite3_table_column_metadata 0
101086101198
#endif
101087101199
101088101200
#ifdef SQLITE_OMIT_AUTHORIZATION
101089101201
# define sqlite3_set_authorizer 0
101090101202
#endif
@@ -101890,10 +102002,11 @@
101890102002
#define PragTyp_KEY 38
101891102003
#define PragTyp_REKEY 39
101892102004
#define PragTyp_LOCK_STATUS 40
101893102005
#define PragTyp_PARSER_TRACE 41
101894102006
#define PragFlag_NeedSchema 0x01
102007
+#define PragFlag_ReadOnly 0x02
101895102008
static const struct sPragmaNames {
101896102009
const char *const zName; /* Name of pragma */
101897102010
u8 ePragTyp; /* PragTyp_XXX value */
101898102011
u8 mPragFlag; /* Zero or more PragFlag_XXX values */
101899102012
u32 iArg; /* Extra argument */
@@ -101906,11 +102019,11 @@
101906102019
#endif
101907102020
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
101908102021
{ /* zName: */ "application_id",
101909102022
/* ePragTyp: */ PragTyp_HEADER_VALUE,
101910102023
/* ePragFlag: */ 0,
101911
- /* iArg: */ 0 },
102024
+ /* iArg: */ BTREE_APPLICATION_ID },
101912102025
#endif
101913102026
#if !defined(SQLITE_OMIT_AUTOVACUUM)
101914102027
{ /* zName: */ "auto_vacuum",
101915102028
/* ePragTyp: */ PragTyp_AUTO_VACUUM,
101916102029
/* ePragFlag: */ PragFlag_NeedSchema,
@@ -101972,10 +102085,16 @@
101972102085
{ /* zName: */ "data_store_directory",
101973102086
/* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
101974102087
/* ePragFlag: */ 0,
101975102088
/* iArg: */ 0 },
101976102089
#endif
102090
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102091
+ { /* zName: */ "data_version",
102092
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
102093
+ /* ePragFlag: */ PragFlag_ReadOnly,
102094
+ /* iArg: */ BTREE_DATA_VERSION },
102095
+#endif
101977102096
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
101978102097
{ /* zName: */ "database_list",
101979102098
/* ePragTyp: */ PragTyp_DATABASE_LIST,
101980102099
/* ePragFlag: */ PragFlag_NeedSchema,
101981102100
/* iArg: */ 0 },
@@ -102027,12 +102146,12 @@
102027102146
#endif
102028102147
#endif
102029102148
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102030102149
{ /* zName: */ "freelist_count",
102031102150
/* ePragTyp: */ PragTyp_HEADER_VALUE,
102032
- /* ePragFlag: */ 0,
102033
- /* iArg: */ 0 },
102151
+ /* ePragFlag: */ PragFlag_ReadOnly,
102152
+ /* iArg: */ BTREE_FREE_PAGE_COUNT },
102034102153
#endif
102035102154
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
102036102155
{ /* zName: */ "full_column_names",
102037102156
/* ePragTyp: */ PragTyp_FLAG,
102038102157
/* ePragFlag: */ 0,
@@ -102180,11 +102299,11 @@
102180102299
#endif
102181102300
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102182102301
{ /* zName: */ "schema_version",
102183102302
/* ePragTyp: */ PragTyp_HEADER_VALUE,
102184102303
/* ePragFlag: */ 0,
102185
- /* iArg: */ 0 },
102304
+ /* iArg: */ BTREE_SCHEMA_VERSION },
102186102305
#endif
102187102306
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
102188102307
{ /* zName: */ "secure_delete",
102189102308
/* ePragTyp: */ PragTyp_SECURE_DELETE,
102190102309
/* ePragFlag: */ 0,
@@ -102246,11 +102365,11 @@
102246102365
/* iArg: */ 0 },
102247102366
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102248102367
{ /* zName: */ "user_version",
102249102368
/* ePragTyp: */ PragTyp_HEADER_VALUE,
102250102369
/* ePragFlag: */ 0,
102251
- /* iArg: */ 0 },
102370
+ /* iArg: */ BTREE_USER_VERSION },
102252102371
#endif
102253102372
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
102254102373
#if defined(SQLITE_DEBUG)
102255102374
{ /* zName: */ "vdbe_addoptrace",
102256102375
/* ePragTyp: */ PragTyp_FLAG,
@@ -102289,11 +102408,11 @@
102289102408
/* ePragTyp: */ PragTyp_FLAG,
102290102409
/* ePragFlag: */ 0,
102291102410
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
102292102411
#endif
102293102412
};
102294
-/* Number of pragmas: 57 on by default, 70 total. */
102413
+/* Number of pragmas: 58 on by default, 71 total. */
102295102414
/* End of the automatically generated pragma table.
102296102415
***************************************************************************/
102297102416
102298102417
/*
102299102418
** Interpret the given string as a safety level. Return 0 for OFF,
@@ -103899,11 +104018,12 @@
103899104018
!(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
103900104019
DbHasProperty(db, 0, DB_Empty)
103901104020
){
103902104021
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
103903104022
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
103904
- ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
104023
+ SCHEMA_ENC(db) = ENC(db) =
104024
+ pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
103905104025
break;
103906104026
}
103907104027
}
103908104028
if( !pEnc->zName ){
103909104029
sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight);
@@ -103944,28 +104064,13 @@
103944104064
**
103945104065
** The user-version is not used internally by SQLite. It may be used by
103946104066
** applications for any purpose.
103947104067
*/
103948104068
case PragTyp_HEADER_VALUE: {
103949
- int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
104069
+ int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */
103950104070
sqlite3VdbeUsesBtree(v, iDb);
103951
- switch( zLeft[0] ){
103952
- case 'a': case 'A':
103953
- iCookie = BTREE_APPLICATION_ID;
103954
- break;
103955
- case 'f': case 'F':
103956
- iCookie = BTREE_FREE_PAGE_COUNT;
103957
- break;
103958
- case 's': case 'S':
103959
- iCookie = BTREE_SCHEMA_VERSION;
103960
- break;
103961
- default:
103962
- iCookie = BTREE_USER_VERSION;
103963
- break;
103964
- }
103965
-
103966
- if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){
104071
+ if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){
103967104072
/* Write the specified cookie value */
103968104073
static const VdbeOpList setCookie[] = {
103969104074
{ OP_Transaction, 0, 1, 0}, /* 0 */
103970104075
{ OP_Integer, 0, 1, 0}, /* 1 */
103971104076
{ OP_SetCookie, 0, 0, 1}, /* 2 */
@@ -104607,13 +104712,15 @@
104607104712
SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
104608104713
int i, rc;
104609104714
int commit_internal = !(db->flags&SQLITE_InternChanges);
104610104715
104611104716
assert( sqlite3_mutex_held(db->mutex) );
104717
+ assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
104612104718
assert( db->init.busy==0 );
104613104719
rc = SQLITE_OK;
104614104720
db->init.busy = 1;
104721
+ ENC(db) = SCHEMA_ENC(db);
104615104722
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
104616104723
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
104617104724
rc = sqlite3InitOne(db, i, pzErrMsg);
104618104725
if( rc ){
104619104726
sqlite3ResetOneSchema(db, i);
@@ -110751,11 +110858,11 @@
110751110858
){
110752110859
int rc;
110753110860
TabResult res;
110754110861
110755110862
#ifdef SQLITE_ENABLE_API_ARMOR
110756
- if( pazResult==0 ) return SQLITE_MISUSE_BKPT;
110863
+ if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT;
110757110864
#endif
110758110865
*pazResult = 0;
110759110866
if( pnColumn ) *pnColumn = 0;
110760110867
if( pnRow ) *pnRow = 0;
110761110868
if( pzErrMsg ) *pzErrMsg = 0;
@@ -118621,11 +118728,10 @@
118621118728
sqlite3_free(p->u.vtab.idxStr);
118622118729
p->u.vtab.needFree = 0;
118623118730
p->u.vtab.idxStr = 0;
118624118731
}else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
118625118732
sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
118626
- sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo);
118627118733
sqlite3DbFree(db, p->u.btree.pIndex);
118628118734
p->u.btree.pIndex = 0;
118629118735
}
118630118736
}
118631118737
}
@@ -125628,10 +125734,13 @@
125628125734
u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */
125629125735
sqlite3 *db = pParse->db; /* The database connection */
125630125736
int mxSqlLen; /* Max length of an SQL string */
125631125737
125632125738
125739
+#ifdef SQLITE_ENABLE_API_ARMOR
125740
+ if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT;
125741
+#endif
125633125742
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
125634125743
if( db->nVdbeActive==0 ){
125635125744
db->u1.isInterrupted = 0;
125636125745
}
125637125746
pParse->rc = SQLITE_OK;
@@ -125866,17 +125975,10 @@
125866125975
*/
125867125976
SQLITE_API int sqlite3_complete(const char *zSql){
125868125977
u8 state = 0; /* Current state, using numbers defined in header comment */
125869125978
u8 token; /* Value of the next token */
125870125979
125871
-#ifdef SQLITE_ENABLE_API_ARMOR
125872
- if( zSql==0 ){
125873
- (void)SQLITE_MISUSE_BKPT;
125874
- return 0;
125875
- }
125876
-#endif
125877
-
125878125980
#ifndef SQLITE_OMIT_TRIGGER
125879125981
/* A complex statement machine used to detect the end of a CREATE TRIGGER
125880125982
** statement. This is the normal case.
125881125983
*/
125882125984
static const u8 trans[8][8] = {
@@ -125901,10 +126003,17 @@
125901126003
/* 0 INVALID: */ { 1, 0, 2, },
125902126004
/* 1 START: */ { 1, 1, 2, },
125903126005
/* 2 NORMAL: */ { 1, 2, 2, },
125904126006
};
125905126007
#endif /* SQLITE_OMIT_TRIGGER */
126008
+
126009
+#ifdef SQLITE_ENABLE_API_ARMOR
126010
+ if( zSql==0 ){
126011
+ (void)SQLITE_MISUSE_BKPT;
126012
+ return 0;
126013
+ }
126014
+#endif
125906126015
125907126016
while( *zSql ){
125908126017
switch( *zSql ){
125909126018
case ';': { /* A semicolon */
125910126019
token = tkSEMI;
@@ -126203,11 +126312,11 @@
126203126312
** If the following function pointer is not NULL and if
126204126313
** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
126205126314
** I/O active are written using this function. These messages
126206126315
** are intended for debugging activity only.
126207126316
*/
126208
-SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0;
126317
+/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0;
126209126318
#endif
126210126319
126211126320
/*
126212126321
** If the following global variable points to a string which is the
126213126322
** name of a directory, then that directory will be used to store
@@ -126412,10 +126521,17 @@
126412126521
** routine is not threadsafe. But it is safe to invoke this routine
126413126522
** on when SQLite is already shut down. If SQLite is already shut down
126414126523
** when this routine is invoked, then this routine is a harmless no-op.
126415126524
*/
126416126525
SQLITE_API int sqlite3_shutdown(void){
126526
+#ifdef SQLITE_OMIT_WSD
126527
+ int rc = sqlite3_wsd_init(4096, 24);
126528
+ if( rc!=SQLITE_OK ){
126529
+ return rc;
126530
+ }
126531
+#endif
126532
+
126417126533
if( sqlite3GlobalConfig.isInit ){
126418126534
#ifdef SQLITE_EXTRA_SHUTDOWN
126419126535
void SQLITE_EXTRA_SHUTDOWN(void);
126420126536
SQLITE_EXTRA_SHUTDOWN();
126421126537
#endif
@@ -126727,10 +126843,15 @@
126727126843
** heap. */
126728126844
sqlite3GlobalConfig.nHeap = va_arg(ap, int);
126729126845
break;
126730126846
}
126731126847
#endif
126848
+
126849
+ case SQLITE_CONFIG_PMASZ: {
126850
+ sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int);
126851
+ break;
126852
+ }
126732126853
126733126854
default: {
126734126855
rc = SQLITE_ERROR;
126735126856
break;
126736126857
}
@@ -127173,18 +127294,10 @@
127173127294
127174127295
/* Close all database connections */
127175127296
for(j=0; j<db->nDb; j++){
127176127297
struct Db *pDb = &db->aDb[j];
127177127298
if( pDb->pBt ){
127178
- if( pDb->pSchema ){
127179
- /* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */
127180
- for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){
127181
- Index *pIdx = sqliteHashData(i);
127182
- sqlite3KeyInfoUnref(pIdx->pKeyInfo);
127183
- pIdx->pKeyInfo = 0;
127184
- }
127185
- }
127186127299
sqlite3BtreeClose(pDb->pBt);
127187127300
pDb->pBt = 0;
127188127301
if( j!=1 ){
127189127302
pDb->pSchema = 0;
127190127303
}
@@ -128308,36 +128421,10 @@
128308128421
*/
128309128422
SQLITE_API const char *sqlite3_errstr(int rc){
128310128423
return sqlite3ErrStr(rc);
128311128424
}
128312128425
128313
-/*
128314
-** Invalidate all cached KeyInfo objects for database connection "db"
128315
-*/
128316
-static void invalidateCachedKeyInfo(sqlite3 *db){
128317
- Db *pDb; /* A single database */
128318
- int iDb; /* The database index number */
128319
- HashElem *k; /* For looping over tables in pDb */
128320
- Table *pTab; /* A table in the database */
128321
- Index *pIdx; /* Each index */
128322
-
128323
- for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
128324
- if( pDb->pBt==0 ) continue;
128325
- sqlite3BtreeEnter(pDb->pBt);
128326
- for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
128327
- pTab = (Table*)sqliteHashData(k);
128328
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
128329
- if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){
128330
- sqlite3KeyInfoUnref(pIdx->pKeyInfo);
128331
- pIdx->pKeyInfo = 0;
128332
- }
128333
- }
128334
- }
128335
- sqlite3BtreeLeave(pDb->pBt);
128336
- }
128337
-}
128338
-
128339128426
/*
128340128427
** Create a new collating function for database "db". The name is zName
128341128428
** and the encoding is enc.
128342128429
*/
128343128430
static int createCollation(
@@ -128377,11 +128464,10 @@
128377128464
sqlite3ErrorWithMsg(db, SQLITE_BUSY,
128378128465
"unable to delete/modify collation sequence due to active statements");
128379128466
return SQLITE_BUSY;
128380128467
}
128381128468
sqlite3ExpirePreparedStatements(db);
128382
- invalidateCachedKeyInfo(db);
128383128469
128384128470
/* If collation sequence pColl was created directly by a call to
128385128471
** sqlite3_create_collation, and not generated by synthCollSeq(),
128386128472
** then any copies made by synthCollSeq() need to be invalidated.
128387128473
** Also, collation destructor - CollSeq.xDel() - function may need
@@ -128882,10 +128968,13 @@
128882128968
| SQLITE_RecTriggers
128883128969
#endif
128884128970
#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS
128885128971
| SQLITE_ForeignKeys
128886128972
#endif
128973
+#if defined(SQLITE_REVERSE_UNORDERED_SELECTS)
128974
+ | SQLITE_ReverseOrder
128975
+#endif
128887128976
;
128888128977
sqlite3HashInit(&db->aCollSeq);
128889128978
#ifndef SQLITE_OMIT_VIRTUALTABLE
128890128979
sqlite3HashInit(&db->aModule);
128891128980
#endif
@@ -128929,11 +129018,14 @@
128929129018
rc = SQLITE_NOMEM;
128930129019
}
128931129020
sqlite3Error(db, rc);
128932129021
goto opendb_out;
128933129022
}
129023
+ sqlite3BtreeEnter(db->aDb[0].pBt);
128934129024
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
129025
+ if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db);
129026
+ sqlite3BtreeLeave(db->aDb[0].pBt);
128935129027
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
128936129028
128937129029
/* The default safety_level for the main database is 'full'; for the temp
128938129030
** database it is 'NONE'. This matches the pager layer defaults.
128939129031
*/
@@ -129087,11 +129179,11 @@
129087129179
if( zFilename8 ){
129088129180
rc = openDatabase(zFilename8, ppDb,
129089129181
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
129090129182
assert( *ppDb || rc==SQLITE_NOMEM );
129091129183
if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
129092
- ENC(*ppDb) = SQLITE_UTF16NATIVE;
129184
+ SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE;
129093129185
}
129094129186
}else{
129095129187
rc = SQLITE_NOMEM;
129096129188
}
129097129189
sqlite3ValueFree(pVal);
@@ -129283,11 +129375,10 @@
129283129375
129284129376
/*
129285129377
** Return meta information about a specific column of a database table.
129286129378
** See comment in sqlite3.h (sqlite.h.in) for details.
129287129379
*/
129288
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
129289129380
SQLITE_API int sqlite3_table_column_metadata(
129290129381
sqlite3 *db, /* Connection handle */
129291129382
const char *zDbName, /* Database name or NULL */
129292129383
const char *zTableName, /* Table name */
129293129384
const char *zColumnName, /* Column name */
@@ -129323,25 +129414,27 @@
129323129414
pTab = 0;
129324129415
goto error_out;
129325129416
}
129326129417
129327129418
/* Find the column for which info is requested */
129328
- if( sqlite3IsRowid(zColumnName) ){
129329
- iCol = pTab->iPKey;
129330
- if( iCol>=0 ){
129331
- pCol = &pTab->aCol[iCol];
129332
- }
129419
+ if( zColumnName==0 ){
129420
+ /* Query for existance of table only */
129333129421
}else{
129334129422
for(iCol=0; iCol<pTab->nCol; iCol++){
129335129423
pCol = &pTab->aCol[iCol];
129336129424
if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
129337129425
break;
129338129426
}
129339129427
}
129340129428
if( iCol==pTab->nCol ){
129341
- pTab = 0;
129342
- goto error_out;
129429
+ if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
129430
+ iCol = pTab->iPKey;
129431
+ pCol = iCol>=0 ? &pTab->aCol[iCol] : 0;
129432
+ }else{
129433
+ pTab = 0;
129434
+ goto error_out;
129435
+ }
129343129436
}
129344129437
}
129345129438
129346129439
/* The following block stores the meta information that will be returned
129347129440
** to the caller in local variables zDataType, zCollSeq, notnull, primarykey
@@ -129390,11 +129483,10 @@
129390129483
sqlite3DbFree(db, zErrMsg);
129391129484
rc = sqlite3ApiExit(db, rc);
129392129485
sqlite3_mutex_leave(db->mutex);
129393129486
return rc;
129394129487
}
129395
-#endif
129396129488
129397129489
/*
129398129490
** Sleep for a little while. Return the amount of time slept.
129399129491
*/
129400129492
SQLITE_API int sqlite3_sleep(int ms){
@@ -129829,32 +129921,34 @@
129829129921
/*
129830129922
** Return the filename of the database associated with a database
129831129923
** connection.
129832129924
*/
129833129925
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
129926
+ Btree *pBt;
129834129927
#ifdef SQLITE_ENABLE_API_ARMOR
129835129928
if( !sqlite3SafetyCheckOk(db) ){
129836129929
(void)SQLITE_MISUSE_BKPT;
129837129930
return 0;
129838129931
}
129839129932
#endif
129840
- Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
129933
+ pBt = sqlite3DbNameToBtree(db, zDbName);
129841129934
return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
129842129935
}
129843129936
129844129937
/*
129845129938
** Return 1 if database is read-only or 0 if read/write. Return -1 if
129846129939
** no such database exists.
129847129940
*/
129848129941
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
129942
+ Btree *pBt;
129849129943
#ifdef SQLITE_ENABLE_API_ARMOR
129850129944
if( !sqlite3SafetyCheckOk(db) ){
129851129945
(void)SQLITE_MISUSE_BKPT;
129852129946
return -1;
129853129947
}
129854129948
#endif
129855
- Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
129949
+ pBt = sqlite3DbNameToBtree(db, zDbName);
129856129950
return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
129857129951
}
129858129952
129859129953
/************** End of main.c ************************************************/
129860129954
/************** Begin file notify.c ******************************************/
@@ -150061,11 +150155,11 @@
150061150155
}
150062150156
i = pCur->nPoint++;
150063150157
pNew = pCur->aPoint + i;
150064150158
pNew->rScore = rScore;
150065150159
pNew->iLevel = iLevel;
150066
- assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH );
150160
+ assert( iLevel<=RTREE_MAX_DEPTH );
150067150161
while( i>0 ){
150068150162
RtreeSearchPoint *pParent;
150069150163
j = (i-1)/2;
150070150164
pParent = pCur->aPoint + j;
150071150165
if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break;
150072150166
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -231,11 +231,11 @@
231 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
232 ** [sqlite_version()] and [sqlite_source_id()].
233 */
234 #define SQLITE_VERSION "3.8.8"
235 #define SQLITE_VERSION_NUMBER 3008008
236 #define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0"
237
238 /*
239 ** CAPI3REF: Run-Time Library Version Numbers
240 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
241 **
@@ -323,11 +323,11 @@
323 ** This interface only reports on the compile-time mutex setting
324 ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
325 ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
326 ** can be fully or partially disabled using a call to [sqlite3_config()]
327 ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
328 ** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the
329 ** sqlite3_threadsafe() function shows only the compile-time setting of
330 ** thread safety, not any run-time changes to that setting made by
331 ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
332 ** is unchanged by calls to sqlite3_config().)^
333 **
@@ -1692,11 +1692,11 @@
1692 ** configuration option.
1693 ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
1694 ** 8-byte aligned
1695 ** memory, the size of each page buffer (sz), and the number of pages (N).
1696 ** The sz argument should be the size of the largest database page
1697 ** (a power of two between 512 and 32768) plus some extra bytes for each
1698 ** page header. ^The number of extra bytes needed by the page header
1699 ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
1700 ** to [sqlite3_config()].
1701 ** ^It is harmless, apart from the wasted memory,
1702 ** for the sz parameter to be larger than necessary. The first
@@ -1872,10 +1872,21 @@
1872 ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
1873 ** is a pointer to an integer and writes into that integer the number of extra
1874 ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
1875 ** The amount of extra space required can change depending on the compiler,
1876 ** target platform, and SQLite version.
 
 
 
 
 
 
 
 
 
 
 
1877 ** </dl>
1878 */
1879 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1880 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1881 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1898,10 +1909,11 @@
1898 #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
1899 #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
1900 #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
1901 #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
1902 #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
 
1903
1904 /*
1905 ** CAPI3REF: Database Connection Configuration Options
1906 **
1907 ** These constants are the available integer configuration options that
@@ -5279,24 +5291,31 @@
5279
5280
5281 /*
5282 ** CAPI3REF: Extract Metadata About A Column Of A Table
5283 **
5284 ** ^This routine returns metadata about a specific column of a specific
5285 ** database table accessible using the [database connection] handle
5286 ** passed as the first function argument.
 
 
 
 
 
 
 
 
5287 **
5288 ** ^The column is identified by the second, third and fourth parameters to
5289 ** this function. ^The second parameter is either the name of the database
5290 ** (i.e. "main", "temp", or an attached database) containing the specified
5291 ** table or NULL. ^If it is NULL, then all attached databases are searched
5292 ** for the table using the same algorithm used by the database engine to
5293 ** resolve unqualified table references.
5294 **
5295 ** ^The third and fourth parameters to this function are the table and column
5296 ** name of the desired column, respectively. Neither of these parameters
5297 ** may be NULL.
5298 **
5299 ** ^Metadata is returned by writing to the memory locations passed as the 5th
5300 ** and subsequent parameters to this function. ^Any of these arguments may be
5301 ** NULL, in which case the corresponding element of metadata is omitted.
5302 **
@@ -5311,36 +5330,33 @@
5311 ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
5312 ** </table>
5313 ** </blockquote>)^
5314 **
5315 ** ^The memory pointed to by the character pointers returned for the
5316 ** declaration type and collation sequence is valid only until the next
5317 ** call to any SQLite API function.
5318 **
5319 ** ^If the specified table is actually a view, an [error code] is returned.
5320 **
5321 ** ^If the specified column is "rowid", "oid" or "_rowid_" and an
 
5322 ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
5323 ** parameters are set for the explicitly declared column. ^(If there is no
5324 ** explicitly declared [INTEGER PRIMARY KEY] column, then the output
5325 ** parameters are set as follows:
5326 **
5327 ** <pre>
5328 ** data type: "INTEGER"
5329 ** collation sequence: "BINARY"
5330 ** not null: 0
5331 ** primary key: 1
5332 ** auto increment: 0
5333 ** </pre>)^
5334 **
5335 ** ^(This function may load one or more schemas from database files. If an
5336 ** error occurs during this process, or if the requested table or column
5337 ** cannot be found, an [error code] is returned and an error message left
5338 ** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^
5339 **
5340 ** ^This API is only available if the library was compiled with the
5341 ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
5342 */
5343 SQLITE_API int sqlite3_table_column_metadata(
5344 sqlite3 *db, /* Connection handle */
5345 const char *zDbName, /* Database name or NULL */
5346 const char *zTableName, /* Table name */
@@ -7303,16 +7319,14 @@
7303
7304 /*
7305 ** CAPI3REF: Write-Ahead Log Commit Hook
7306 **
7307 ** ^The [sqlite3_wal_hook()] function is used to register a callback that
7308 ** will be invoked each time a database connection commits data to a
7309 ** [write-ahead log] (i.e. whenever a transaction is committed in
7310 ** [journal_mode | journal_mode=WAL mode]).
7311 **
7312 ** ^The callback is invoked by SQLite after the commit has taken place and
7313 ** the associated write-lock on the database released, so the implementation
7314 ** may read, write or [checkpoint] the database as required.
7315 **
7316 ** ^The first parameter passed to the callback function when it is invoked
7317 ** is a copy of the third parameter passed to sqlite3_wal_hook() when
7318 ** registering the callback. ^The second is a copy of the database handle.
@@ -9096,11 +9110,11 @@
9096 #define _BTREE_H_
9097
9098 /* TODO: This definition is just included so other modules compile. It
9099 ** needs to be revisited.
9100 */
9101 #define SQLITE_N_BTREE_META 10
9102
9103 /*
9104 ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
9105 ** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
9106 */
@@ -9211,10 +9225,15 @@
9211 ** offset = 36 + (idx * 4)
9212 **
9213 ** For example, the free-page-count field is located at byte offset 36 of
9214 ** the database file header. The incr-vacuum-flag field is located at
9215 ** byte offset 64 (== 36+4*7).
 
 
 
 
 
9216 */
9217 #define BTREE_FREE_PAGE_COUNT 0
9218 #define BTREE_SCHEMA_VERSION 1
9219 #define BTREE_FILE_FORMAT 2
9220 #define BTREE_DEFAULT_CACHE_SIZE 3
@@ -9221,10 +9240,11 @@
9221 #define BTREE_LARGEST_ROOT_PAGE 4
9222 #define BTREE_TEXT_ENCODING 5
9223 #define BTREE_USER_VERSION 6
9224 #define BTREE_INCR_VACUUM 7
9225 #define BTREE_APPLICATION_ID 8
 
9226
9227 /*
9228 ** Values that may be OR'd together to form the second argument of an
9229 ** sqlite3BtreeCursorHints() call.
9230 */
@@ -10002,10 +10022,11 @@
10002 SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
10003 #endif
10004
10005 /* Functions used to query pager state and configuration. */
10006 SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
 
10007 SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
10008 SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
10009 SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
10010 SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
10011 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
@@ -10743,10 +10764,11 @@
10743 i64 szMmap; /* Default mmap_size setting */
10744 unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
10745 int errCode; /* Most recent error code (SQLITE_*) */
10746 int errMask; /* & result codes with this before returning */
10747 u16 dbOptFlags; /* Flags to enable/disable optimizations */
 
10748 u8 autoCommit; /* The auto-commit flag. */
10749 u8 temp_store; /* 1: file 2: memory 0: default */
10750 u8 mallocFailed; /* True if we have seen a malloc failure */
10751 u8 dfltLockMode; /* Default locking-mode for attached dbs */
10752 signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
@@ -10844,11 +10866,12 @@
10844 };
10845
10846 /*
10847 ** A macro to discover the encoding of a database.
10848 */
10849 #define ENC(db) ((db)->aDb[0].pSchema->enc)
 
10850
10851 /*
10852 ** Possible values for the sqlite3.flags.
10853 */
10854 #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
@@ -11468,11 +11491,10 @@
11468 Index *pNext; /* The next index associated with the same table */
11469 Schema *pSchema; /* Schema containing this index */
11470 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
11471 char **azColl; /* Array of collation sequence names for index */
11472 Expr *pPartIdxWhere; /* WHERE clause for partial indices */
11473 KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */
11474 int tnum; /* DB Page containing root of this index */
11475 LogEst szIdxRow; /* Estimated average row size in bytes */
11476 u16 nKeyCol; /* Number of columns forming the key */
11477 u16 nColumn; /* Number of columns stored in the index */
11478 u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
@@ -12522,10 +12544,11 @@
12522 void *pPage; /* Page cache memory */
12523 int szPage; /* Size of each page in pPage[] */
12524 int nPage; /* Number of pages in pPage[] */
12525 int mxParserStack; /* maximum depth of the parser stack */
12526 int sharedCacheEnabled; /* true if shared-cache mode enabled */
 
12527 /* The above might be initialized to non-zero. The following need to always
12528 ** initially be zero, however. */
12529 int isInit; /* True after initialization has finished */
12530 int inProgress; /* True while initialization in progress */
12531 int isMutexInit; /* True after mutexes are initialized */
@@ -13444,11 +13467,11 @@
13444 ** print I/O tracing messages.
13445 */
13446 #ifdef SQLITE_ENABLE_IOTRACE
13447 # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
13448 SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*);
13449 SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...);
13450 #else
13451 # define IOTRACE(A)
13452 # define sqlite3VdbeIOTraceSql(X)
13453 #endif
13454
@@ -13657,10 +13680,17 @@
13657 */
13658 #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
13659 # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
13660 #endif
13661
 
 
 
 
 
 
 
13662 /*
13663 ** The following singleton contains the global configuration for
13664 ** the SQLite library.
13665 */
13666 SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
@@ -13687,10 +13717,11 @@
13687 (void*)0, /* pPage */
13688 0, /* szPage */
13689 0, /* nPage */
13690 0, /* mxParserStack */
13691 0, /* sharedCacheEnabled */
 
13692 /* All the rest should always be initialized to zero */
13693 0, /* isInit */
13694 0, /* inProgress */
13695 0, /* isMutexInit */
13696 0, /* isMallocInit */
@@ -19972,10 +20003,16 @@
19972 #endif
19973 }
19974 break;
19975 }
19976 default: {
 
 
 
 
 
 
19977 assert( iType-2 >= 0 );
19978 assert( iType-2 < ArraySize(winMutex_staticMutexes) );
19979 assert( winMutex_isInit==1 );
19980 p = &winMutex_staticMutexes[iType-2];
19981 #ifdef SQLITE_DEBUG
@@ -28779,28 +28816,31 @@
28779 do{
28780 err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
28781 }while( err==EINTR );
28782 if( err ) return SQLITE_IOERR_WRITE;
28783 #else
28784 /* If the OS does not have posix_fallocate(), fake it. First use
28785 ** ftruncate() to set the file size, then write a single byte to
28786 ** the last byte in each block within the extended region. This
28787 ** is the same technique used by glibc to implement posix_fallocate()
28788 ** on systems that do not have a real fallocate() system call.
 
28789 */
28790 int nBlk = buf.st_blksize; /* File-system block size */
28791 i64 iWrite; /* Next offset to write to */
28792
28793 if( robust_ftruncate(pFile->h, nSize) ){
28794 pFile->lastErrno = errno;
28795 return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
28796 }
28797 iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
28798 while( iWrite<nSize ){
 
 
 
28799 int nWrite = seekAndWrite(pFile, iWrite, "", 1);
28800 if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
28801 iWrite += nBlk;
 
 
 
28802 }
28803 #endif
28804 }
28805 }
28806
@@ -34014,12 +34054,12 @@
34014 */
34015 SQLITE_API int sqlite3_win32_reset_heap(){
34016 int rc;
34017 MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
34018 MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
34019 MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
34020 MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
34021 sqlite3_mutex_enter(pMaster);
34022 sqlite3_mutex_enter(pMem);
34023 winMemAssertMagic();
34024 if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
34025 /*
@@ -35290,11 +35330,11 @@
35290 sqlite3_file *id, /* File to read from */
35291 void *pBuf, /* Write content into this buffer */
35292 int amt, /* Number of bytes to read */
35293 sqlite3_int64 offset /* Begin reading at this offset */
35294 ){
35295 #if !SQLITE_OS_WINCE
35296 OVERLAPPED overlapped; /* The offset for ReadFile. */
35297 #endif
35298 winFile *pFile = (winFile*)id; /* file handle */
35299 DWORD nRead; /* Number of bytes actually read from file */
35300 int nRetry = 0; /* Number of retrys */
@@ -35322,11 +35362,11 @@
35322 offset += nCopy;
35323 }
35324 }
35325 #endif
35326
35327 #if SQLITE_OS_WINCE
35328 if( winSeekFile(pFile, offset) ){
35329 OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
35330 return SQLITE_FULL;
35331 }
35332 while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
@@ -35394,32 +35434,32 @@
35394 offset += nCopy;
35395 }
35396 }
35397 #endif
35398
35399 #if SQLITE_OS_WINCE
35400 rc = winSeekFile(pFile, offset);
35401 if( rc==0 ){
35402 #else
35403 {
35404 #endif
35405 #if !SQLITE_OS_WINCE
35406 OVERLAPPED overlapped; /* The offset for WriteFile. */
35407 #endif
35408 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
35409 int nRem = amt; /* Number of bytes yet to be written */
35410 DWORD nWrite; /* Bytes written by each WriteFile() call */
35411 DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
35412
35413 #if !SQLITE_OS_WINCE
35414 memset(&overlapped, 0, sizeof(OVERLAPPED));
35415 overlapped.Offset = (LONG)(offset & 0xffffffff);
35416 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
35417 #endif
35418
35419 while( nRem>0 ){
35420 #if SQLITE_OS_WINCE
35421 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
35422 #else
35423 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
35424 #endif
35425 if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
@@ -35428,11 +35468,11 @@
35428 assert( nWrite==0 || nWrite<=(DWORD)nRem );
35429 if( nWrite==0 || nWrite>(DWORD)nRem ){
35430 lastErrno = osGetLastError();
35431 break;
35432 }
35433 #if !SQLITE_OS_WINCE
35434 offset += nWrite;
35435 overlapped.Offset = (LONG)(offset & 0xffffffff);
35436 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
35437 #endif
35438 aRem += nWrite;
@@ -38974,11 +39014,12 @@
38974 SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
38975 assert( pCache->nRef==0 && pCache->pDirty==0 );
38976 if( pCache->szPage ){
38977 sqlite3_pcache *pNew;
38978 pNew = sqlite3GlobalConfig.pcache2.xCreate(
38979 szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
 
38980 );
38981 if( pNew==0 ) return SQLITE_NOMEM;
38982 sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
38983 if( pCache->pCache ){
38984 sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
@@ -39433,11 +39474,11 @@
39433
39434 /*
39435 ** Return the size of the header added by this middleware layer
39436 ** in the page-cache hierarchy.
39437 */
39438 SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); }
39439
39440
39441 #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
39442 /*
39443 ** For all dirty pages currently in the cache, invoke the specified
@@ -39749,11 +39790,11 @@
39749 pcache1Free(pPg);
39750 sqlite3_free(p);
39751 pPg = 0;
39752 }
39753 #else
39754 pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
39755 p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
39756 #endif
39757 pcache1EnterMutex(pCache->pGroup);
39758
39759 if( pPg ){
@@ -40437,11 +40478,11 @@
40437 }
40438
40439 /*
40440 ** Return the size of the header on each page of this PCACHE implementation.
40441 */
40442 SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); }
40443
40444 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
40445 /*
40446 ** This function is called to free superfluous dynamically allocated memory
40447 ** held by the pager system. Memory in use by any SQLite pager allocated
@@ -41795,10 +41836,12 @@
41795 u8 eLock; /* Current lock held on database file */
41796 u8 changeCountDone; /* Set after incrementing the change-counter */
41797 u8 setMaster; /* True if a m-j name has been written to jrnl */
41798 u8 doNotSpill; /* Do not spill the cache when non-zero */
41799 u8 subjInMemory; /* True to use in-memory sub-journals */
 
 
41800 Pgno dbSize; /* Number of pages in the database */
41801 Pgno dbOrigSize; /* dbSize before the current transaction */
41802 Pgno dbFileSize; /* Number of pages in the database file */
41803 Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */
41804 int errCode; /* One of several kinds of errors */
@@ -41812,13 +41855,13 @@
41812 i64 journalOff; /* Current write offset in the journal file */
41813 i64 journalHdr; /* Byte offset to previous journal header */
41814 sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
41815 PagerSavepoint *aSavepoint; /* Array of active savepoints */
41816 int nSavepoint; /* Number of elements in aSavepoint[] */
 
41817 char dbFileVers[16]; /* Changes whenever database file changes */
41818
41819 u8 bUseFetch; /* True to use xFetch() */
41820 int nMmapOut; /* Number of mmap pages currently outstanding */
41821 sqlite3_int64 szMmap; /* Desired maximum mmap size */
41822 PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */
41823 /*
41824 ** End of the routinely-changing class members
@@ -42830,13 +42873,22 @@
42830
42831 /*
42832 ** Discard the entire contents of the in-memory page-cache.
42833 */
42834 static void pager_reset(Pager *pPager){
 
42835 sqlite3BackupRestart(pPager->pBackup);
42836 sqlite3PcacheClear(pPager->pPCache);
42837 }
 
 
 
 
 
 
 
 
42838
42839 /*
42840 ** Free all structures in the Pager.aSavepoint[] array and set both
42841 ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
42842 ** if it is open and the pager is not in exclusive mode.
@@ -45036,11 +45088,11 @@
45036 Pgno pgno, /* Page number */
45037 void *pData, /* xFetch()'d data for this page */
45038 PgHdr **ppPage /* OUT: Acquired page object */
45039 ){
45040 PgHdr *p; /* Memory mapped page to return */
45041
45042 if( pPager->pMmapFreelist ){
45043 *ppPage = p = pPager->pMmapFreelist;
45044 pPager->pMmapFreelist = p->pDirty;
45045 p->pDirty = 0;
45046 memset(p->pExtra, 0, pPager->nExtra);
@@ -46267,20 +46319,16 @@
46267 assert( (pPager->eLock==SHARED_LOCK)
46268 || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
46269 );
46270 }
46271
46272 if( !pPager->tempFile && (
46273 pPager->pBackup
46274 || sqlite3PcachePagecount(pPager->pPCache)>0
46275 || USEFETCH(pPager)
46276 )){
46277 /* The shared-lock has just been acquired on the database file
46278 ** and there are already pages in the cache (from a previous
46279 ** read or write transaction). Check to see if the database
46280 ** has been modified. If the database has changed, flush the
46281 ** cache.
46282 **
46283 ** Database changes is detected by looking at 15 bytes beginning
46284 ** at offset 24 into the file. The first 4 of these 16 bytes are
46285 ** a 32-bit counter that is incremented with each change. The
46286 ** other bytes change randomly with each file change when
@@ -46441,10 +46489,11 @@
46441 assert( noContent==0 || bMmapOk==0 );
46442
46443 if( pgno==0 ){
46444 return SQLITE_CORRUPT_BKPT;
46445 }
 
46446
46447 /* If the pager is in the error state, return an error immediately.
46448 ** Otherwise, request the page from the PCache layer. */
46449 if( pPager->errCode!=SQLITE_OK ){
46450 rc = pPager->errCode;
@@ -46590,10 +46639,11 @@
46590 sqlite3_pcache_page *pPage;
46591 assert( pPager!=0 );
46592 assert( pgno!=0 );
46593 assert( pPager->pPCache!=0 );
46594 pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);
 
46595 return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
46596 }
46597
46598 /*
46599 ** Release a page reference.
@@ -47456,10 +47506,11 @@
47456 pPager->eState = PAGER_READER;
47457 return SQLITE_OK;
47458 }
47459
47460 PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
 
47461 rc = pager_end_transaction(pPager, pPager->setMaster, 1);
47462 return pager_error(pPager, rc);
47463 }
47464
47465 /*
@@ -50825,11 +50876,11 @@
50825 }
50826 nCollide = HASHTABLE_NSLOT;
50827 for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
50828 u32 iFrame = aHash[iKey] + iZero;
50829 if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){
50830 /* assert( iFrame>iRead ); -- not true if there is corruption */
50831 iRead = iFrame;
50832 }
50833 if( (nCollide--)==0 ){
50834 return SQLITE_CORRUPT_BKPT;
50835 }
@@ -51931,10 +51982,11 @@
51931 u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
51932 u8 sharable; /* True if we can share pBt with another db */
51933 u8 locked; /* True if db currently has pBt locked */
51934 int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
51935 int nBackup; /* Number of backup operations reading this btree */
 
51936 Btree *pNext; /* List of other sharable Btrees from the same db */
51937 Btree *pPrev; /* Back pointer of the same list */
51938 #ifndef SQLITE_OMIT_SHARED_CACHE
51939 BtLock lock; /* Object used to lock page 1 */
51940 #endif
@@ -56094,10 +56146,11 @@
56094 rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
56095 if( rc!=SQLITE_OK && bCleanup==0 ){
56096 sqlite3BtreeLeave(p);
56097 return rc;
56098 }
 
56099 pBt->inTransaction = TRANS_READ;
56100 btreeClearHasContent(pBt);
56101 }
56102
56103 btreeEndTransaction(p);
@@ -56457,11 +56510,11 @@
56457 }
56458 for(i=0; i<=pCur->iPage; i++){
56459 releasePage(pCur->apPage[i]);
56460 }
56461 unlockBtreeIfUnused(pBt);
56462 sqlite3DbFree(pBtree->db, pCur->aOverflow);
56463 /* sqlite3_free(pCur); */
56464 sqlite3BtreeLeave(pBtree);
56465 }
56466 return SQLITE_OK;
56467 }
@@ -56751,10 +56804,11 @@
56751 pBuf += a;
56752 amt -= a;
56753 }else{
56754 offset -= pCur->info.nLocal;
56755 }
 
56756
56757 if( rc==SQLITE_OK && amt>0 ){
56758 const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
56759 Pgno nextPage;
56760
@@ -56769,12 +56823,12 @@
56769 ** means "not yet known" (the cache is lazily populated).
56770 */
56771 if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
56772 int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
56773 if( nOvfl>pCur->nOvflAlloc ){
56774 Pgno *aNew = (Pgno*)sqlite3DbRealloc(
56775 pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno)
56776 );
56777 if( aNew==0 ){
56778 rc = SQLITE_NOMEM;
56779 }else{
56780 pCur->nOvflAlloc = nOvfl*2;
@@ -56817,10 +56871,11 @@
56817 ** Note that the aOverflow[] array must be allocated because eOp!=2
56818 ** here. If eOp==2, then offset==0 and this branch is never taken.
56819 */
56820 assert( eOp!=2 );
56821 assert( pCur->curFlags & BTCF_ValidOvfl );
 
56822 if( pCur->aOverflow[iIdx+1] ){
56823 nextPage = pCur->aOverflow[iIdx+1];
56824 }else{
56825 rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
56826 }
@@ -59329,11 +59384,11 @@
59329 + nMaxCells*sizeof(u16) /* szCell */
59330 + pBt->pageSize; /* aSpace1 */
59331
59332 /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer
59333 ** that is more than 6 times the database page size. */
59334 assert( szScratch<=6*pBt->pageSize );
59335 apCell = sqlite3ScratchMalloc( szScratch );
59336 if( apCell==0 ){
59337 rc = SQLITE_NOMEM;
59338 goto balance_cleanup;
59339 }
@@ -59406,12 +59461,12 @@
59406 assert( leafCorrection==4 );
59407 if( szCell[nCell]<4 ){
59408 /* Do not allow any cells smaller than 4 bytes. If a smaller cell
59409 ** does exist, pad it with 0x00 bytes. */
59410 assert( szCell[nCell]==3 );
59411 assert( apCell[nCell]==&pTemp[iSpace1-3] );
59412 pTemp[iSpace1++] = 0x00;
59413 szCell[nCell] = 4;
59414 }
59415 }
59416 nCell++;
59417 }
@@ -60719,10 +60774,17 @@
60719 ** is read-only, the others are read/write.
60720 **
60721 ** The schema layer numbers meta values differently. At the schema
60722 ** layer (and the SetCookie and ReadCookie opcodes) the number of
60723 ** free pages is not visible. So Cookie[0] is the same as Meta[1].
 
 
 
 
 
 
 
60724 */
60725 SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
60726 BtShared *pBt = p->pBt;
60727
60728 sqlite3BtreeEnter(p);
@@ -60729,11 +60791,15 @@
60729 assert( p->inTrans>TRANS_NONE );
60730 assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
60731 assert( pBt->pPage1 );
60732 assert( idx>=0 && idx<=15 );
60733
60734 *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
 
 
 
 
60735
60736 /* If auto-vacuum is disabled in this build and this is an auto-vacuum
60737 ** database, mark the database as read-only. */
60738 #ifdef SQLITE_OMIT_AUTOVACUUM
60739 if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
@@ -60820,11 +60886,11 @@
60820 if( pPage->leaf ){
60821 do {
60822 if( pCur->iPage==0 ){
60823 /* All pages of the b-tree have been visited. Return successfully. */
60824 *pnEntry = nEntry;
60825 return SQLITE_OK;
60826 }
60827 moveToParent(pCur);
60828 }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
60829
60830 pCur->aiIdx[pCur->iPage]++;
@@ -61676,11 +61742,11 @@
61676 }
61677
61678 /*
61679 ** Return the size of the header added to each page by this module.
61680 */
61681 SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); }
61682
61683 /************** End of btree.c ***********************************************/
61684 /************** Begin file backup.c ******************************************/
61685 /*
61686 ** 2009 January 28
@@ -64440,36 +64506,39 @@
64440 **
64441 ** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
64442 */
64443 SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
64444 int hasAbort = 0;
 
64445 Op *pOp;
64446 VdbeOpIter sIter;
64447 memset(&sIter, 0, sizeof(sIter));
64448 sIter.v = v;
64449
64450 while( (pOp = opIterNext(&sIter))!=0 ){
64451 int opcode = pOp->opcode;
64452 if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
64453 #ifndef SQLITE_OMIT_FOREIGN_KEY
64454 || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
64455 #endif
64456 || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
64457 && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
64458 ){
64459 hasAbort = 1;
64460 break;
64461 }
 
 
 
 
 
64462 }
64463 sqlite3DbFree(v->db, sIter.apSub);
64464
64465 /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
64466 ** If malloc failed, then the while() loop above may not have iterated
64467 ** through all opcodes and hasAbort may be set incorrectly. Return
64468 ** true for this case to prevent the assert() in the callers frame
64469 ** from failing. */
64470 return ( v->db->mallocFailed || hasAbort==mayAbort );
64471 }
64472 #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
64473
64474 /*
64475 ** Loop through the program looking for P2 values that are negative
@@ -68589,11 +68658,14 @@
68589 #ifndef SQLITE_OMIT_WAL
68590 int i;
68591 for(i=0; i<db->nDb; i++){
68592 Btree *pBt = db->aDb[i].pBt;
68593 if( pBt ){
68594 int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
 
 
 
68595 if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
68596 rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
68597 }
68598 }
68599 }
@@ -68769,11 +68841,10 @@
68769 ** program counter to 0 to ensure that when the statement is
68770 ** finalized or reset the parser error message is available via
68771 ** sqlite3_errmsg() and sqlite3_errcode().
68772 */
68773 const char *zErr = (const char *)sqlite3_value_text(db->pErr);
68774 assert( zErr!=0 || db->mallocFailed );
68775 sqlite3DbFree(db, v->zErrMsg);
68776 if( !db->mallocFailed ){
68777 v->zErrMsg = sqlite3DbStrDup(db, zErr);
68778 v->rc = rc2;
68779 } else {
@@ -77131,11 +77202,11 @@
77131 /*
77132 ** Hard-coded maximum amount of data to accumulate in memory before flushing
77133 ** to a level 0 PMA. The purpose of this limit is to prevent various integer
77134 ** overflows. 512MiB.
77135 */
77136 #define SQLITE_MAX_MXPMASIZE (1<<29)
77137
77138 /*
77139 ** Private objects used by the sorter
77140 */
77141 typedef struct MergeEngine MergeEngine; /* Merge PMAs together */
@@ -77427,13 +77498,10 @@
77427 **
77428 ** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; }
77429 */
77430 #define SRVAL(p) ((void*)((SorterRecord*)(p) + 1))
77431
77432 /* The minimum PMA size is set to this value multiplied by the database
77433 ** page size in bytes. */
77434 #define SORTER_MIN_WORKING 10
77435
77436 /* Maximum number of PMAs that a single MergeEngine can merge */
77437 #define SORTER_MAX_MERGE_COUNT 16
77438
77439 static int vdbeIncrSwap(IncrMerger*);
@@ -77828,14 +77896,15 @@
77828 SortSubtask *pTask = &pSorter->aTask[i];
77829 pTask->pSorter = pSorter;
77830 }
77831
77832 if( !sqlite3TempInMemory(db) ){
77833 pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
 
77834 mxCache = db->aDb[0].pSchema->cache_size;
77835 if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
77836 pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_MXPMASIZE);
77837
77838 /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
77839 ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
77840 ** large heap allocations.
77841 */
@@ -78109,16 +78178,16 @@
78109 ** Whether or not the file does end up memory mapped of course depends on
78110 ** the specific VFS implementation.
78111 */
78112 static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
78113 if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
78114 int rc = sqlite3OsTruncate(pFd, nByte);
78115 if( rc==SQLITE_OK ){
78116 void *p = 0;
78117 sqlite3OsFetch(pFd, 0, (int)nByte, &p);
78118 sqlite3OsUnfetch(pFd, 0, p);
78119 }
78120 }
78121 }
78122 #else
78123 # define vdbeSorterExtendFile(x,y,z)
78124 #endif
@@ -87296,11 +87365,11 @@
87296
87297 p->iGet = -1;
87298 p->mxSample = mxSample;
87299 p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
87300 p->current.anLt = &p->current.anEq[nColUp];
87301 p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565;
87302
87303 /* Set up the Stat4Accum.a[] and aBest[] arrays */
87304 p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
87305 p->aBest = &p->a[mxSample];
87306 pSpace = (u8*)(&p->a[mxSample+nCol]);
@@ -88889,17 +88958,19 @@
88889 }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
88890 zErrDyn = sqlite3MPrintf(db,
88891 "attached databases must use the same text encoding as main database");
88892 rc = SQLITE_ERROR;
88893 }
 
88894 pPager = sqlite3BtreePager(aNew->pBt);
88895 sqlite3PagerLockingMode(pPager, db->dfltLockMode);
88896 sqlite3BtreeSecureDelete(aNew->pBt,
88897 sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
88898 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
88899 sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
88900 #endif
 
88901 }
88902 aNew->safety_level = 3;
88903 aNew->zName = sqlite3DbStrDup(db, zName);
88904 if( rc==SQLITE_OK && aNew->zName==0 ){
88905 rc = SQLITE_NOMEM;
@@ -90021,11 +90092,10 @@
90021 */
90022 static void freeIndex(sqlite3 *db, Index *p){
90023 #ifndef SQLITE_OMIT_ANALYZE
90024 sqlite3DeleteIndexSamples(db, p);
90025 #endif
90026 if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo);
90027 sqlite3ExprDelete(db, p->pPartIdxWhere);
90028 sqlite3DbFree(db, p->zColAff);
90029 if( p->isResized ) sqlite3DbFree(db, p->azColl);
90030 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
90031 sqlite3_free(p->aiRowEst);
@@ -91300,10 +91370,23 @@
91300 if( pPk==0 ) return;
91301 pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
91302 pTab->iPKey = -1;
91303 }else{
91304 pPk = sqlite3PrimaryKeyIndex(pTab);
 
 
 
 
 
 
 
 
 
 
 
 
 
91305 }
91306 pPk->isCovering = 1;
91307 assert( pPk!=0 );
91308 nPk = pPk->nKeyCol;
91309
@@ -93776,44 +93859,35 @@
93776 **
93777 ** The caller should invoke sqlite3KeyInfoUnref() on the returned object
93778 ** when it has finished using it.
93779 */
93780 SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
 
 
 
 
93781 if( pParse->nErr ) return 0;
93782 #ifndef SQLITE_OMIT_SHARED_CACHE
93783 if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){
93784 sqlite3KeyInfoUnref(pIdx->pKeyInfo);
93785 pIdx->pKeyInfo = 0;
93786 }
93787 #endif
93788 if( pIdx->pKeyInfo==0 ){
93789 int i;
93790 int nCol = pIdx->nColumn;
93791 int nKey = pIdx->nKeyCol;
93792 KeyInfo *pKey;
93793 if( pIdx->uniqNotNull ){
93794 pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
93795 }else{
93796 pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
93797 }
93798 if( pKey ){
93799 assert( sqlite3KeyInfoIsWriteable(pKey) );
93800 for(i=0; i<nCol; i++){
93801 char *zColl = pIdx->azColl[i];
93802 assert( zColl!=0 );
93803 pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
93804 sqlite3LocateCollSeq(pParse, zColl);
93805 pKey->aSortOrder[i] = pIdx->aSortOrder[i];
93806 }
93807 if( pParse->nErr ){
93808 sqlite3KeyInfoUnref(pKey);
93809 }else{
93810 pIdx->pKeyInfo = pKey;
93811 }
93812 }
93813 }
93814 return sqlite3KeyInfoRef(pIdx->pKeyInfo);
93815 }
93816
93817 #ifndef SQLITE_OMIT_CTE
93818 /*
93819 ** This routine is invoked once per CTE by the parser while parsing a
@@ -97430,11 +97504,11 @@
97430 assert( nIncr==1 );
97431 sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
97432 OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
97433 }else{
97434 if( nIncr>0 && pFKey->isDeferred==0 ){
97435 sqlite3ParseToplevel(pParse)->mayAbort = 1;
97436 }
97437 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
97438 }
97439
97440 sqlite3VdbeResolveLabel(v, iOk);
@@ -97501,10 +97575,14 @@
97501 ** This function is called to generate code executed when a row is deleted
97502 ** from the parent table of foreign key constraint pFKey and, if pFKey is
97503 ** deferred, when a row is inserted into the same table. When generating
97504 ** code for an SQL UPDATE operation, this function may be called twice -
97505 ** once to "delete" the old row and once to "insert" the new row.
 
 
 
 
97506 **
97507 ** The code generated by this function scans through the rows in the child
97508 ** table that correspond to the parent table row being deleted or inserted.
97509 ** For each child row found, one of the following actions is taken:
97510 **
@@ -97618,17 +97696,13 @@
97618 sNameContext.pSrcList = pSrc;
97619 sNameContext.pParse = pParse;
97620 sqlite3ResolveExprNames(&sNameContext, pWhere);
97621
97622 /* Create VDBE to loop through the entries in pSrc that match the WHERE
97623 ** clause. If the constraint is not deferred, throw an exception for
97624 ** each row found. Otherwise, for deferred constraints, increment the
97625 ** deferred constraint counter by nIncr for each row selected. */
97626 pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
97627 if( nIncr>0 && pFKey->isDeferred==0 ){
97628 sqlite3ParseToplevel(pParse)->mayAbort = 1;
97629 }
97630 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
97631 if( pWInfo ){
97632 sqlite3WhereEnd(pWInfo);
97633 }
97634
@@ -97802,10 +97876,28 @@
97802 }
97803 }
97804 }
97805 return 0;
97806 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97807
97808 /*
97809 ** This function is called when inserting, deleting or updating a row of
97810 ** table pTab to generate VDBE code to perform foreign key constraint
97811 ** processing for the operation.
@@ -97855,11 +97947,11 @@
97855 Index *pIdx = 0; /* Index on key columns in pTo */
97856 int *aiFree = 0;
97857 int *aiCol;
97858 int iCol;
97859 int i;
97860 int isIgnore = 0;
97861
97862 if( aChange
97863 && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
97864 && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0
97865 ){
@@ -97914,11 +98006,11 @@
97914 ** values read from the parent table are NULL. */
97915 if( db->xAuth ){
97916 int rcauth;
97917 char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
97918 rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
97919 isIgnore = (rcauth==SQLITE_IGNORE);
97920 }
97921 #endif
97922 }
97923
97924 /* Take a shared-cache advisory read-lock on the parent table. Allocate
@@ -97929,16 +98021,22 @@
97929
97930 if( regOld!=0 ){
97931 /* A row is being removed from the child table. Search for the parent.
97932 ** If the parent does not exist, removing the child row resolves an
97933 ** outstanding foreign key constraint violation. */
97934 fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
97935 }
97936 if( regNew!=0 ){
97937 /* A row is being added to the child table. If a parent row cannot
97938 ** be found, adding the child row has violated the FK constraint. */
97939 fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
 
 
 
 
 
 
97940 }
97941
97942 sqlite3DbFree(db, aiFree);
97943 }
97944
@@ -97955,12 +98053,12 @@
97955
97956 if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs)
97957 && !pParse->pToplevel && !pParse->isMultiWrite
97958 ){
97959 assert( regOld==0 && regNew!=0 );
97960 /* Inserting a single row into a parent table cannot cause an immediate
97961 ** foreign key violation. So do nothing in this case. */
97962 continue;
97963 }
97964
97965 if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
97966 if( !isIgnoreErrors || db->mallocFailed ) return;
@@ -97980,17 +98078,32 @@
97980
97981 if( regNew!=0 ){
97982 fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
97983 }
97984 if( regOld!=0 ){
97985 /* If there is a RESTRICT action configured for the current operation
97986 ** on the parent table of this FK, then throw an exception
97987 ** immediately if the FK constraint is violated, even if this is a
97988 ** deferred trigger. That's what RESTRICT means. To defer checking
97989 ** the constraint, the FK should specify NO ACTION (represented
97990 ** using OE_None). NO ACTION is the default. */
97991 fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97992 }
97993 pItem->zName = 0;
97994 sqlite3SrcListDelete(db, pSrc);
97995 }
97996 sqlite3DbFree(db, aiCol);
@@ -101080,11 +101193,10 @@
101080 # define sqlite3_column_database_name16 0
101081 # define sqlite3_column_table_name 0
101082 # define sqlite3_column_table_name16 0
101083 # define sqlite3_column_origin_name 0
101084 # define sqlite3_column_origin_name16 0
101085 # define sqlite3_table_column_metadata 0
101086 #endif
101087
101088 #ifdef SQLITE_OMIT_AUTHORIZATION
101089 # define sqlite3_set_authorizer 0
101090 #endif
@@ -101890,10 +102002,11 @@
101890 #define PragTyp_KEY 38
101891 #define PragTyp_REKEY 39
101892 #define PragTyp_LOCK_STATUS 40
101893 #define PragTyp_PARSER_TRACE 41
101894 #define PragFlag_NeedSchema 0x01
 
101895 static const struct sPragmaNames {
101896 const char *const zName; /* Name of pragma */
101897 u8 ePragTyp; /* PragTyp_XXX value */
101898 u8 mPragFlag; /* Zero or more PragFlag_XXX values */
101899 u32 iArg; /* Extra argument */
@@ -101906,11 +102019,11 @@
101906 #endif
101907 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
101908 { /* zName: */ "application_id",
101909 /* ePragTyp: */ PragTyp_HEADER_VALUE,
101910 /* ePragFlag: */ 0,
101911 /* iArg: */ 0 },
101912 #endif
101913 #if !defined(SQLITE_OMIT_AUTOVACUUM)
101914 { /* zName: */ "auto_vacuum",
101915 /* ePragTyp: */ PragTyp_AUTO_VACUUM,
101916 /* ePragFlag: */ PragFlag_NeedSchema,
@@ -101972,10 +102085,16 @@
101972 { /* zName: */ "data_store_directory",
101973 /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
101974 /* ePragFlag: */ 0,
101975 /* iArg: */ 0 },
101976 #endif
 
 
 
 
 
 
101977 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
101978 { /* zName: */ "database_list",
101979 /* ePragTyp: */ PragTyp_DATABASE_LIST,
101980 /* ePragFlag: */ PragFlag_NeedSchema,
101981 /* iArg: */ 0 },
@@ -102027,12 +102146,12 @@
102027 #endif
102028 #endif
102029 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102030 { /* zName: */ "freelist_count",
102031 /* ePragTyp: */ PragTyp_HEADER_VALUE,
102032 /* ePragFlag: */ 0,
102033 /* iArg: */ 0 },
102034 #endif
102035 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
102036 { /* zName: */ "full_column_names",
102037 /* ePragTyp: */ PragTyp_FLAG,
102038 /* ePragFlag: */ 0,
@@ -102180,11 +102299,11 @@
102180 #endif
102181 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102182 { /* zName: */ "schema_version",
102183 /* ePragTyp: */ PragTyp_HEADER_VALUE,
102184 /* ePragFlag: */ 0,
102185 /* iArg: */ 0 },
102186 #endif
102187 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
102188 { /* zName: */ "secure_delete",
102189 /* ePragTyp: */ PragTyp_SECURE_DELETE,
102190 /* ePragFlag: */ 0,
@@ -102246,11 +102365,11 @@
102246 /* iArg: */ 0 },
102247 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102248 { /* zName: */ "user_version",
102249 /* ePragTyp: */ PragTyp_HEADER_VALUE,
102250 /* ePragFlag: */ 0,
102251 /* iArg: */ 0 },
102252 #endif
102253 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
102254 #if defined(SQLITE_DEBUG)
102255 { /* zName: */ "vdbe_addoptrace",
102256 /* ePragTyp: */ PragTyp_FLAG,
@@ -102289,11 +102408,11 @@
102289 /* ePragTyp: */ PragTyp_FLAG,
102290 /* ePragFlag: */ 0,
102291 /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
102292 #endif
102293 };
102294 /* Number of pragmas: 57 on by default, 70 total. */
102295 /* End of the automatically generated pragma table.
102296 ***************************************************************************/
102297
102298 /*
102299 ** Interpret the given string as a safety level. Return 0 for OFF,
@@ -103899,11 +104018,12 @@
103899 !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
103900 DbHasProperty(db, 0, DB_Empty)
103901 ){
103902 for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
103903 if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
103904 ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
 
103905 break;
103906 }
103907 }
103908 if( !pEnc->zName ){
103909 sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight);
@@ -103944,28 +104064,13 @@
103944 **
103945 ** The user-version is not used internally by SQLite. It may be used by
103946 ** applications for any purpose.
103947 */
103948 case PragTyp_HEADER_VALUE: {
103949 int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
103950 sqlite3VdbeUsesBtree(v, iDb);
103951 switch( zLeft[0] ){
103952 case 'a': case 'A':
103953 iCookie = BTREE_APPLICATION_ID;
103954 break;
103955 case 'f': case 'F':
103956 iCookie = BTREE_FREE_PAGE_COUNT;
103957 break;
103958 case 's': case 'S':
103959 iCookie = BTREE_SCHEMA_VERSION;
103960 break;
103961 default:
103962 iCookie = BTREE_USER_VERSION;
103963 break;
103964 }
103965
103966 if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){
103967 /* Write the specified cookie value */
103968 static const VdbeOpList setCookie[] = {
103969 { OP_Transaction, 0, 1, 0}, /* 0 */
103970 { OP_Integer, 0, 1, 0}, /* 1 */
103971 { OP_SetCookie, 0, 0, 1}, /* 2 */
@@ -104607,13 +104712,15 @@
104607 SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
104608 int i, rc;
104609 int commit_internal = !(db->flags&SQLITE_InternChanges);
104610
104611 assert( sqlite3_mutex_held(db->mutex) );
 
104612 assert( db->init.busy==0 );
104613 rc = SQLITE_OK;
104614 db->init.busy = 1;
 
104615 for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
104616 if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
104617 rc = sqlite3InitOne(db, i, pzErrMsg);
104618 if( rc ){
104619 sqlite3ResetOneSchema(db, i);
@@ -110751,11 +110858,11 @@
110751 ){
110752 int rc;
110753 TabResult res;
110754
110755 #ifdef SQLITE_ENABLE_API_ARMOR
110756 if( pazResult==0 ) return SQLITE_MISUSE_BKPT;
110757 #endif
110758 *pazResult = 0;
110759 if( pnColumn ) *pnColumn = 0;
110760 if( pnRow ) *pnRow = 0;
110761 if( pzErrMsg ) *pzErrMsg = 0;
@@ -118621,11 +118728,10 @@
118621 sqlite3_free(p->u.vtab.idxStr);
118622 p->u.vtab.needFree = 0;
118623 p->u.vtab.idxStr = 0;
118624 }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
118625 sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
118626 sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo);
118627 sqlite3DbFree(db, p->u.btree.pIndex);
118628 p->u.btree.pIndex = 0;
118629 }
118630 }
118631 }
@@ -125628,10 +125734,13 @@
125628 u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */
125629 sqlite3 *db = pParse->db; /* The database connection */
125630 int mxSqlLen; /* Max length of an SQL string */
125631
125632
 
 
 
125633 mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
125634 if( db->nVdbeActive==0 ){
125635 db->u1.isInterrupted = 0;
125636 }
125637 pParse->rc = SQLITE_OK;
@@ -125866,17 +125975,10 @@
125866 */
125867 SQLITE_API int sqlite3_complete(const char *zSql){
125868 u8 state = 0; /* Current state, using numbers defined in header comment */
125869 u8 token; /* Value of the next token */
125870
125871 #ifdef SQLITE_ENABLE_API_ARMOR
125872 if( zSql==0 ){
125873 (void)SQLITE_MISUSE_BKPT;
125874 return 0;
125875 }
125876 #endif
125877
125878 #ifndef SQLITE_OMIT_TRIGGER
125879 /* A complex statement machine used to detect the end of a CREATE TRIGGER
125880 ** statement. This is the normal case.
125881 */
125882 static const u8 trans[8][8] = {
@@ -125901,10 +126003,17 @@
125901 /* 0 INVALID: */ { 1, 0, 2, },
125902 /* 1 START: */ { 1, 1, 2, },
125903 /* 2 NORMAL: */ { 1, 2, 2, },
125904 };
125905 #endif /* SQLITE_OMIT_TRIGGER */
 
 
 
 
 
 
 
125906
125907 while( *zSql ){
125908 switch( *zSql ){
125909 case ';': { /* A semicolon */
125910 token = tkSEMI;
@@ -126203,11 +126312,11 @@
126203 ** If the following function pointer is not NULL and if
126204 ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
126205 ** I/O active are written using this function. These messages
126206 ** are intended for debugging activity only.
126207 */
126208 SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0;
126209 #endif
126210
126211 /*
126212 ** If the following global variable points to a string which is the
126213 ** name of a directory, then that directory will be used to store
@@ -126412,10 +126521,17 @@
126412 ** routine is not threadsafe. But it is safe to invoke this routine
126413 ** on when SQLite is already shut down. If SQLite is already shut down
126414 ** when this routine is invoked, then this routine is a harmless no-op.
126415 */
126416 SQLITE_API int sqlite3_shutdown(void){
 
 
 
 
 
 
 
126417 if( sqlite3GlobalConfig.isInit ){
126418 #ifdef SQLITE_EXTRA_SHUTDOWN
126419 void SQLITE_EXTRA_SHUTDOWN(void);
126420 SQLITE_EXTRA_SHUTDOWN();
126421 #endif
@@ -126727,10 +126843,15 @@
126727 ** heap. */
126728 sqlite3GlobalConfig.nHeap = va_arg(ap, int);
126729 break;
126730 }
126731 #endif
 
 
 
 
 
126732
126733 default: {
126734 rc = SQLITE_ERROR;
126735 break;
126736 }
@@ -127173,18 +127294,10 @@
127173
127174 /* Close all database connections */
127175 for(j=0; j<db->nDb; j++){
127176 struct Db *pDb = &db->aDb[j];
127177 if( pDb->pBt ){
127178 if( pDb->pSchema ){
127179 /* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */
127180 for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){
127181 Index *pIdx = sqliteHashData(i);
127182 sqlite3KeyInfoUnref(pIdx->pKeyInfo);
127183 pIdx->pKeyInfo = 0;
127184 }
127185 }
127186 sqlite3BtreeClose(pDb->pBt);
127187 pDb->pBt = 0;
127188 if( j!=1 ){
127189 pDb->pSchema = 0;
127190 }
@@ -128308,36 +128421,10 @@
128308 */
128309 SQLITE_API const char *sqlite3_errstr(int rc){
128310 return sqlite3ErrStr(rc);
128311 }
128312
128313 /*
128314 ** Invalidate all cached KeyInfo objects for database connection "db"
128315 */
128316 static void invalidateCachedKeyInfo(sqlite3 *db){
128317 Db *pDb; /* A single database */
128318 int iDb; /* The database index number */
128319 HashElem *k; /* For looping over tables in pDb */
128320 Table *pTab; /* A table in the database */
128321 Index *pIdx; /* Each index */
128322
128323 for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
128324 if( pDb->pBt==0 ) continue;
128325 sqlite3BtreeEnter(pDb->pBt);
128326 for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
128327 pTab = (Table*)sqliteHashData(k);
128328 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
128329 if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){
128330 sqlite3KeyInfoUnref(pIdx->pKeyInfo);
128331 pIdx->pKeyInfo = 0;
128332 }
128333 }
128334 }
128335 sqlite3BtreeLeave(pDb->pBt);
128336 }
128337 }
128338
128339 /*
128340 ** Create a new collating function for database "db". The name is zName
128341 ** and the encoding is enc.
128342 */
128343 static int createCollation(
@@ -128377,11 +128464,10 @@
128377 sqlite3ErrorWithMsg(db, SQLITE_BUSY,
128378 "unable to delete/modify collation sequence due to active statements");
128379 return SQLITE_BUSY;
128380 }
128381 sqlite3ExpirePreparedStatements(db);
128382 invalidateCachedKeyInfo(db);
128383
128384 /* If collation sequence pColl was created directly by a call to
128385 ** sqlite3_create_collation, and not generated by synthCollSeq(),
128386 ** then any copies made by synthCollSeq() need to be invalidated.
128387 ** Also, collation destructor - CollSeq.xDel() - function may need
@@ -128882,10 +128968,13 @@
128882 | SQLITE_RecTriggers
128883 #endif
128884 #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS
128885 | SQLITE_ForeignKeys
128886 #endif
 
 
 
128887 ;
128888 sqlite3HashInit(&db->aCollSeq);
128889 #ifndef SQLITE_OMIT_VIRTUALTABLE
128890 sqlite3HashInit(&db->aModule);
128891 #endif
@@ -128929,11 +129018,14 @@
128929 rc = SQLITE_NOMEM;
128930 }
128931 sqlite3Error(db, rc);
128932 goto opendb_out;
128933 }
 
128934 db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
 
 
128935 db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
128936
128937 /* The default safety_level for the main database is 'full'; for the temp
128938 ** database it is 'NONE'. This matches the pager layer defaults.
128939 */
@@ -129087,11 +129179,11 @@
129087 if( zFilename8 ){
129088 rc = openDatabase(zFilename8, ppDb,
129089 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
129090 assert( *ppDb || rc==SQLITE_NOMEM );
129091 if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
129092 ENC(*ppDb) = SQLITE_UTF16NATIVE;
129093 }
129094 }else{
129095 rc = SQLITE_NOMEM;
129096 }
129097 sqlite3ValueFree(pVal);
@@ -129283,11 +129375,10 @@
129283
129284 /*
129285 ** Return meta information about a specific column of a database table.
129286 ** See comment in sqlite3.h (sqlite.h.in) for details.
129287 */
129288 #ifdef SQLITE_ENABLE_COLUMN_METADATA
129289 SQLITE_API int sqlite3_table_column_metadata(
129290 sqlite3 *db, /* Connection handle */
129291 const char *zDbName, /* Database name or NULL */
129292 const char *zTableName, /* Table name */
129293 const char *zColumnName, /* Column name */
@@ -129323,25 +129414,27 @@
129323 pTab = 0;
129324 goto error_out;
129325 }
129326
129327 /* Find the column for which info is requested */
129328 if( sqlite3IsRowid(zColumnName) ){
129329 iCol = pTab->iPKey;
129330 if( iCol>=0 ){
129331 pCol = &pTab->aCol[iCol];
129332 }
129333 }else{
129334 for(iCol=0; iCol<pTab->nCol; iCol++){
129335 pCol = &pTab->aCol[iCol];
129336 if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
129337 break;
129338 }
129339 }
129340 if( iCol==pTab->nCol ){
129341 pTab = 0;
129342 goto error_out;
 
 
 
 
 
129343 }
129344 }
129345
129346 /* The following block stores the meta information that will be returned
129347 ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey
@@ -129390,11 +129483,10 @@
129390 sqlite3DbFree(db, zErrMsg);
129391 rc = sqlite3ApiExit(db, rc);
129392 sqlite3_mutex_leave(db->mutex);
129393 return rc;
129394 }
129395 #endif
129396
129397 /*
129398 ** Sleep for a little while. Return the amount of time slept.
129399 */
129400 SQLITE_API int sqlite3_sleep(int ms){
@@ -129829,32 +129921,34 @@
129829 /*
129830 ** Return the filename of the database associated with a database
129831 ** connection.
129832 */
129833 SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
 
129834 #ifdef SQLITE_ENABLE_API_ARMOR
129835 if( !sqlite3SafetyCheckOk(db) ){
129836 (void)SQLITE_MISUSE_BKPT;
129837 return 0;
129838 }
129839 #endif
129840 Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
129841 return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
129842 }
129843
129844 /*
129845 ** Return 1 if database is read-only or 0 if read/write. Return -1 if
129846 ** no such database exists.
129847 */
129848 SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
 
129849 #ifdef SQLITE_ENABLE_API_ARMOR
129850 if( !sqlite3SafetyCheckOk(db) ){
129851 (void)SQLITE_MISUSE_BKPT;
129852 return -1;
129853 }
129854 #endif
129855 Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
129856 return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
129857 }
129858
129859 /************** End of main.c ************************************************/
129860 /************** Begin file notify.c ******************************************/
@@ -150061,11 +150155,11 @@
150061 }
150062 i = pCur->nPoint++;
150063 pNew = pCur->aPoint + i;
150064 pNew->rScore = rScore;
150065 pNew->iLevel = iLevel;
150066 assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH );
150067 while( i>0 ){
150068 RtreeSearchPoint *pParent;
150069 j = (i-1)/2;
150070 pParent = pCur->aPoint + j;
150071 if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break;
150072
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -231,11 +231,11 @@
231 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
232 ** [sqlite_version()] and [sqlite_source_id()].
233 */
234 #define SQLITE_VERSION "3.8.8"
235 #define SQLITE_VERSION_NUMBER 3008008
236 #define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6"
237
238 /*
239 ** CAPI3REF: Run-Time Library Version Numbers
240 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
241 **
@@ -323,11 +323,11 @@
323 ** This interface only reports on the compile-time mutex setting
324 ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
325 ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
326 ** can be fully or partially disabled using a call to [sqlite3_config()]
327 ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
328 ** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the
329 ** sqlite3_threadsafe() function shows only the compile-time setting of
330 ** thread safety, not any run-time changes to that setting made by
331 ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
332 ** is unchanged by calls to sqlite3_config().)^
333 **
@@ -1692,11 +1692,11 @@
1692 ** configuration option.
1693 ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
1694 ** 8-byte aligned
1695 ** memory, the size of each page buffer (sz), and the number of pages (N).
1696 ** The sz argument should be the size of the largest database page
1697 ** (a power of two between 512 and 65536) plus some extra bytes for each
1698 ** page header. ^The number of extra bytes needed by the page header
1699 ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
1700 ** to [sqlite3_config()].
1701 ** ^It is harmless, apart from the wasted memory,
1702 ** for the sz parameter to be larger than necessary. The first
@@ -1872,10 +1872,21 @@
1872 ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
1873 ** is a pointer to an integer and writes into that integer the number of extra
1874 ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
1875 ** The amount of extra space required can change depending on the compiler,
1876 ** target platform, and SQLite version.
1877 **
1878 ** [[SQLITE_CONFIG_PMASZ]]
1879 ** <dt>SQLITE_CONFIG_PMASZ
1880 ** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which
1881 ** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded
1882 ** sorter to that integer. The default minimum PMA Size is set by the
1883 ** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched
1884 ** to help with sort operations when multithreaded sorting
1885 ** is enabled (using the [PRAGMA threads] command) and the amount of content
1886 ** to be sorted exceeds the page size times the minimum of the
1887 ** [PRAGMA cache_size] setting and this value.
1888 ** </dl>
1889 */
1890 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1891 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1892 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1898,10 +1909,11 @@
1909 #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
1910 #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
1911 #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
1912 #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
1913 #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
1914 #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
1915
1916 /*
1917 ** CAPI3REF: Database Connection Configuration Options
1918 **
1919 ** These constants are the available integer configuration options that
@@ -5279,24 +5291,31 @@
5291
5292
5293 /*
5294 ** CAPI3REF: Extract Metadata About A Column Of A Table
5295 **
5296 ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
5297 ** information about column C of table T in database D
5298 ** on [database connection] X.)^ ^The sqlite3_table_column_metadata()
5299 ** interface returns SQLITE_OK and fills in the non-NULL pointers in
5300 ** the final five arguments with appropriate values if the specified
5301 ** column exists. ^The sqlite3_table_column_metadata() interface returns
5302 ** SQLITE_ERROR and if the specified column does not exist.
5303 ** ^If the column-name parameter to sqlite3_table_column_metadata() is a
5304 ** NULL pointer, then this routine simply checks for the existance of the
5305 ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
5306 ** does not.
5307 **
5308 ** ^The column is identified by the second, third and fourth parameters to
5309 ** this function. ^(The second parameter is either the name of the database
5310 ** (i.e. "main", "temp", or an attached database) containing the specified
5311 ** table or NULL.)^ ^If it is NULL, then all attached databases are searched
5312 ** for the table using the same algorithm used by the database engine to
5313 ** resolve unqualified table references.
5314 **
5315 ** ^The third and fourth parameters to this function are the table and column
5316 ** name of the desired column, respectively.
 
5317 **
5318 ** ^Metadata is returned by writing to the memory locations passed as the 5th
5319 ** and subsequent parameters to this function. ^Any of these arguments may be
5320 ** NULL, in which case the corresponding element of metadata is omitted.
5321 **
@@ -5311,36 +5330,33 @@
5330 ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
5331 ** </table>
5332 ** </blockquote>)^
5333 **
5334 ** ^The memory pointed to by the character pointers returned for the
5335 ** declaration type and collation sequence is valid until the next
5336 ** call to any SQLite API function.
5337 **
5338 ** ^If the specified table is actually a view, an [error code] is returned.
5339 **
5340 ** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
5341 ** is not a [WITHOUT ROWID] table and an
5342 ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
5343 ** parameters are set for the explicitly declared column. ^(If there is no
5344 ** [INTEGER PRIMARY KEY] column, then the outputs
5345 ** for the [rowid] are set as follows:
5346 **
5347 ** <pre>
5348 ** data type: "INTEGER"
5349 ** collation sequence: "BINARY"
5350 ** not null: 0
5351 ** primary key: 1
5352 ** auto increment: 0
5353 ** </pre>)^
5354 **
5355 ** ^This function causes all database schemas to be read from disk and
5356 ** parsed, if that has not already been done, and returns an error if
5357 ** any errors are encountered while loading the schema.
 
 
 
 
5358 */
5359 SQLITE_API int sqlite3_table_column_metadata(
5360 sqlite3 *db, /* Connection handle */
5361 const char *zDbName, /* Database name or NULL */
5362 const char *zTableName, /* Table name */
@@ -7303,16 +7319,14 @@
7319
7320 /*
7321 ** CAPI3REF: Write-Ahead Log Commit Hook
7322 **
7323 ** ^The [sqlite3_wal_hook()] function is used to register a callback that
7324 ** is invoked each time data is committed to a database in wal mode.
 
 
7325 **
7326 ** ^(The callback is invoked by SQLite after the commit has taken place and
7327 ** the associated write-lock on the database released)^, so the implementation
7328 ** may read, write or [checkpoint] the database as required.
7329 **
7330 ** ^The first parameter passed to the callback function when it is invoked
7331 ** is a copy of the third parameter passed to sqlite3_wal_hook() when
7332 ** registering the callback. ^The second is a copy of the database handle.
@@ -9096,11 +9110,11 @@
9110 #define _BTREE_H_
9111
9112 /* TODO: This definition is just included so other modules compile. It
9113 ** needs to be revisited.
9114 */
9115 #define SQLITE_N_BTREE_META 16
9116
9117 /*
9118 ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
9119 ** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
9120 */
@@ -9211,10 +9225,15 @@
9225 ** offset = 36 + (idx * 4)
9226 **
9227 ** For example, the free-page-count field is located at byte offset 36 of
9228 ** the database file header. The incr-vacuum-flag field is located at
9229 ** byte offset 64 (== 36+4*7).
9230 **
9231 ** The BTREE_DATA_VERSION value is not really a value stored in the header.
9232 ** It is a read-only number computed by the pager. But we merge it with
9233 ** the header value access routines since its access pattern is the same.
9234 ** Call it a "virtual meta value".
9235 */
9236 #define BTREE_FREE_PAGE_COUNT 0
9237 #define BTREE_SCHEMA_VERSION 1
9238 #define BTREE_FILE_FORMAT 2
9239 #define BTREE_DEFAULT_CACHE_SIZE 3
@@ -9221,10 +9240,11 @@
9240 #define BTREE_LARGEST_ROOT_PAGE 4
9241 #define BTREE_TEXT_ENCODING 5
9242 #define BTREE_USER_VERSION 6
9243 #define BTREE_INCR_VACUUM 7
9244 #define BTREE_APPLICATION_ID 8
9245 #define BTREE_DATA_VERSION 15 /* A virtual meta-value */
9246
9247 /*
9248 ** Values that may be OR'd together to form the second argument of an
9249 ** sqlite3BtreeCursorHints() call.
9250 */
@@ -10002,10 +10022,11 @@
10022 SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
10023 #endif
10024
10025 /* Functions used to query pager state and configuration. */
10026 SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
10027 SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*);
10028 SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
10029 SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
10030 SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
10031 SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
10032 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
@@ -10743,10 +10764,11 @@
10764 i64 szMmap; /* Default mmap_size setting */
10765 unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
10766 int errCode; /* Most recent error code (SQLITE_*) */
10767 int errMask; /* & result codes with this before returning */
10768 u16 dbOptFlags; /* Flags to enable/disable optimizations */
10769 u8 enc; /* Text encoding */
10770 u8 autoCommit; /* The auto-commit flag. */
10771 u8 temp_store; /* 1: file 2: memory 0: default */
10772 u8 mallocFailed; /* True if we have seen a malloc failure */
10773 u8 dfltLockMode; /* Default locking-mode for attached dbs */
10774 signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
@@ -10844,11 +10866,12 @@
10866 };
10867
10868 /*
10869 ** A macro to discover the encoding of a database.
10870 */
10871 #define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
10872 #define ENC(db) ((db)->enc)
10873
10874 /*
10875 ** Possible values for the sqlite3.flags.
10876 */
10877 #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
@@ -11468,11 +11491,10 @@
11491 Index *pNext; /* The next index associated with the same table */
11492 Schema *pSchema; /* Schema containing this index */
11493 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
11494 char **azColl; /* Array of collation sequence names for index */
11495 Expr *pPartIdxWhere; /* WHERE clause for partial indices */
 
11496 int tnum; /* DB Page containing root of this index */
11497 LogEst szIdxRow; /* Estimated average row size in bytes */
11498 u16 nKeyCol; /* Number of columns forming the key */
11499 u16 nColumn; /* Number of columns stored in the index */
11500 u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
@@ -12522,10 +12544,11 @@
12544 void *pPage; /* Page cache memory */
12545 int szPage; /* Size of each page in pPage[] */
12546 int nPage; /* Number of pages in pPage[] */
12547 int mxParserStack; /* maximum depth of the parser stack */
12548 int sharedCacheEnabled; /* true if shared-cache mode enabled */
12549 u32 szPma; /* Maximum Sorter PMA size */
12550 /* The above might be initialized to non-zero. The following need to always
12551 ** initially be zero, however. */
12552 int isInit; /* True after initialization has finished */
12553 int inProgress; /* True while initialization in progress */
12554 int isMutexInit; /* True after mutexes are initialized */
@@ -13444,11 +13467,11 @@
13467 ** print I/O tracing messages.
13468 */
13469 #ifdef SQLITE_ENABLE_IOTRACE
13470 # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
13471 SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*);
13472 void (*sqlite3IoTrace)(const char*,...);
13473 #else
13474 # define IOTRACE(A)
13475 # define sqlite3VdbeIOTraceSql(X)
13476 #endif
13477
@@ -13657,10 +13680,17 @@
13680 */
13681 #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
13682 # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
13683 #endif
13684
13685 /* The minimum PMA size is set to this value multiplied by the database
13686 ** page size in bytes.
13687 */
13688 #ifndef SQLITE_SORTER_PMASZ
13689 # define SQLITE_SORTER_PMASZ 250
13690 #endif
13691
13692 /*
13693 ** The following singleton contains the global configuration for
13694 ** the SQLite library.
13695 */
13696 SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
@@ -13687,10 +13717,11 @@
13717 (void*)0, /* pPage */
13718 0, /* szPage */
13719 0, /* nPage */
13720 0, /* mxParserStack */
13721 0, /* sharedCacheEnabled */
13722 SQLITE_SORTER_PMASZ, /* szPma */
13723 /* All the rest should always be initialized to zero */
13724 0, /* isInit */
13725 0, /* inProgress */
13726 0, /* isMutexInit */
13727 0, /* isMallocInit */
@@ -19972,10 +20003,16 @@
20003 #endif
20004 }
20005 break;
20006 }
20007 default: {
20008 #ifdef SQLITE_ENABLE_API_ARMOR
20009 if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
20010 (void)SQLITE_MISUSE_BKPT;
20011 return 0;
20012 }
20013 #endif
20014 assert( iType-2 >= 0 );
20015 assert( iType-2 < ArraySize(winMutex_staticMutexes) );
20016 assert( winMutex_isInit==1 );
20017 p = &winMutex_staticMutexes[iType-2];
20018 #ifdef SQLITE_DEBUG
@@ -28779,28 +28816,31 @@
28816 do{
28817 err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
28818 }while( err==EINTR );
28819 if( err ) return SQLITE_IOERR_WRITE;
28820 #else
28821 /* If the OS does not have posix_fallocate(), fake it. Write a
28822 ** single byte to the last byte in each block that falls entirely
28823 ** within the extended region. Then, if required, a single byte
28824 ** at offset (nSize-1), to set the size of the file correctly.
28825 ** This is a similar technique to that used by glibc on systems
28826 ** that do not have a real fallocate() call.
28827 */
28828 int nBlk = buf.st_blksize; /* File-system block size */
28829 i64 iWrite; /* Next offset to write to */
28830
 
 
 
 
28831 iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
28832 assert( iWrite>=buf.st_size );
28833 assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) );
28834 assert( ((iWrite+1)%nBlk)==0 );
28835 for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){
28836 int nWrite = seekAndWrite(pFile, iWrite, "", 1);
28837 if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
28838 }
28839 if( nSize%nBlk ){
28840 int nWrite = seekAndWrite(pFile, nSize-1, "", 1);
28841 if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
28842 }
28843 #endif
28844 }
28845 }
28846
@@ -34014,12 +34054,12 @@
34054 */
34055 SQLITE_API int sqlite3_win32_reset_heap(){
34056 int rc;
34057 MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
34058 MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
34059 MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); )
34060 MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); )
34061 sqlite3_mutex_enter(pMaster);
34062 sqlite3_mutex_enter(pMem);
34063 winMemAssertMagic();
34064 if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
34065 /*
@@ -35290,11 +35330,11 @@
35330 sqlite3_file *id, /* File to read from */
35331 void *pBuf, /* Write content into this buffer */
35332 int amt, /* Number of bytes to read */
35333 sqlite3_int64 offset /* Begin reading at this offset */
35334 ){
35335 #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
35336 OVERLAPPED overlapped; /* The offset for ReadFile. */
35337 #endif
35338 winFile *pFile = (winFile*)id; /* file handle */
35339 DWORD nRead; /* Number of bytes actually read from file */
35340 int nRetry = 0; /* Number of retrys */
@@ -35322,11 +35362,11 @@
35362 offset += nCopy;
35363 }
35364 }
35365 #endif
35366
35367 #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
35368 if( winSeekFile(pFile, offset) ){
35369 OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
35370 return SQLITE_FULL;
35371 }
35372 while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
@@ -35394,32 +35434,32 @@
35434 offset += nCopy;
35435 }
35436 }
35437 #endif
35438
35439 #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
35440 rc = winSeekFile(pFile, offset);
35441 if( rc==0 ){
35442 #else
35443 {
35444 #endif
35445 #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
35446 OVERLAPPED overlapped; /* The offset for WriteFile. */
35447 #endif
35448 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
35449 int nRem = amt; /* Number of bytes yet to be written */
35450 DWORD nWrite; /* Bytes written by each WriteFile() call */
35451 DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
35452
35453 #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
35454 memset(&overlapped, 0, sizeof(OVERLAPPED));
35455 overlapped.Offset = (LONG)(offset & 0xffffffff);
35456 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
35457 #endif
35458
35459 while( nRem>0 ){
35460 #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
35461 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
35462 #else
35463 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
35464 #endif
35465 if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
@@ -35428,11 +35468,11 @@
35468 assert( nWrite==0 || nWrite<=(DWORD)nRem );
35469 if( nWrite==0 || nWrite>(DWORD)nRem ){
35470 lastErrno = osGetLastError();
35471 break;
35472 }
35473 #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
35474 offset += nWrite;
35475 overlapped.Offset = (LONG)(offset & 0xffffffff);
35476 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
35477 #endif
35478 aRem += nWrite;
@@ -38974,11 +39014,12 @@
39014 SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
39015 assert( pCache->nRef==0 && pCache->pDirty==0 );
39016 if( pCache->szPage ){
39017 sqlite3_pcache *pNew;
39018 pNew = sqlite3GlobalConfig.pcache2.xCreate(
39019 szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)),
39020 pCache->bPurgeable
39021 );
39022 if( pNew==0 ) return SQLITE_NOMEM;
39023 sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
39024 if( pCache->pCache ){
39025 sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
@@ -39433,11 +39474,11 @@
39474
39475 /*
39476 ** Return the size of the header added by this middleware layer
39477 ** in the page-cache hierarchy.
39478 */
39479 SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
39480
39481
39482 #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
39483 /*
39484 ** For all dirty pages currently in the cache, invoke the specified
@@ -39749,11 +39790,11 @@
39790 pcache1Free(pPg);
39791 sqlite3_free(p);
39792 pPg = 0;
39793 }
39794 #else
39795 pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra);
39796 p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
39797 #endif
39798 pcache1EnterMutex(pCache->pGroup);
39799
39800 if( pPg ){
@@ -40437,11 +40478,11 @@
40478 }
40479
40480 /*
40481 ** Return the size of the header on each page of this PCACHE implementation.
40482 */
40483 SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
40484
40485 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
40486 /*
40487 ** This function is called to free superfluous dynamically allocated memory
40488 ** held by the pager system. Memory in use by any SQLite pager allocated
@@ -41795,10 +41836,12 @@
41836 u8 eLock; /* Current lock held on database file */
41837 u8 changeCountDone; /* Set after incrementing the change-counter */
41838 u8 setMaster; /* True if a m-j name has been written to jrnl */
41839 u8 doNotSpill; /* Do not spill the cache when non-zero */
41840 u8 subjInMemory; /* True to use in-memory sub-journals */
41841 u8 bUseFetch; /* True to use xFetch() */
41842 u8 hasBeenUsed; /* True if any content previously read from this pager*/
41843 Pgno dbSize; /* Number of pages in the database */
41844 Pgno dbOrigSize; /* dbSize before the current transaction */
41845 Pgno dbFileSize; /* Number of pages in the database file */
41846 Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */
41847 int errCode; /* One of several kinds of errors */
@@ -41812,13 +41855,13 @@
41855 i64 journalOff; /* Current write offset in the journal file */
41856 i64 journalHdr; /* Byte offset to previous journal header */
41857 sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
41858 PagerSavepoint *aSavepoint; /* Array of active savepoints */
41859 int nSavepoint; /* Number of elements in aSavepoint[] */
41860 u32 iDataVersion; /* Changes whenever database content changes */
41861 char dbFileVers[16]; /* Changes whenever database file changes */
41862
 
41863 int nMmapOut; /* Number of mmap pages currently outstanding */
41864 sqlite3_int64 szMmap; /* Desired maximum mmap size */
41865 PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */
41866 /*
41867 ** End of the routinely-changing class members
@@ -42830,13 +42873,22 @@
42873
42874 /*
42875 ** Discard the entire contents of the in-memory page-cache.
42876 */
42877 static void pager_reset(Pager *pPager){
42878 pPager->iDataVersion++;
42879 sqlite3BackupRestart(pPager->pBackup);
42880 sqlite3PcacheClear(pPager->pPCache);
42881 }
42882
42883 /*
42884 ** Return the pPager->iDataVersion value
42885 */
42886 SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){
42887 assert( pPager->eState>PAGER_OPEN );
42888 return pPager->iDataVersion;
42889 }
42890
42891 /*
42892 ** Free all structures in the Pager.aSavepoint[] array and set both
42893 ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
42894 ** if it is open and the pager is not in exclusive mode.
@@ -45036,11 +45088,11 @@
45088 Pgno pgno, /* Page number */
45089 void *pData, /* xFetch()'d data for this page */
45090 PgHdr **ppPage /* OUT: Acquired page object */
45091 ){
45092 PgHdr *p; /* Memory mapped page to return */
45093
45094 if( pPager->pMmapFreelist ){
45095 *ppPage = p = pPager->pMmapFreelist;
45096 pPager->pMmapFreelist = p->pDirty;
45097 p->pDirty = 0;
45098 memset(p->pExtra, 0, pPager->nExtra);
@@ -46267,20 +46319,16 @@
46319 assert( (pPager->eLock==SHARED_LOCK)
46320 || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
46321 );
46322 }
46323
46324 if( !pPager->tempFile && pPager->hasBeenUsed ){
46325 /* The shared-lock has just been acquired then check to
46326 ** see if the database has been modified. If the database has changed,
46327 ** flush the cache. The pPager->hasBeenUsed flag prevents this from
46328 ** occurring on the very first access to a file, in order to save a
46329 ** single unnecessary sqlite3OsRead() call at the start-up.
 
 
 
 
46330 **
46331 ** Database changes is detected by looking at 15 bytes beginning
46332 ** at offset 24 into the file. The first 4 of these 16 bytes are
46333 ** a 32-bit counter that is incremented with each change. The
46334 ** other bytes change randomly with each file change when
@@ -46441,10 +46489,11 @@
46489 assert( noContent==0 || bMmapOk==0 );
46490
46491 if( pgno==0 ){
46492 return SQLITE_CORRUPT_BKPT;
46493 }
46494 pPager->hasBeenUsed = 1;
46495
46496 /* If the pager is in the error state, return an error immediately.
46497 ** Otherwise, request the page from the PCache layer. */
46498 if( pPager->errCode!=SQLITE_OK ){
46499 rc = pPager->errCode;
@@ -46590,10 +46639,11 @@
46639 sqlite3_pcache_page *pPage;
46640 assert( pPager!=0 );
46641 assert( pgno!=0 );
46642 assert( pPager->pPCache!=0 );
46643 pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0);
46644 assert( pPage==0 || pPager->hasBeenUsed );
46645 return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage);
46646 }
46647
46648 /*
46649 ** Release a page reference.
@@ -47456,10 +47506,11 @@
47506 pPager->eState = PAGER_READER;
47507 return SQLITE_OK;
47508 }
47509
47510 PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
47511 pPager->iDataVersion++;
47512 rc = pager_end_transaction(pPager, pPager->setMaster, 1);
47513 return pager_error(pPager, rc);
47514 }
47515
47516 /*
@@ -50825,11 +50876,11 @@
50876 }
50877 nCollide = HASHTABLE_NSLOT;
50878 for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
50879 u32 iFrame = aHash[iKey] + iZero;
50880 if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){
50881 assert( iFrame>iRead || CORRUPT_DB );
50882 iRead = iFrame;
50883 }
50884 if( (nCollide--)==0 ){
50885 return SQLITE_CORRUPT_BKPT;
50886 }
@@ -51931,10 +51982,11 @@
51982 u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
51983 u8 sharable; /* True if we can share pBt with another db */
51984 u8 locked; /* True if db currently has pBt locked */
51985 int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
51986 int nBackup; /* Number of backup operations reading this btree */
51987 u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
51988 Btree *pNext; /* List of other sharable Btrees from the same db */
51989 Btree *pPrev; /* Back pointer of the same list */
51990 #ifndef SQLITE_OMIT_SHARED_CACHE
51991 BtLock lock; /* Object used to lock page 1 */
51992 #endif
@@ -56094,10 +56146,11 @@
56146 rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
56147 if( rc!=SQLITE_OK && bCleanup==0 ){
56148 sqlite3BtreeLeave(p);
56149 return rc;
56150 }
56151 p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
56152 pBt->inTransaction = TRANS_READ;
56153 btreeClearHasContent(pBt);
56154 }
56155
56156 btreeEndTransaction(p);
@@ -56457,11 +56510,11 @@
56510 }
56511 for(i=0; i<=pCur->iPage; i++){
56512 releasePage(pCur->apPage[i]);
56513 }
56514 unlockBtreeIfUnused(pBt);
56515 sqlite3_free(pCur->aOverflow);
56516 /* sqlite3_free(pCur); */
56517 sqlite3BtreeLeave(pBtree);
56518 }
56519 return SQLITE_OK;
56520 }
@@ -56751,10 +56804,11 @@
56804 pBuf += a;
56805 amt -= a;
56806 }else{
56807 offset -= pCur->info.nLocal;
56808 }
56809
56810
56811 if( rc==SQLITE_OK && amt>0 ){
56812 const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
56813 Pgno nextPage;
56814
@@ -56769,12 +56823,12 @@
56823 ** means "not yet known" (the cache is lazily populated).
56824 */
56825 if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
56826 int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
56827 if( nOvfl>pCur->nOvflAlloc ){
56828 Pgno *aNew = (Pgno*)sqlite3Realloc(
56829 pCur->aOverflow, nOvfl*2*sizeof(Pgno)
56830 );
56831 if( aNew==0 ){
56832 rc = SQLITE_NOMEM;
56833 }else{
56834 pCur->nOvflAlloc = nOvfl*2;
@@ -56817,10 +56871,11 @@
56871 ** Note that the aOverflow[] array must be allocated because eOp!=2
56872 ** here. If eOp==2, then offset==0 and this branch is never taken.
56873 */
56874 assert( eOp!=2 );
56875 assert( pCur->curFlags & BTCF_ValidOvfl );
56876 assert( pCur->pBtree->db==pBt->db );
56877 if( pCur->aOverflow[iIdx+1] ){
56878 nextPage = pCur->aOverflow[iIdx+1];
56879 }else{
56880 rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
56881 }
@@ -59329,11 +59384,11 @@
59384 + nMaxCells*sizeof(u16) /* szCell */
59385 + pBt->pageSize; /* aSpace1 */
59386
59387 /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer
59388 ** that is more than 6 times the database page size. */
59389 assert( szScratch<=6*(int)pBt->pageSize );
59390 apCell = sqlite3ScratchMalloc( szScratch );
59391 if( apCell==0 ){
59392 rc = SQLITE_NOMEM;
59393 goto balance_cleanup;
59394 }
@@ -59406,12 +59461,12 @@
59461 assert( leafCorrection==4 );
59462 if( szCell[nCell]<4 ){
59463 /* Do not allow any cells smaller than 4 bytes. If a smaller cell
59464 ** does exist, pad it with 0x00 bytes. */
59465 assert( szCell[nCell]==3 );
59466 assert( apCell[nCell]==&aSpace1[iSpace1-3] );
59467 aSpace1[iSpace1++] = 0x00;
59468 szCell[nCell] = 4;
59469 }
59470 }
59471 nCell++;
59472 }
@@ -60719,10 +60774,17 @@
60774 ** is read-only, the others are read/write.
60775 **
60776 ** The schema layer numbers meta values differently. At the schema
60777 ** layer (and the SetCookie and ReadCookie opcodes) the number of
60778 ** free pages is not visible. So Cookie[0] is the same as Meta[1].
60779 **
60780 ** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead
60781 ** of reading the value out of the header, it instead loads the "DataVersion"
60782 ** from the pager. The BTREE_DATA_VERSION value is not actually stored in the
60783 ** database file. It is a number computed by the pager. But its access
60784 ** pattern is the same as header meta values, and so it is convenient to
60785 ** read it from this routine.
60786 */
60787 SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
60788 BtShared *pBt = p->pBt;
60789
60790 sqlite3BtreeEnter(p);
@@ -60729,11 +60791,15 @@
60791 assert( p->inTrans>TRANS_NONE );
60792 assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
60793 assert( pBt->pPage1 );
60794 assert( idx>=0 && idx<=15 );
60795
60796 if( idx==BTREE_DATA_VERSION ){
60797 *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
60798 }else{
60799 *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
60800 }
60801
60802 /* If auto-vacuum is disabled in this build and this is an auto-vacuum
60803 ** database, mark the database as read-only. */
60804 #ifdef SQLITE_OMIT_AUTOVACUUM
60805 if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
@@ -60820,11 +60886,11 @@
60886 if( pPage->leaf ){
60887 do {
60888 if( pCur->iPage==0 ){
60889 /* All pages of the b-tree have been visited. Return successfully. */
60890 *pnEntry = nEntry;
60891 return moveToRoot(pCur);
60892 }
60893 moveToParent(pCur);
60894 }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
60895
60896 pCur->aiIdx[pCur->iPage]++;
@@ -61676,11 +61742,11 @@
61742 }
61743
61744 /*
61745 ** Return the size of the header added to each page by this module.
61746 */
61747 SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
61748
61749 /************** End of btree.c ***********************************************/
61750 /************** Begin file backup.c ******************************************/
61751 /*
61752 ** 2009 January 28
@@ -64440,36 +64506,39 @@
64506 **
64507 ** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
64508 */
64509 SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
64510 int hasAbort = 0;
64511 int hasFkCounter = 0;
64512 Op *pOp;
64513 VdbeOpIter sIter;
64514 memset(&sIter, 0, sizeof(sIter));
64515 sIter.v = v;
64516
64517 while( (pOp = opIterNext(&sIter))!=0 ){
64518 int opcode = pOp->opcode;
64519 if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
 
 
 
64520 || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
64521 && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
64522 ){
64523 hasAbort = 1;
64524 break;
64525 }
64526 #ifndef SQLITE_OMIT_FOREIGN_KEY
64527 if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
64528 hasFkCounter = 1;
64529 }
64530 #endif
64531 }
64532 sqlite3DbFree(v->db, sIter.apSub);
64533
64534 /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
64535 ** If malloc failed, then the while() loop above may not have iterated
64536 ** through all opcodes and hasAbort may be set incorrectly. Return
64537 ** true for this case to prevent the assert() in the callers frame
64538 ** from failing. */
64539 return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter );
64540 }
64541 #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
64542
64543 /*
64544 ** Loop through the program looking for P2 values that are negative
@@ -68589,11 +68658,14 @@
68658 #ifndef SQLITE_OMIT_WAL
68659 int i;
68660 for(i=0; i<db->nDb; i++){
68661 Btree *pBt = db->aDb[i].pBt;
68662 if( pBt ){
68663 int nEntry;
68664 sqlite3BtreeEnter(pBt);
68665 nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
68666 sqlite3BtreeLeave(pBt);
68667 if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
68668 rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
68669 }
68670 }
68671 }
@@ -68769,11 +68841,10 @@
68841 ** program counter to 0 to ensure that when the statement is
68842 ** finalized or reset the parser error message is available via
68843 ** sqlite3_errmsg() and sqlite3_errcode().
68844 */
68845 const char *zErr = (const char *)sqlite3_value_text(db->pErr);
 
68846 sqlite3DbFree(db, v->zErrMsg);
68847 if( !db->mallocFailed ){
68848 v->zErrMsg = sqlite3DbStrDup(db, zErr);
68849 v->rc = rc2;
68850 } else {
@@ -77131,11 +77202,11 @@
77202 /*
77203 ** Hard-coded maximum amount of data to accumulate in memory before flushing
77204 ** to a level 0 PMA. The purpose of this limit is to prevent various integer
77205 ** overflows. 512MiB.
77206 */
77207 #define SQLITE_MAX_PMASZ (1<<29)
77208
77209 /*
77210 ** Private objects used by the sorter
77211 */
77212 typedef struct MergeEngine MergeEngine; /* Merge PMAs together */
@@ -77427,13 +77498,10 @@
77498 **
77499 ** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; }
77500 */
77501 #define SRVAL(p) ((void*)((SorterRecord*)(p) + 1))
77502
 
 
 
77503
77504 /* Maximum number of PMAs that a single MergeEngine can merge */
77505 #define SORTER_MAX_MERGE_COUNT 16
77506
77507 static int vdbeIncrSwap(IncrMerger*);
@@ -77828,14 +77896,15 @@
77896 SortSubtask *pTask = &pSorter->aTask[i];
77897 pTask->pSorter = pSorter;
77898 }
77899
77900 if( !sqlite3TempInMemory(db) ){
77901 u32 szPma = sqlite3GlobalConfig.szPma;
77902 pSorter->mnPmaSize = szPma * pgsz;
77903 mxCache = db->aDb[0].pSchema->cache_size;
77904 if( mxCache<(int)szPma ) mxCache = (int)szPma;
77905 pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);
77906
77907 /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
77908 ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
77909 ** large heap allocations.
77910 */
@@ -78109,16 +78178,16 @@
78178 ** Whether or not the file does end up memory mapped of course depends on
78179 ** the specific VFS implementation.
78180 */
78181 static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
78182 if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
78183 void *p = 0;
78184 int chunksize = 4*1024;
78185 sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
78186 sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
78187 sqlite3OsFetch(pFd, 0, (int)nByte, &p);
78188 sqlite3OsUnfetch(pFd, 0, p);
78189 }
78190 }
78191 #else
78192 # define vdbeSorterExtendFile(x,y,z)
78193 #endif
@@ -87296,11 +87365,11 @@
87365
87366 p->iGet = -1;
87367 p->mxSample = mxSample;
87368 p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
87369 p->current.anLt = &p->current.anEq[nColUp];
87370 p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
87371
87372 /* Set up the Stat4Accum.a[] and aBest[] arrays */
87373 p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
87374 p->aBest = &p->a[mxSample];
87375 pSpace = (u8*)(&p->a[mxSample+nCol]);
@@ -88889,17 +88958,19 @@
88958 }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
88959 zErrDyn = sqlite3MPrintf(db,
88960 "attached databases must use the same text encoding as main database");
88961 rc = SQLITE_ERROR;
88962 }
88963 sqlite3BtreeEnter(aNew->pBt);
88964 pPager = sqlite3BtreePager(aNew->pBt);
88965 sqlite3PagerLockingMode(pPager, db->dfltLockMode);
88966 sqlite3BtreeSecureDelete(aNew->pBt,
88967 sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
88968 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
88969 sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
88970 #endif
88971 sqlite3BtreeLeave(aNew->pBt);
88972 }
88973 aNew->safety_level = 3;
88974 aNew->zName = sqlite3DbStrDup(db, zName);
88975 if( rc==SQLITE_OK && aNew->zName==0 ){
88976 rc = SQLITE_NOMEM;
@@ -90021,11 +90092,10 @@
90092 */
90093 static void freeIndex(sqlite3 *db, Index *p){
90094 #ifndef SQLITE_OMIT_ANALYZE
90095 sqlite3DeleteIndexSamples(db, p);
90096 #endif
 
90097 sqlite3ExprDelete(db, p->pPartIdxWhere);
90098 sqlite3DbFree(db, p->zColAff);
90099 if( p->isResized ) sqlite3DbFree(db, p->azColl);
90100 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
90101 sqlite3_free(p->aiRowEst);
@@ -91300,10 +91370,23 @@
91370 if( pPk==0 ) return;
91371 pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
91372 pTab->iPKey = -1;
91373 }else{
91374 pPk = sqlite3PrimaryKeyIndex(pTab);
91375 /*
91376 ** Remove all redundant columns from the PRIMARY KEY. For example, change
91377 ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
91378 ** code assumes the PRIMARY KEY contains no repeated columns.
91379 */
91380 for(i=j=1; i<pPk->nKeyCol; i++){
91381 if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){
91382 pPk->nColumn--;
91383 }else{
91384 pPk->aiColumn[j++] = pPk->aiColumn[i];
91385 }
91386 }
91387 pPk->nKeyCol = j;
91388 }
91389 pPk->isCovering = 1;
91390 assert( pPk!=0 );
91391 nPk = pPk->nKeyCol;
91392
@@ -93776,44 +93859,35 @@
93859 **
93860 ** The caller should invoke sqlite3KeyInfoUnref() on the returned object
93861 ** when it has finished using it.
93862 */
93863 SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
93864 int i;
93865 int nCol = pIdx->nColumn;
93866 int nKey = pIdx->nKeyCol;
93867 KeyInfo *pKey;
93868 if( pParse->nErr ) return 0;
93869 if( pIdx->uniqNotNull ){
93870 pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
93871 }else{
93872 pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
93873 }
93874 if( pKey ){
93875 assert( sqlite3KeyInfoIsWriteable(pKey) );
93876 for(i=0; i<nCol; i++){
93877 char *zColl = pIdx->azColl[i];
93878 assert( zColl!=0 );
93879 pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
93880 sqlite3LocateCollSeq(pParse, zColl);
93881 pKey->aSortOrder[i] = pIdx->aSortOrder[i];
93882 }
93883 if( pParse->nErr ){
93884 sqlite3KeyInfoUnref(pKey);
93885 pKey = 0;
93886 }
93887 }
93888 return pKey;
 
 
 
 
 
 
 
 
 
 
 
 
 
93889 }
93890
93891 #ifndef SQLITE_OMIT_CTE
93892 /*
93893 ** This routine is invoked once per CTE by the parser while parsing a
@@ -97430,11 +97504,11 @@
97504 assert( nIncr==1 );
97505 sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
97506 OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
97507 }else{
97508 if( nIncr>0 && pFKey->isDeferred==0 ){
97509 sqlite3MayAbort(pParse);
97510 }
97511 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
97512 }
97513
97514 sqlite3VdbeResolveLabel(v, iOk);
@@ -97501,10 +97575,14 @@
97575 ** This function is called to generate code executed when a row is deleted
97576 ** from the parent table of foreign key constraint pFKey and, if pFKey is
97577 ** deferred, when a row is inserted into the same table. When generating
97578 ** code for an SQL UPDATE operation, this function may be called twice -
97579 ** once to "delete" the old row and once to "insert" the new row.
97580 **
97581 ** Parameter nIncr is passed -1 when inserting a row (as this may decrease
97582 ** the number of FK violations in the db) or +1 when deleting one (as this
97583 ** may increase the number of FK constraint problems).
97584 **
97585 ** The code generated by this function scans through the rows in the child
97586 ** table that correspond to the parent table row being deleted or inserted.
97587 ** For each child row found, one of the following actions is taken:
97588 **
@@ -97618,17 +97696,13 @@
97696 sNameContext.pSrcList = pSrc;
97697 sNameContext.pParse = pParse;
97698 sqlite3ResolveExprNames(&sNameContext, pWhere);
97699
97700 /* Create VDBE to loop through the entries in pSrc that match the WHERE
97701 ** clause. For each row found, increment either the deferred or immediate
97702 ** foreign key constraint counter. */
 
97703 pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
 
 
 
97704 sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
97705 if( pWInfo ){
97706 sqlite3WhereEnd(pWInfo);
97707 }
97708
@@ -97802,10 +97876,28 @@
97876 }
97877 }
97878 }
97879 return 0;
97880 }
97881
97882 /*
97883 ** Return true if the parser passed as the first argument is being
97884 ** used to code a trigger that is really a "SET NULL" action belonging
97885 ** to trigger pFKey.
97886 */
97887 static int isSetNullAction(Parse *pParse, FKey *pFKey){
97888 Parse *pTop = sqlite3ParseToplevel(pParse);
97889 if( pTop->pTriggerPrg ){
97890 Trigger *p = pTop->pTriggerPrg->pTrigger;
97891 if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull)
97892 || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull)
97893 ){
97894 return 1;
97895 }
97896 }
97897 return 0;
97898 }
97899
97900 /*
97901 ** This function is called when inserting, deleting or updating a row of
97902 ** table pTab to generate VDBE code to perform foreign key constraint
97903 ** processing for the operation.
@@ -97855,11 +97947,11 @@
97947 Index *pIdx = 0; /* Index on key columns in pTo */
97948 int *aiFree = 0;
97949 int *aiCol;
97950 int iCol;
97951 int i;
97952 int bIgnore = 0;
97953
97954 if( aChange
97955 && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
97956 && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0
97957 ){
@@ -97914,11 +98006,11 @@
98006 ** values read from the parent table are NULL. */
98007 if( db->xAuth ){
98008 int rcauth;
98009 char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
98010 rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
98011 bIgnore = (rcauth==SQLITE_IGNORE);
98012 }
98013 #endif
98014 }
98015
98016 /* Take a shared-cache advisory read-lock on the parent table. Allocate
@@ -97929,16 +98021,22 @@
98021
98022 if( regOld!=0 ){
98023 /* A row is being removed from the child table. Search for the parent.
98024 ** If the parent does not exist, removing the child row resolves an
98025 ** outstanding foreign key constraint violation. */
98026 fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore);
98027 }
98028 if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){
98029 /* A row is being added to the child table. If a parent row cannot
98030 ** be found, adding the child row has violated the FK constraint.
98031 **
98032 ** If this operation is being performed as part of a trigger program
98033 ** that is actually a "SET NULL" action belonging to this very
98034 ** foreign key, then omit this scan altogether. As all child key
98035 ** values are guaranteed to be NULL, it is not possible for adding
98036 ** this row to cause an FK violation. */
98037 fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore);
98038 }
98039
98040 sqlite3DbFree(db, aiFree);
98041 }
98042
@@ -97955,12 +98053,12 @@
98053
98054 if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs)
98055 && !pParse->pToplevel && !pParse->isMultiWrite
98056 ){
98057 assert( regOld==0 && regNew!=0 );
98058 /* Inserting a single row into a parent table cannot cause (or fix)
98059 ** an immediate foreign key violation. So do nothing in this case. */
98060 continue;
98061 }
98062
98063 if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
98064 if( !isIgnoreErrors || db->mallocFailed ) return;
@@ -97980,17 +98078,32 @@
98078
98079 if( regNew!=0 ){
98080 fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
98081 }
98082 if( regOld!=0 ){
98083 int eAction = pFKey->aAction[aChange!=0];
 
 
 
 
 
98084 fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);
98085 /* If this is a deferred FK constraint, or a CASCADE or SET NULL
98086 ** action applies, then any foreign key violations caused by
98087 ** removing the parent key will be rectified by the action trigger.
98088 ** So do not set the "may-abort" flag in this case.
98089 **
98090 ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the
98091 ** may-abort flag will eventually be set on this statement anyway
98092 ** (when this function is called as part of processing the UPDATE
98093 ** within the action trigger).
98094 **
98095 ** Note 2: At first glance it may seem like SQLite could simply omit
98096 ** all OP_FkCounter related scans when either CASCADE or SET NULL
98097 ** applies. The trouble starts if the CASCADE or SET NULL action
98098 ** trigger causes other triggers or action rules attached to the
98099 ** child table to fire. In these cases the fk constraint counters
98100 ** might be set incorrectly if any OP_FkCounter related scans are
98101 ** omitted. */
98102 if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){
98103 sqlite3MayAbort(pParse);
98104 }
98105 }
98106 pItem->zName = 0;
98107 sqlite3SrcListDelete(db, pSrc);
98108 }
98109 sqlite3DbFree(db, aiCol);
@@ -101080,11 +101193,10 @@
101193 # define sqlite3_column_database_name16 0
101194 # define sqlite3_column_table_name 0
101195 # define sqlite3_column_table_name16 0
101196 # define sqlite3_column_origin_name 0
101197 # define sqlite3_column_origin_name16 0
 
101198 #endif
101199
101200 #ifdef SQLITE_OMIT_AUTHORIZATION
101201 # define sqlite3_set_authorizer 0
101202 #endif
@@ -101890,10 +102002,11 @@
102002 #define PragTyp_KEY 38
102003 #define PragTyp_REKEY 39
102004 #define PragTyp_LOCK_STATUS 40
102005 #define PragTyp_PARSER_TRACE 41
102006 #define PragFlag_NeedSchema 0x01
102007 #define PragFlag_ReadOnly 0x02
102008 static const struct sPragmaNames {
102009 const char *const zName; /* Name of pragma */
102010 u8 ePragTyp; /* PragTyp_XXX value */
102011 u8 mPragFlag; /* Zero or more PragFlag_XXX values */
102012 u32 iArg; /* Extra argument */
@@ -101906,11 +102019,11 @@
102019 #endif
102020 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102021 { /* zName: */ "application_id",
102022 /* ePragTyp: */ PragTyp_HEADER_VALUE,
102023 /* ePragFlag: */ 0,
102024 /* iArg: */ BTREE_APPLICATION_ID },
102025 #endif
102026 #if !defined(SQLITE_OMIT_AUTOVACUUM)
102027 { /* zName: */ "auto_vacuum",
102028 /* ePragTyp: */ PragTyp_AUTO_VACUUM,
102029 /* ePragFlag: */ PragFlag_NeedSchema,
@@ -101972,10 +102085,16 @@
102085 { /* zName: */ "data_store_directory",
102086 /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
102087 /* ePragFlag: */ 0,
102088 /* iArg: */ 0 },
102089 #endif
102090 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102091 { /* zName: */ "data_version",
102092 /* ePragTyp: */ PragTyp_HEADER_VALUE,
102093 /* ePragFlag: */ PragFlag_ReadOnly,
102094 /* iArg: */ BTREE_DATA_VERSION },
102095 #endif
102096 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
102097 { /* zName: */ "database_list",
102098 /* ePragTyp: */ PragTyp_DATABASE_LIST,
102099 /* ePragFlag: */ PragFlag_NeedSchema,
102100 /* iArg: */ 0 },
@@ -102027,12 +102146,12 @@
102146 #endif
102147 #endif
102148 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102149 { /* zName: */ "freelist_count",
102150 /* ePragTyp: */ PragTyp_HEADER_VALUE,
102151 /* ePragFlag: */ PragFlag_ReadOnly,
102152 /* iArg: */ BTREE_FREE_PAGE_COUNT },
102153 #endif
102154 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
102155 { /* zName: */ "full_column_names",
102156 /* ePragTyp: */ PragTyp_FLAG,
102157 /* ePragFlag: */ 0,
@@ -102180,11 +102299,11 @@
102299 #endif
102300 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102301 { /* zName: */ "schema_version",
102302 /* ePragTyp: */ PragTyp_HEADER_VALUE,
102303 /* ePragFlag: */ 0,
102304 /* iArg: */ BTREE_SCHEMA_VERSION },
102305 #endif
102306 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
102307 { /* zName: */ "secure_delete",
102308 /* ePragTyp: */ PragTyp_SECURE_DELETE,
102309 /* ePragFlag: */ 0,
@@ -102246,11 +102365,11 @@
102365 /* iArg: */ 0 },
102366 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
102367 { /* zName: */ "user_version",
102368 /* ePragTyp: */ PragTyp_HEADER_VALUE,
102369 /* ePragFlag: */ 0,
102370 /* iArg: */ BTREE_USER_VERSION },
102371 #endif
102372 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
102373 #if defined(SQLITE_DEBUG)
102374 { /* zName: */ "vdbe_addoptrace",
102375 /* ePragTyp: */ PragTyp_FLAG,
@@ -102289,11 +102408,11 @@
102408 /* ePragTyp: */ PragTyp_FLAG,
102409 /* ePragFlag: */ 0,
102410 /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
102411 #endif
102412 };
102413 /* Number of pragmas: 58 on by default, 71 total. */
102414 /* End of the automatically generated pragma table.
102415 ***************************************************************************/
102416
102417 /*
102418 ** Interpret the given string as a safety level. Return 0 for OFF,
@@ -103899,11 +104018,12 @@
104018 !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
104019 DbHasProperty(db, 0, DB_Empty)
104020 ){
104021 for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
104022 if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
104023 SCHEMA_ENC(db) = ENC(db) =
104024 pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
104025 break;
104026 }
104027 }
104028 if( !pEnc->zName ){
104029 sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight);
@@ -103944,28 +104064,13 @@
104064 **
104065 ** The user-version is not used internally by SQLite. It may be used by
104066 ** applications for any purpose.
104067 */
104068 case PragTyp_HEADER_VALUE: {
104069 int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */
104070 sqlite3VdbeUsesBtree(v, iDb);
104071 if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104072 /* Write the specified cookie value */
104073 static const VdbeOpList setCookie[] = {
104074 { OP_Transaction, 0, 1, 0}, /* 0 */
104075 { OP_Integer, 0, 1, 0}, /* 1 */
104076 { OP_SetCookie, 0, 0, 1}, /* 2 */
@@ -104607,13 +104712,15 @@
104712 SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
104713 int i, rc;
104714 int commit_internal = !(db->flags&SQLITE_InternChanges);
104715
104716 assert( sqlite3_mutex_held(db->mutex) );
104717 assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
104718 assert( db->init.busy==0 );
104719 rc = SQLITE_OK;
104720 db->init.busy = 1;
104721 ENC(db) = SCHEMA_ENC(db);
104722 for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
104723 if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
104724 rc = sqlite3InitOne(db, i, pzErrMsg);
104725 if( rc ){
104726 sqlite3ResetOneSchema(db, i);
@@ -110751,11 +110858,11 @@
110858 ){
110859 int rc;
110860 TabResult res;
110861
110862 #ifdef SQLITE_ENABLE_API_ARMOR
110863 if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT;
110864 #endif
110865 *pazResult = 0;
110866 if( pnColumn ) *pnColumn = 0;
110867 if( pnRow ) *pnRow = 0;
110868 if( pzErrMsg ) *pzErrMsg = 0;
@@ -118621,11 +118728,10 @@
118728 sqlite3_free(p->u.vtab.idxStr);
118729 p->u.vtab.needFree = 0;
118730 p->u.vtab.idxStr = 0;
118731 }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
118732 sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
 
118733 sqlite3DbFree(db, p->u.btree.pIndex);
118734 p->u.btree.pIndex = 0;
118735 }
118736 }
118737 }
@@ -125628,10 +125734,13 @@
125734 u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */
125735 sqlite3 *db = pParse->db; /* The database connection */
125736 int mxSqlLen; /* Max length of an SQL string */
125737
125738
125739 #ifdef SQLITE_ENABLE_API_ARMOR
125740 if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT;
125741 #endif
125742 mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
125743 if( db->nVdbeActive==0 ){
125744 db->u1.isInterrupted = 0;
125745 }
125746 pParse->rc = SQLITE_OK;
@@ -125866,17 +125975,10 @@
125975 */
125976 SQLITE_API int sqlite3_complete(const char *zSql){
125977 u8 state = 0; /* Current state, using numbers defined in header comment */
125978 u8 token; /* Value of the next token */
125979
 
 
 
 
 
 
 
125980 #ifndef SQLITE_OMIT_TRIGGER
125981 /* A complex statement machine used to detect the end of a CREATE TRIGGER
125982 ** statement. This is the normal case.
125983 */
125984 static const u8 trans[8][8] = {
@@ -125901,10 +126003,17 @@
126003 /* 0 INVALID: */ { 1, 0, 2, },
126004 /* 1 START: */ { 1, 1, 2, },
126005 /* 2 NORMAL: */ { 1, 2, 2, },
126006 };
126007 #endif /* SQLITE_OMIT_TRIGGER */
126008
126009 #ifdef SQLITE_ENABLE_API_ARMOR
126010 if( zSql==0 ){
126011 (void)SQLITE_MISUSE_BKPT;
126012 return 0;
126013 }
126014 #endif
126015
126016 while( *zSql ){
126017 switch( *zSql ){
126018 case ';': { /* A semicolon */
126019 token = tkSEMI;
@@ -126203,11 +126312,11 @@
126312 ** If the following function pointer is not NULL and if
126313 ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
126314 ** I/O active are written using this function. These messages
126315 ** are intended for debugging activity only.
126316 */
126317 /* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0;
126318 #endif
126319
126320 /*
126321 ** If the following global variable points to a string which is the
126322 ** name of a directory, then that directory will be used to store
@@ -126412,10 +126521,17 @@
126521 ** routine is not threadsafe. But it is safe to invoke this routine
126522 ** on when SQLite is already shut down. If SQLite is already shut down
126523 ** when this routine is invoked, then this routine is a harmless no-op.
126524 */
126525 SQLITE_API int sqlite3_shutdown(void){
126526 #ifdef SQLITE_OMIT_WSD
126527 int rc = sqlite3_wsd_init(4096, 24);
126528 if( rc!=SQLITE_OK ){
126529 return rc;
126530 }
126531 #endif
126532
126533 if( sqlite3GlobalConfig.isInit ){
126534 #ifdef SQLITE_EXTRA_SHUTDOWN
126535 void SQLITE_EXTRA_SHUTDOWN(void);
126536 SQLITE_EXTRA_SHUTDOWN();
126537 #endif
@@ -126727,10 +126843,15 @@
126843 ** heap. */
126844 sqlite3GlobalConfig.nHeap = va_arg(ap, int);
126845 break;
126846 }
126847 #endif
126848
126849 case SQLITE_CONFIG_PMASZ: {
126850 sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int);
126851 break;
126852 }
126853
126854 default: {
126855 rc = SQLITE_ERROR;
126856 break;
126857 }
@@ -127173,18 +127294,10 @@
127294
127295 /* Close all database connections */
127296 for(j=0; j<db->nDb; j++){
127297 struct Db *pDb = &db->aDb[j];
127298 if( pDb->pBt ){
 
 
 
 
 
 
 
 
127299 sqlite3BtreeClose(pDb->pBt);
127300 pDb->pBt = 0;
127301 if( j!=1 ){
127302 pDb->pSchema = 0;
127303 }
@@ -128308,36 +128421,10 @@
128421 */
128422 SQLITE_API const char *sqlite3_errstr(int rc){
128423 return sqlite3ErrStr(rc);
128424 }
128425
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128426 /*
128427 ** Create a new collating function for database "db". The name is zName
128428 ** and the encoding is enc.
128429 */
128430 static int createCollation(
@@ -128377,11 +128464,10 @@
128464 sqlite3ErrorWithMsg(db, SQLITE_BUSY,
128465 "unable to delete/modify collation sequence due to active statements");
128466 return SQLITE_BUSY;
128467 }
128468 sqlite3ExpirePreparedStatements(db);
 
128469
128470 /* If collation sequence pColl was created directly by a call to
128471 ** sqlite3_create_collation, and not generated by synthCollSeq(),
128472 ** then any copies made by synthCollSeq() need to be invalidated.
128473 ** Also, collation destructor - CollSeq.xDel() - function may need
@@ -128882,10 +128968,13 @@
128968 | SQLITE_RecTriggers
128969 #endif
128970 #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS
128971 | SQLITE_ForeignKeys
128972 #endif
128973 #if defined(SQLITE_REVERSE_UNORDERED_SELECTS)
128974 | SQLITE_ReverseOrder
128975 #endif
128976 ;
128977 sqlite3HashInit(&db->aCollSeq);
128978 #ifndef SQLITE_OMIT_VIRTUALTABLE
128979 sqlite3HashInit(&db->aModule);
128980 #endif
@@ -128929,11 +129018,14 @@
129018 rc = SQLITE_NOMEM;
129019 }
129020 sqlite3Error(db, rc);
129021 goto opendb_out;
129022 }
129023 sqlite3BtreeEnter(db->aDb[0].pBt);
129024 db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
129025 if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db);
129026 sqlite3BtreeLeave(db->aDb[0].pBt);
129027 db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
129028
129029 /* The default safety_level for the main database is 'full'; for the temp
129030 ** database it is 'NONE'. This matches the pager layer defaults.
129031 */
@@ -129087,11 +129179,11 @@
129179 if( zFilename8 ){
129180 rc = openDatabase(zFilename8, ppDb,
129181 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
129182 assert( *ppDb || rc==SQLITE_NOMEM );
129183 if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
129184 SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE;
129185 }
129186 }else{
129187 rc = SQLITE_NOMEM;
129188 }
129189 sqlite3ValueFree(pVal);
@@ -129283,11 +129375,10 @@
129375
129376 /*
129377 ** Return meta information about a specific column of a database table.
129378 ** See comment in sqlite3.h (sqlite.h.in) for details.
129379 */
 
129380 SQLITE_API int sqlite3_table_column_metadata(
129381 sqlite3 *db, /* Connection handle */
129382 const char *zDbName, /* Database name or NULL */
129383 const char *zTableName, /* Table name */
129384 const char *zColumnName, /* Column name */
@@ -129323,25 +129414,27 @@
129414 pTab = 0;
129415 goto error_out;
129416 }
129417
129418 /* Find the column for which info is requested */
129419 if( zColumnName==0 ){
129420 /* Query for existance of table only */
 
 
 
129421 }else{
129422 for(iCol=0; iCol<pTab->nCol; iCol++){
129423 pCol = &pTab->aCol[iCol];
129424 if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
129425 break;
129426 }
129427 }
129428 if( iCol==pTab->nCol ){
129429 if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){
129430 iCol = pTab->iPKey;
129431 pCol = iCol>=0 ? &pTab->aCol[iCol] : 0;
129432 }else{
129433 pTab = 0;
129434 goto error_out;
129435 }
129436 }
129437 }
129438
129439 /* The following block stores the meta information that will be returned
129440 ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey
@@ -129390,11 +129483,10 @@
129483 sqlite3DbFree(db, zErrMsg);
129484 rc = sqlite3ApiExit(db, rc);
129485 sqlite3_mutex_leave(db->mutex);
129486 return rc;
129487 }
 
129488
129489 /*
129490 ** Sleep for a little while. Return the amount of time slept.
129491 */
129492 SQLITE_API int sqlite3_sleep(int ms){
@@ -129829,32 +129921,34 @@
129921 /*
129922 ** Return the filename of the database associated with a database
129923 ** connection.
129924 */
129925 SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
129926 Btree *pBt;
129927 #ifdef SQLITE_ENABLE_API_ARMOR
129928 if( !sqlite3SafetyCheckOk(db) ){
129929 (void)SQLITE_MISUSE_BKPT;
129930 return 0;
129931 }
129932 #endif
129933 pBt = sqlite3DbNameToBtree(db, zDbName);
129934 return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
129935 }
129936
129937 /*
129938 ** Return 1 if database is read-only or 0 if read/write. Return -1 if
129939 ** no such database exists.
129940 */
129941 SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
129942 Btree *pBt;
129943 #ifdef SQLITE_ENABLE_API_ARMOR
129944 if( !sqlite3SafetyCheckOk(db) ){
129945 (void)SQLITE_MISUSE_BKPT;
129946 return -1;
129947 }
129948 #endif
129949 pBt = sqlite3DbNameToBtree(db, zDbName);
129950 return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
129951 }
129952
129953 /************** End of main.c ************************************************/
129954 /************** Begin file notify.c ******************************************/
@@ -150061,11 +150155,11 @@
150155 }
150156 i = pCur->nPoint++;
150157 pNew = pCur->aPoint + i;
150158 pNew->rScore = rScore;
150159 pNew->iLevel = iLevel;
150160 assert( iLevel<=RTREE_MAX_DEPTH );
150161 while( i>0 ){
150162 RtreeSearchPoint *pParent;
150163 j = (i-1)/2;
150164 pParent = pCur->aPoint + j;
150165 if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break;
150166
+40 -26
--- 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.8.8"
111111
#define SQLITE_VERSION_NUMBER 3008008
112
-#define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0"
112
+#define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -199,11 +199,11 @@
199199
** This interface only reports on the compile-time mutex setting
200200
** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
201201
** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
202202
** can be fully or partially disabled using a call to [sqlite3_config()]
203203
** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
204
-** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the
204
+** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the
205205
** sqlite3_threadsafe() function shows only the compile-time setting of
206206
** thread safety, not any run-time changes to that setting made by
207207
** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
208208
** is unchanged by calls to sqlite3_config().)^
209209
**
@@ -1568,11 +1568,11 @@
15681568
** configuration option.
15691569
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
15701570
** 8-byte aligned
15711571
** memory, the size of each page buffer (sz), and the number of pages (N).
15721572
** The sz argument should be the size of the largest database page
1573
-** (a power of two between 512 and 32768) plus some extra bytes for each
1573
+** (a power of two between 512 and 65536) plus some extra bytes for each
15741574
** page header. ^The number of extra bytes needed by the page header
15751575
** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
15761576
** to [sqlite3_config()].
15771577
** ^It is harmless, apart from the wasted memory,
15781578
** for the sz parameter to be larger than necessary. The first
@@ -1748,10 +1748,21 @@
17481748
** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
17491749
** is a pointer to an integer and writes into that integer the number of extra
17501750
** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
17511751
** The amount of extra space required can change depending on the compiler,
17521752
** target platform, and SQLite version.
1753
+**
1754
+** [[SQLITE_CONFIG_PMASZ]]
1755
+** <dt>SQLITE_CONFIG_PMASZ
1756
+** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which
1757
+** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded
1758
+** sorter to that integer. The default minimum PMA Size is set by the
1759
+** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched
1760
+** to help with sort operations when multithreaded sorting
1761
+** is enabled (using the [PRAGMA threads] command) and the amount of content
1762
+** to be sorted exceeds the page size times the minimum of the
1763
+** [PRAGMA cache_size] setting and this value.
17531764
** </dl>
17541765
*/
17551766
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
17561767
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
17571768
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1774,10 +1785,11 @@
17741785
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
17751786
#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
17761787
#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
17771788
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
17781789
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
1790
+#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
17791791
17801792
/*
17811793
** CAPI3REF: Database Connection Configuration Options
17821794
**
17831795
** These constants are the available integer configuration options that
@@ -5155,24 +5167,31 @@
51555167
51565168
51575169
/*
51585170
** CAPI3REF: Extract Metadata About A Column Of A Table
51595171
**
5160
-** ^This routine returns metadata about a specific column of a specific
5161
-** database table accessible using the [database connection] handle
5162
-** passed as the first function argument.
5172
+** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
5173
+** information about column C of table T in database D
5174
+** on [database connection] X.)^ ^The sqlite3_table_column_metadata()
5175
+** interface returns SQLITE_OK and fills in the non-NULL pointers in
5176
+** the final five arguments with appropriate values if the specified
5177
+** column exists. ^The sqlite3_table_column_metadata() interface returns
5178
+** SQLITE_ERROR and if the specified column does not exist.
5179
+** ^If the column-name parameter to sqlite3_table_column_metadata() is a
5180
+** NULL pointer, then this routine simply checks for the existance of the
5181
+** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
5182
+** does not.
51635183
**
51645184
** ^The column is identified by the second, third and fourth parameters to
5165
-** this function. ^The second parameter is either the name of the database
5185
+** this function. ^(The second parameter is either the name of the database
51665186
** (i.e. "main", "temp", or an attached database) containing the specified
5167
-** table or NULL. ^If it is NULL, then all attached databases are searched
5187
+** table or NULL.)^ ^If it is NULL, then all attached databases are searched
51685188
** for the table using the same algorithm used by the database engine to
51695189
** resolve unqualified table references.
51705190
**
51715191
** ^The third and fourth parameters to this function are the table and column
5172
-** name of the desired column, respectively. Neither of these parameters
5173
-** may be NULL.
5192
+** name of the desired column, respectively.
51745193
**
51755194
** ^Metadata is returned by writing to the memory locations passed as the 5th
51765195
** and subsequent parameters to this function. ^Any of these arguments may be
51775196
** NULL, in which case the corresponding element of metadata is omitted.
51785197
**
@@ -5187,36 +5206,33 @@
51875206
** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
51885207
** </table>
51895208
** </blockquote>)^
51905209
**
51915210
** ^The memory pointed to by the character pointers returned for the
5192
-** declaration type and collation sequence is valid only until the next
5211
+** declaration type and collation sequence is valid until the next
51935212
** call to any SQLite API function.
51945213
**
51955214
** ^If the specified table is actually a view, an [error code] is returned.
51965215
**
5197
-** ^If the specified column is "rowid", "oid" or "_rowid_" and an
5216
+** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
5217
+** is not a [WITHOUT ROWID] table and an
51985218
** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
51995219
** parameters are set for the explicitly declared column. ^(If there is no
5200
-** explicitly declared [INTEGER PRIMARY KEY] column, then the output
5201
-** parameters are set as follows:
5220
+** [INTEGER PRIMARY KEY] column, then the outputs
5221
+** for the [rowid] are set as follows:
52025222
**
52035223
** <pre>
52045224
** data type: "INTEGER"
52055225
** collation sequence: "BINARY"
52065226
** not null: 0
52075227
** primary key: 1
52085228
** auto increment: 0
52095229
** </pre>)^
52105230
**
5211
-** ^(This function may load one or more schemas from database files. If an
5212
-** error occurs during this process, or if the requested table or column
5213
-** cannot be found, an [error code] is returned and an error message left
5214
-** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^
5215
-**
5216
-** ^This API is only available if the library was compiled with the
5217
-** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
5231
+** ^This function causes all database schemas to be read from disk and
5232
+** parsed, if that has not already been done, and returns an error if
5233
+** any errors are encountered while loading the schema.
52185234
*/
52195235
SQLITE_API int sqlite3_table_column_metadata(
52205236
sqlite3 *db, /* Connection handle */
52215237
const char *zDbName, /* Database name or NULL */
52225238
const char *zTableName, /* Table name */
@@ -7179,16 +7195,14 @@
71797195
71807196
/*
71817197
** CAPI3REF: Write-Ahead Log Commit Hook
71827198
**
71837199
** ^The [sqlite3_wal_hook()] function is used to register a callback that
7184
-** will be invoked each time a database connection commits data to a
7185
-** [write-ahead log] (i.e. whenever a transaction is committed in
7186
-** [journal_mode | journal_mode=WAL mode]).
7200
+** is invoked each time data is committed to a database in wal mode.
71877201
**
7188
-** ^The callback is invoked by SQLite after the commit has taken place and
7189
-** the associated write-lock on the database released, so the implementation
7202
+** ^(The callback is invoked by SQLite after the commit has taken place and
7203
+** the associated write-lock on the database released)^, so the implementation
71907204
** may read, write or [checkpoint] the database as required.
71917205
**
71927206
** ^The first parameter passed to the callback function when it is invoked
71937207
** is a copy of the third parameter passed to sqlite3_wal_hook() when
71947208
** registering the callback. ^The second is a copy of the database handle.
71957209
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.8"
111 #define SQLITE_VERSION_NUMBER 3008008
112 #define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -199,11 +199,11 @@
199 ** This interface only reports on the compile-time mutex setting
200 ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
201 ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
202 ** can be fully or partially disabled using a call to [sqlite3_config()]
203 ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
204 ** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the
205 ** sqlite3_threadsafe() function shows only the compile-time setting of
206 ** thread safety, not any run-time changes to that setting made by
207 ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
208 ** is unchanged by calls to sqlite3_config().)^
209 **
@@ -1568,11 +1568,11 @@
1568 ** configuration option.
1569 ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
1570 ** 8-byte aligned
1571 ** memory, the size of each page buffer (sz), and the number of pages (N).
1572 ** The sz argument should be the size of the largest database page
1573 ** (a power of two between 512 and 32768) plus some extra bytes for each
1574 ** page header. ^The number of extra bytes needed by the page header
1575 ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
1576 ** to [sqlite3_config()].
1577 ** ^It is harmless, apart from the wasted memory,
1578 ** for the sz parameter to be larger than necessary. The first
@@ -1748,10 +1748,21 @@
1748 ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
1749 ** is a pointer to an integer and writes into that integer the number of extra
1750 ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
1751 ** The amount of extra space required can change depending on the compiler,
1752 ** target platform, and SQLite version.
 
 
 
 
 
 
 
 
 
 
 
1753 ** </dl>
1754 */
1755 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1756 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1757 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1774,10 +1785,11 @@
1774 #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
1775 #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
1776 #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
1777 #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
1778 #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
 
1779
1780 /*
1781 ** CAPI3REF: Database Connection Configuration Options
1782 **
1783 ** These constants are the available integer configuration options that
@@ -5155,24 +5167,31 @@
5155
5156
5157 /*
5158 ** CAPI3REF: Extract Metadata About A Column Of A Table
5159 **
5160 ** ^This routine returns metadata about a specific column of a specific
5161 ** database table accessible using the [database connection] handle
5162 ** passed as the first function argument.
 
 
 
 
 
 
 
 
5163 **
5164 ** ^The column is identified by the second, third and fourth parameters to
5165 ** this function. ^The second parameter is either the name of the database
5166 ** (i.e. "main", "temp", or an attached database) containing the specified
5167 ** table or NULL. ^If it is NULL, then all attached databases are searched
5168 ** for the table using the same algorithm used by the database engine to
5169 ** resolve unqualified table references.
5170 **
5171 ** ^The third and fourth parameters to this function are the table and column
5172 ** name of the desired column, respectively. Neither of these parameters
5173 ** may be NULL.
5174 **
5175 ** ^Metadata is returned by writing to the memory locations passed as the 5th
5176 ** and subsequent parameters to this function. ^Any of these arguments may be
5177 ** NULL, in which case the corresponding element of metadata is omitted.
5178 **
@@ -5187,36 +5206,33 @@
5187 ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
5188 ** </table>
5189 ** </blockquote>)^
5190 **
5191 ** ^The memory pointed to by the character pointers returned for the
5192 ** declaration type and collation sequence is valid only until the next
5193 ** call to any SQLite API function.
5194 **
5195 ** ^If the specified table is actually a view, an [error code] is returned.
5196 **
5197 ** ^If the specified column is "rowid", "oid" or "_rowid_" and an
 
5198 ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
5199 ** parameters are set for the explicitly declared column. ^(If there is no
5200 ** explicitly declared [INTEGER PRIMARY KEY] column, then the output
5201 ** parameters are set as follows:
5202 **
5203 ** <pre>
5204 ** data type: "INTEGER"
5205 ** collation sequence: "BINARY"
5206 ** not null: 0
5207 ** primary key: 1
5208 ** auto increment: 0
5209 ** </pre>)^
5210 **
5211 ** ^(This function may load one or more schemas from database files. If an
5212 ** error occurs during this process, or if the requested table or column
5213 ** cannot be found, an [error code] is returned and an error message left
5214 ** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^
5215 **
5216 ** ^This API is only available if the library was compiled with the
5217 ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
5218 */
5219 SQLITE_API int sqlite3_table_column_metadata(
5220 sqlite3 *db, /* Connection handle */
5221 const char *zDbName, /* Database name or NULL */
5222 const char *zTableName, /* Table name */
@@ -7179,16 +7195,14 @@
7179
7180 /*
7181 ** CAPI3REF: Write-Ahead Log Commit Hook
7182 **
7183 ** ^The [sqlite3_wal_hook()] function is used to register a callback that
7184 ** will be invoked each time a database connection commits data to a
7185 ** [write-ahead log] (i.e. whenever a transaction is committed in
7186 ** [journal_mode | journal_mode=WAL mode]).
7187 **
7188 ** ^The callback is invoked by SQLite after the commit has taken place and
7189 ** the associated write-lock on the database released, so the implementation
7190 ** may read, write or [checkpoint] the database as required.
7191 **
7192 ** ^The first parameter passed to the callback function when it is invoked
7193 ** is a copy of the third parameter passed to sqlite3_wal_hook() when
7194 ** registering the callback. ^The second is a copy of the database handle.
7195
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.8"
111 #define SQLITE_VERSION_NUMBER 3008008
112 #define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -199,11 +199,11 @@
199 ** This interface only reports on the compile-time mutex setting
200 ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
201 ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
202 ** can be fully or partially disabled using a call to [sqlite3_config()]
203 ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
204 ** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the
205 ** sqlite3_threadsafe() function shows only the compile-time setting of
206 ** thread safety, not any run-time changes to that setting made by
207 ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
208 ** is unchanged by calls to sqlite3_config().)^
209 **
@@ -1568,11 +1568,11 @@
1568 ** configuration option.
1569 ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
1570 ** 8-byte aligned
1571 ** memory, the size of each page buffer (sz), and the number of pages (N).
1572 ** The sz argument should be the size of the largest database page
1573 ** (a power of two between 512 and 65536) plus some extra bytes for each
1574 ** page header. ^The number of extra bytes needed by the page header
1575 ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
1576 ** to [sqlite3_config()].
1577 ** ^It is harmless, apart from the wasted memory,
1578 ** for the sz parameter to be larger than necessary. The first
@@ -1748,10 +1748,21 @@
1748 ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
1749 ** is a pointer to an integer and writes into that integer the number of extra
1750 ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
1751 ** The amount of extra space required can change depending on the compiler,
1752 ** target platform, and SQLite version.
1753 **
1754 ** [[SQLITE_CONFIG_PMASZ]]
1755 ** <dt>SQLITE_CONFIG_PMASZ
1756 ** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which
1757 ** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded
1758 ** sorter to that integer. The default minimum PMA Size is set by the
1759 ** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched
1760 ** to help with sort operations when multithreaded sorting
1761 ** is enabled (using the [PRAGMA threads] command) and the amount of content
1762 ** to be sorted exceeds the page size times the minimum of the
1763 ** [PRAGMA cache_size] setting and this value.
1764 ** </dl>
1765 */
1766 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1767 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1768 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1774,10 +1785,11 @@
1785 #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
1786 #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
1787 #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
1788 #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
1789 #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
1790 #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
1791
1792 /*
1793 ** CAPI3REF: Database Connection Configuration Options
1794 **
1795 ** These constants are the available integer configuration options that
@@ -5155,24 +5167,31 @@
5167
5168
5169 /*
5170 ** CAPI3REF: Extract Metadata About A Column Of A Table
5171 **
5172 ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
5173 ** information about column C of table T in database D
5174 ** on [database connection] X.)^ ^The sqlite3_table_column_metadata()
5175 ** interface returns SQLITE_OK and fills in the non-NULL pointers in
5176 ** the final five arguments with appropriate values if the specified
5177 ** column exists. ^The sqlite3_table_column_metadata() interface returns
5178 ** SQLITE_ERROR and if the specified column does not exist.
5179 ** ^If the column-name parameter to sqlite3_table_column_metadata() is a
5180 ** NULL pointer, then this routine simply checks for the existance of the
5181 ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
5182 ** does not.
5183 **
5184 ** ^The column is identified by the second, third and fourth parameters to
5185 ** this function. ^(The second parameter is either the name of the database
5186 ** (i.e. "main", "temp", or an attached database) containing the specified
5187 ** table or NULL.)^ ^If it is NULL, then all attached databases are searched
5188 ** for the table using the same algorithm used by the database engine to
5189 ** resolve unqualified table references.
5190 **
5191 ** ^The third and fourth parameters to this function are the table and column
5192 ** name of the desired column, respectively.
 
5193 **
5194 ** ^Metadata is returned by writing to the memory locations passed as the 5th
5195 ** and subsequent parameters to this function. ^Any of these arguments may be
5196 ** NULL, in which case the corresponding element of metadata is omitted.
5197 **
@@ -5187,36 +5206,33 @@
5206 ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
5207 ** </table>
5208 ** </blockquote>)^
5209 **
5210 ** ^The memory pointed to by the character pointers returned for the
5211 ** declaration type and collation sequence is valid until the next
5212 ** call to any SQLite API function.
5213 **
5214 ** ^If the specified table is actually a view, an [error code] is returned.
5215 **
5216 ** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
5217 ** is not a [WITHOUT ROWID] table and an
5218 ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
5219 ** parameters are set for the explicitly declared column. ^(If there is no
5220 ** [INTEGER PRIMARY KEY] column, then the outputs
5221 ** for the [rowid] are set as follows:
5222 **
5223 ** <pre>
5224 ** data type: "INTEGER"
5225 ** collation sequence: "BINARY"
5226 ** not null: 0
5227 ** primary key: 1
5228 ** auto increment: 0
5229 ** </pre>)^
5230 **
5231 ** ^This function causes all database schemas to be read from disk and
5232 ** parsed, if that has not already been done, and returns an error if
5233 ** any errors are encountered while loading the schema.
 
 
 
 
5234 */
5235 SQLITE_API int sqlite3_table_column_metadata(
5236 sqlite3 *db, /* Connection handle */
5237 const char *zDbName, /* Database name or NULL */
5238 const char *zTableName, /* Table name */
@@ -7179,16 +7195,14 @@
7195
7196 /*
7197 ** CAPI3REF: Write-Ahead Log Commit Hook
7198 **
7199 ** ^The [sqlite3_wal_hook()] function is used to register a callback that
7200 ** is invoked each time data is committed to a database in wal mode.
 
 
7201 **
7202 ** ^(The callback is invoked by SQLite after the commit has taken place and
7203 ** the associated write-lock on the database released)^, so the implementation
7204 ** may read, write or [checkpoint] the database as required.
7205 **
7206 ** ^The first parameter passed to the callback function when it is invoked
7207 ** is a copy of the third parameter passed to sqlite3_wal_hook() when
7208 ** registering the callback. ^The second is a copy of the database handle.
7209
+1 -1
--- src/stat.c
+++ src/stat.c
@@ -77,11 +77,11 @@
7777
if( n>0 ){
7878
int a, b;
7979
Stmt q;
8080
@ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
8181
db_prepare(&q, "SELECT total(size), avg(size), max(size)"
82
- " FROM blob WHERE size>0");
82
+ " FROM blob WHERE size>0 /*scan*/");
8383
db_step(&q);
8484
t = db_column_int64(&q, 0);
8585
szAvg = db_column_int(&q, 1);
8686
szMax = db_column_int(&q, 2);
8787
db_finalize(&q);
8888
--- src/stat.c
+++ src/stat.c
@@ -77,11 +77,11 @@
77 if( n>0 ){
78 int a, b;
79 Stmt q;
80 @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
81 db_prepare(&q, "SELECT total(size), avg(size), max(size)"
82 " FROM blob WHERE size>0");
83 db_step(&q);
84 t = db_column_int64(&q, 0);
85 szAvg = db_column_int(&q, 1);
86 szMax = db_column_int(&q, 2);
87 db_finalize(&q);
88
--- src/stat.c
+++ src/stat.c
@@ -77,11 +77,11 @@
77 if( n>0 ){
78 int a, b;
79 Stmt q;
80 @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
81 db_prepare(&q, "SELECT total(size), avg(size), max(size)"
82 " FROM blob WHERE size>0 /*scan*/");
83 db_step(&q);
84 t = db_column_int64(&q, 0);
85 szAvg = db_column_int(&q, 1);
86 szMax = db_column_int(&q, 2);
87 db_finalize(&q);
88
+79 -4
--- src/style.c
+++ src/style.c
@@ -783,10 +783,15 @@
783783
{ ".filetree",
784784
"tree-view file browser",
785785
@ margin: 1em 0;
786786
@ line-height: 1.5;
787787
},
788
+ {
789
+ ".filetree > ul",
790
+ "tree-view top-level list",
791
+ @ display: inline-block;
792
+ },
788793
{ ".filetree ul",
789794
"tree-view lists",
790795
@ margin: 0;
791796
@ padding: 0;
792797
@ list-style: none;
@@ -832,21 +837,37 @@
832837
},
833838
{ ".filetree a",
834839
"tree-view links",
835840
@ position: relative;
836841
@ z-index: 1;
837
- @ display: inline-block;
842
+ @ display: table-cell;
838843
@ min-height: 16px;
839844
@ padding-left: 21px;
840845
@ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==);
841846
@ background-position: center left;
842847
@ background-repeat: no-repeat;
843848
},
844
- { ".filetree .dir > a",
849
+ { "div.filetreeline",
850
+ "line of a file tree",
851
+ @ display: table;
852
+ @ width: 100%;
853
+ @ white-space: nowrap;
854
+ },
855
+ { ".filetree .dir > div.filetreeline > a",
845856
"tree-view directory links",
846857
@ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=);
847858
},
859
+ { "div.filetreeage",
860
+ "Last change floating display on the right",
861
+ @ display: table-cell;
862
+ @ padding-left: 3em;
863
+ @ text-align: right;
864
+ },
865
+ { "div.filetreeline:hover",
866
+ "Highlight the line of a file tree",
867
+ @ background-color: #eee;
868
+ },
848869
{ "table.login_out",
849870
"table format for login/out label/input table",
850871
@ text-align: left;
851872
@ margin-right: 10px;
852873
@ margin-left: 10px;
@@ -1211,17 +1232,71 @@
12111232
@ color: black;
12121233
@ background-color: white;
12131234
},
12141235
{ "table.adminLogTable",
12151236
"Class for the /admin_log table",
1216
- @ text-align: left
1237
+ @ text-align: left;
12171238
},
12181239
{ ".adminLogTable .adminTime",
12191240
"Class for the /admin_log table",
1220
- @ text-align: left
1241
+ @ text-align: left;
1242
+ @ vertical-align: top;
1243
+ @ white-space: nowrap;
1244
+ },
1245
+ { ".fileage table",
1246
+ "The fileage table",
1247
+ @ border-spacing: 0;
1248
+ },
1249
+ { ".fileage tr:hover",
1250
+ "Mouse-over effects for the file-age table",
1251
+ @ background-color: #eee;
1252
+ },
1253
+ { ".fileage td",
1254
+ "fileage table cells",
12211255
@ vertical-align: top;
1256
+ @ text-align: left;
1257
+ @ border-top: 1px solid #ddd;
1258
+ @ padding-top: 3px;
1259
+ },
1260
+ { ".fileage td:first-child",
1261
+ "fileage first column (the age)",
12221262
@ white-space: nowrap;
1263
+ },
1264
+ { ".fileage td:nth-child(2)",
1265
+ "fileage second column (the filename)",
1266
+ @ padding-left: 1em;
1267
+ @ padding-right: 1em;
1268
+ },
1269
+ { ".fileage td:nth-child(3)",
1270
+ "fileage third column (the check-in comment)",
1271
+ @ word-break: break-all;
1272
+ @ word-wrap: break-word;
1273
+ @ max-width: 50%;
1274
+ },
1275
+ { ".brlist table", "The list of branches",
1276
+ @ border-spacing: 0;
1277
+ },
1278
+ { ".brlist table th", "Branch list table headers",
1279
+ @ text-align: left;
1280
+ @ padding: 0px 1em 0.5ex 0px;
1281
+ },
1282
+ { ".brlist table td", "Branch list table headers",
1283
+ @ padding: 0px 2em 0px 0px;
1284
+ },
1285
+ { "th.sort:after",
1286
+ "General styles for sortable column marker",
1287
+ @ margin-left: .4em;
1288
+ @ cursor: pointer;
1289
+ @ text-shadow: 0 0 0 #000; /* Makes arrow darker */
1290
+ },
1291
+ { "th.sort.asc:after",
1292
+ "Ascending sort column marker",
1293
+ @ content: '\2193';
1294
+ },
1295
+ { "th.sort.desc:after",
1296
+ "Descending sort column marker",
1297
+ @ content: '\2191';
12231298
},
12241299
{ 0,
12251300
0,
12261301
0
12271302
}
12281303
--- src/style.c
+++ src/style.c
@@ -783,10 +783,15 @@
783 { ".filetree",
784 "tree-view file browser",
785 @ margin: 1em 0;
786 @ line-height: 1.5;
787 },
 
 
 
 
 
788 { ".filetree ul",
789 "tree-view lists",
790 @ margin: 0;
791 @ padding: 0;
792 @ list-style: none;
@@ -832,21 +837,37 @@
832 },
833 { ".filetree a",
834 "tree-view links",
835 @ position: relative;
836 @ z-index: 1;
837 @ display: inline-block;
838 @ min-height: 16px;
839 @ padding-left: 21px;
840 @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==);
841 @ background-position: center left;
842 @ background-repeat: no-repeat;
843 },
844 { ".filetree .dir > a",
 
 
 
 
 
 
845 "tree-view directory links",
846 @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=);
847 },
 
 
 
 
 
 
 
 
 
 
848 { "table.login_out",
849 "table format for login/out label/input table",
850 @ text-align: left;
851 @ margin-right: 10px;
852 @ margin-left: 10px;
@@ -1211,17 +1232,71 @@
1211 @ color: black;
1212 @ background-color: white;
1213 },
1214 { "table.adminLogTable",
1215 "Class for the /admin_log table",
1216 @ text-align: left
1217 },
1218 { ".adminLogTable .adminTime",
1219 "Class for the /admin_log table",
1220 @ text-align: left
 
 
 
 
 
 
 
 
 
 
 
 
 
1221 @ vertical-align: top;
 
 
 
 
 
 
1222 @ white-space: nowrap;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1223 },
1224 { 0,
1225 0,
1226 0
1227 }
1228
--- src/style.c
+++ src/style.c
@@ -783,10 +783,15 @@
783 { ".filetree",
784 "tree-view file browser",
785 @ margin: 1em 0;
786 @ line-height: 1.5;
787 },
788 {
789 ".filetree > ul",
790 "tree-view top-level list",
791 @ display: inline-block;
792 },
793 { ".filetree ul",
794 "tree-view lists",
795 @ margin: 0;
796 @ padding: 0;
797 @ list-style: none;
@@ -832,21 +837,37 @@
837 },
838 { ".filetree a",
839 "tree-view links",
840 @ position: relative;
841 @ z-index: 1;
842 @ display: table-cell;
843 @ min-height: 16px;
844 @ padding-left: 21px;
845 @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==);
846 @ background-position: center left;
847 @ background-repeat: no-repeat;
848 },
849 { "div.filetreeline",
850 "line of a file tree",
851 @ display: table;
852 @ width: 100%;
853 @ white-space: nowrap;
854 },
855 { ".filetree .dir > div.filetreeline > a",
856 "tree-view directory links",
857 @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=);
858 },
859 { "div.filetreeage",
860 "Last change floating display on the right",
861 @ display: table-cell;
862 @ padding-left: 3em;
863 @ text-align: right;
864 },
865 { "div.filetreeline:hover",
866 "Highlight the line of a file tree",
867 @ background-color: #eee;
868 },
869 { "table.login_out",
870 "table format for login/out label/input table",
871 @ text-align: left;
872 @ margin-right: 10px;
873 @ margin-left: 10px;
@@ -1211,17 +1232,71 @@
1232 @ color: black;
1233 @ background-color: white;
1234 },
1235 { "table.adminLogTable",
1236 "Class for the /admin_log table",
1237 @ text-align: left;
1238 },
1239 { ".adminLogTable .adminTime",
1240 "Class for the /admin_log table",
1241 @ text-align: left;
1242 @ vertical-align: top;
1243 @ white-space: nowrap;
1244 },
1245 { ".fileage table",
1246 "The fileage table",
1247 @ border-spacing: 0;
1248 },
1249 { ".fileage tr:hover",
1250 "Mouse-over effects for the file-age table",
1251 @ background-color: #eee;
1252 },
1253 { ".fileage td",
1254 "fileage table cells",
1255 @ vertical-align: top;
1256 @ text-align: left;
1257 @ border-top: 1px solid #ddd;
1258 @ padding-top: 3px;
1259 },
1260 { ".fileage td:first-child",
1261 "fileage first column (the age)",
1262 @ white-space: nowrap;
1263 },
1264 { ".fileage td:nth-child(2)",
1265 "fileage second column (the filename)",
1266 @ padding-left: 1em;
1267 @ padding-right: 1em;
1268 },
1269 { ".fileage td:nth-child(3)",
1270 "fileage third column (the check-in comment)",
1271 @ word-break: break-all;
1272 @ word-wrap: break-word;
1273 @ max-width: 50%;
1274 },
1275 { ".brlist table", "The list of branches",
1276 @ border-spacing: 0;
1277 },
1278 { ".brlist table th", "Branch list table headers",
1279 @ text-align: left;
1280 @ padding: 0px 1em 0.5ex 0px;
1281 },
1282 { ".brlist table td", "Branch list table headers",
1283 @ padding: 0px 2em 0px 0px;
1284 },
1285 { "th.sort:after",
1286 "General styles for sortable column marker",
1287 @ margin-left: .4em;
1288 @ cursor: pointer;
1289 @ text-shadow: 0 0 0 #000; /* Makes arrow darker */
1290 },
1291 { "th.sort.asc:after",
1292 "Ascending sort column marker",
1293 @ content: '\2193';
1294 },
1295 { "th.sort.desc:after",
1296 "Descending sort column marker",
1297 @ content: '\2191';
1298 },
1299 { 0,
1300 0,
1301 0
1302 }
1303
+18 -12
--- src/timeline.c
+++ src/timeline.c
@@ -87,10 +87,11 @@
8787
#define TIMELINE_FCHANGES 0x0020 /* Detail file changes */
8888
#define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */
8989
#define TIMELINE_UCOLOR 0x0080 /* Background color by user */
9090
#define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
9191
#define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
92
+#define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */
9293
#endif
9394
9495
/*
9596
** Hash a string and use the hash to determine a background color.
9697
*/
@@ -404,10 +405,13 @@
404405
}
405406
}else if( zType[0]=='e' && tagid ){
406407
hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
407408
}else if( (tmFlags & TIMELINE_ARTID)!=0 ){
408409
hyperlink_to_uuid(zUuid);
410
+ }
411
+ if( tmFlags & TIMELINE_SHOWRID ){
412
+ @ (%d(rid))
409413
}
410414
db_column_blob(pQuery, commentColumn, &comment);
411415
if( zType[0]!='c' ){
412416
/* Comments for anything other than a check-in are generated by
413417
** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
@@ -604,12 +608,12 @@
604608
** for the upward portion of a merge arrow. The merge arrow goes up
605609
** to the row identified by mu:. If this value is zero then
606610
** node has no merge children and no merge-out line is drawn.
607611
** mu: The id of the row which is the top of the merge-out arrow.
608612
** u: Draw a thick child-line out of the top of this node and up to
609
- ** the node with an id equal to this value. 0 if there is no
610
- ** thick-line riser.
613
+ ** the node with an id equal to this value. 0 if it is straight to
614
+ ** the top of the page, -1 if there is no thick-line riser.
611615
** f: 0x01: a leaf node.
612616
** au: An array of integers that define thick-line risers for branches.
613617
** The integers are in pairs. For each pair, the first integer is
614618
** is the rail on which the riser should run and the second integer
615619
** is the id of the node upto which the riser should run.
@@ -1070,11 +1074,11 @@
10701074
const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */
10711075
const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/
10721076
int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
10731077
int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */
10741078
int tagid; /* Tag ID */
1075
- int tmFlags; /* Timeline flags */
1079
+ int tmFlags = 0; /* Timeline flags */
10761080
const char *zThisTag = 0; /* Suppress links to this tag */
10771081
const char *zThisUser = 0; /* Suppress links to this user */
10781082
HQuery url; /* URL for various branch links */
10791083
int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
10801084
int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */
@@ -1110,13 +1114,13 @@
11101114
){
11111115
zCirca = zBefore = zAfter = 0;
11121116
nEntry = -1;
11131117
}
11141118
if( zType[0]=='a' ){
1115
- tmFlags = TIMELINE_BRIEF | TIMELINE_GRAPH;
1119
+ tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH;
11161120
}else{
1117
- tmFlags = TIMELINE_GRAPH;
1121
+ tmFlags |= TIMELINE_GRAPH;
11181122
}
11191123
if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry));
11201124
if( P("ng")!=0 || zSearch!=0 ){
11211125
tmFlags &= ~TIMELINE_GRAPH;
11221126
url_add_parameter(&url, "ng", 0);
@@ -1206,10 +1210,11 @@
12061210
}else if( (p_rid || d_rid) && g.perm.Read ){
12071211
/* If p= or d= is present, ignore all other parameters other than n= */
12081212
char *zUuid;
12091213
int np, nd;
12101214
1215
+ tmFlags |= TIMELINE_DISJOINT;
12111216
if( p_rid && d_rid ){
12121217
if( p_rid!=d_rid ) p_rid = d_rid;
12131218
if( P("n")==0 ) nEntry = 10;
12141219
}
12151220
db_multi_exec(
@@ -1460,11 +1465,11 @@
14601465
n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/");
14611466
if( zYearMonth ){
14621467
blob_appendf(&desc, "%s events for %h", zEType, zYearMonth);
14631468
}else if( zYearWeek ){
14641469
blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek);
1465
- }else if( zAfter==0 && zBefore==0 && zCirca==0 && nEntry>0 ){
1470
+ }else if( zAfter==0 && zBefore==0 && zCirca==0 && n>=nEntry && nEntry>0 ){
14661471
blob_appendf(&desc, "%d most recent %ss", n, zEType);
14671472
}else{
14681473
blob_appendf(&desc, "%d %ss", n, zEType);
14691474
}
14701475
if( zUses ){
@@ -1511,11 +1516,11 @@
15111516
}
15121517
if( zBefore || (zAfter && n==nEntry) ){
15131518
zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
15141519
timeline_submenu(&url, "Newer", "a", zDate, "b");
15151520
free(zDate);
1516
- }else if( tagid==0 ){
1521
+ }else if( tagid==0 && zUses==0 ){
15171522
if( zType[0]!='a' ){
15181523
timeline_submenu(&url, "All Types", "y", "all", 0);
15191524
}
15201525
if( zType[0]!='w' && g.perm.RdWiki ){
15211526
timeline_submenu(&url, "Wiki Only", "y", "w", 0);
@@ -1552,10 +1557,11 @@
15521557
}
15531558
}
15541559
if( P("showsql") ){
15551560
@ <blockquote>%h(blob_sql_text(&sql))</blockquote>
15561561
}
1562
+ if( P("showrid") ) tmFlags |= TIMELINE_SHOWRID;
15571563
blob_zero(&sql);
15581564
db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
15591565
@ <h2>%b(&desc)</h2>
15601566
blob_reset(&desc);
15611567
www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
@@ -2393,11 +2399,11 @@
23932399
@ <br><div>Total events: %d(nEventTotal)
23942400
@ <br>Average per active %s(zAvgLabel): %d(nAvg)
23952401
@ </div>
23962402
}
23972403
if( !includeMonth ){
2398
- output_table_sorting_javascript("statsTable","tnx");
2404
+ output_table_sorting_javascript("statsTable","tnx",-1);
23992405
}
24002406
}
24012407
24022408
/*
24032409
** Implements the "byuser" view for /reports.
@@ -2444,11 +2450,11 @@
24442450
rowClass = ++nRowNumber % 2;
24452451
nEventTotal += nCount;
24462452
@<tr class='row%d(rowClass)'>
24472453
@ <td>
24482454
@ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2449
- @ </td><td>%d(nCount)</td>
2455
+ @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td>
24502456
@ <td>
24512457
@ <div class='statistics-report-graph-line'
24522458
@ style='width:%d(nSize)%%;'>&nbsp;</div>
24532459
@ </td>
24542460
@</tr>
@@ -2457,11 +2463,11 @@
24572463
use percent-based graph bars.
24582464
*/
24592465
}
24602466
@ </tbody></table>
24612467
db_finalize(&query);
2462
- output_table_sorting_javascript("statsTable","tnx");
2468
+ output_table_sorting_javascript("statsTable","tkx",2);
24632469
}
24642470
24652471
/*
24662472
** Implements the "byweekday" view for /reports.
24672473
*/
@@ -2522,11 +2528,11 @@
25222528
@ </td>
25232529
@</tr>
25242530
}
25252531
@ </tbody></table>
25262532
db_finalize(&query);
2527
- output_table_sorting_javascript("statsTable","ntnx");
2533
+ output_table_sorting_javascript("statsTable","ntnx",1);
25282534
}
25292535
25302536
25312537
/*
25322538
** Helper for stats_report_by_month_year(), which generates a list of
@@ -2655,11 +2661,11 @@
26552661
int nAvg = iterations ? (total/iterations) : 0;
26562662
cgi_printf("<br><div>Total events: %d<br>"
26572663
"Average per active week: %d</div>",
26582664
total, nAvg);
26592665
}
2660
- output_table_sorting_javascript("statsTable","tnx");
2666
+ output_table_sorting_javascript("statsTable","tnx",-1);
26612667
}
26622668
}
26632669
26642670
/*
26652671
** WEBPAGE: reports
26662672
--- src/timeline.c
+++ src/timeline.c
@@ -87,10 +87,11 @@
87 #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */
88 #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */
89 #define TIMELINE_UCOLOR 0x0080 /* Background color by user */
90 #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
91 #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
 
92 #endif
93
94 /*
95 ** Hash a string and use the hash to determine a background color.
96 */
@@ -404,10 +405,13 @@
404 }
405 }else if( zType[0]=='e' && tagid ){
406 hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
407 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
408 hyperlink_to_uuid(zUuid);
 
 
 
409 }
410 db_column_blob(pQuery, commentColumn, &comment);
411 if( zType[0]!='c' ){
412 /* Comments for anything other than a check-in are generated by
413 ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
@@ -604,12 +608,12 @@
604 ** for the upward portion of a merge arrow. The merge arrow goes up
605 ** to the row identified by mu:. If this value is zero then
606 ** node has no merge children and no merge-out line is drawn.
607 ** mu: The id of the row which is the top of the merge-out arrow.
608 ** u: Draw a thick child-line out of the top of this node and up to
609 ** the node with an id equal to this value. 0 if there is no
610 ** thick-line riser.
611 ** f: 0x01: a leaf node.
612 ** au: An array of integers that define thick-line risers for branches.
613 ** The integers are in pairs. For each pair, the first integer is
614 ** is the rail on which the riser should run and the second integer
615 ** is the id of the node upto which the riser should run.
@@ -1070,11 +1074,11 @@
1070 const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */
1071 const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/
1072 int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
1073 int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */
1074 int tagid; /* Tag ID */
1075 int tmFlags; /* Timeline flags */
1076 const char *zThisTag = 0; /* Suppress links to this tag */
1077 const char *zThisUser = 0; /* Suppress links to this user */
1078 HQuery url; /* URL for various branch links */
1079 int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
1080 int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */
@@ -1110,13 +1114,13 @@
1110 ){
1111 zCirca = zBefore = zAfter = 0;
1112 nEntry = -1;
1113 }
1114 if( zType[0]=='a' ){
1115 tmFlags = TIMELINE_BRIEF | TIMELINE_GRAPH;
1116 }else{
1117 tmFlags = TIMELINE_GRAPH;
1118 }
1119 if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry));
1120 if( P("ng")!=0 || zSearch!=0 ){
1121 tmFlags &= ~TIMELINE_GRAPH;
1122 url_add_parameter(&url, "ng", 0);
@@ -1206,10 +1210,11 @@
1206 }else if( (p_rid || d_rid) && g.perm.Read ){
1207 /* If p= or d= is present, ignore all other parameters other than n= */
1208 char *zUuid;
1209 int np, nd;
1210
 
1211 if( p_rid && d_rid ){
1212 if( p_rid!=d_rid ) p_rid = d_rid;
1213 if( P("n")==0 ) nEntry = 10;
1214 }
1215 db_multi_exec(
@@ -1460,11 +1465,11 @@
1460 n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/");
1461 if( zYearMonth ){
1462 blob_appendf(&desc, "%s events for %h", zEType, zYearMonth);
1463 }else if( zYearWeek ){
1464 blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek);
1465 }else if( zAfter==0 && zBefore==0 && zCirca==0 && nEntry>0 ){
1466 blob_appendf(&desc, "%d most recent %ss", n, zEType);
1467 }else{
1468 blob_appendf(&desc, "%d %ss", n, zEType);
1469 }
1470 if( zUses ){
@@ -1511,11 +1516,11 @@
1511 }
1512 if( zBefore || (zAfter && n==nEntry) ){
1513 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
1514 timeline_submenu(&url, "Newer", "a", zDate, "b");
1515 free(zDate);
1516 }else if( tagid==0 ){
1517 if( zType[0]!='a' ){
1518 timeline_submenu(&url, "All Types", "y", "all", 0);
1519 }
1520 if( zType[0]!='w' && g.perm.RdWiki ){
1521 timeline_submenu(&url, "Wiki Only", "y", "w", 0);
@@ -1552,10 +1557,11 @@
1552 }
1553 }
1554 if( P("showsql") ){
1555 @ <blockquote>%h(blob_sql_text(&sql))</blockquote>
1556 }
 
1557 blob_zero(&sql);
1558 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
1559 @ <h2>%b(&desc)</h2>
1560 blob_reset(&desc);
1561 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
@@ -2393,11 +2399,11 @@
2393 @ <br><div>Total events: %d(nEventTotal)
2394 @ <br>Average per active %s(zAvgLabel): %d(nAvg)
2395 @ </div>
2396 }
2397 if( !includeMonth ){
2398 output_table_sorting_javascript("statsTable","tnx");
2399 }
2400 }
2401
2402 /*
2403 ** Implements the "byuser" view for /reports.
@@ -2444,11 +2450,11 @@
2444 rowClass = ++nRowNumber % 2;
2445 nEventTotal += nCount;
2446 @<tr class='row%d(rowClass)'>
2447 @ <td>
2448 @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2449 @ </td><td>%d(nCount)</td>
2450 @ <td>
2451 @ <div class='statistics-report-graph-line'
2452 @ style='width:%d(nSize)%%;'>&nbsp;</div>
2453 @ </td>
2454 @</tr>
@@ -2457,11 +2463,11 @@
2457 use percent-based graph bars.
2458 */
2459 }
2460 @ </tbody></table>
2461 db_finalize(&query);
2462 output_table_sorting_javascript("statsTable","tnx");
2463 }
2464
2465 /*
2466 ** Implements the "byweekday" view for /reports.
2467 */
@@ -2522,11 +2528,11 @@
2522 @ </td>
2523 @</tr>
2524 }
2525 @ </tbody></table>
2526 db_finalize(&query);
2527 output_table_sorting_javascript("statsTable","ntnx");
2528 }
2529
2530
2531 /*
2532 ** Helper for stats_report_by_month_year(), which generates a list of
@@ -2655,11 +2661,11 @@
2655 int nAvg = iterations ? (total/iterations) : 0;
2656 cgi_printf("<br><div>Total events: %d<br>"
2657 "Average per active week: %d</div>",
2658 total, nAvg);
2659 }
2660 output_table_sorting_javascript("statsTable","tnx");
2661 }
2662 }
2663
2664 /*
2665 ** WEBPAGE: reports
2666
--- src/timeline.c
+++ src/timeline.c
@@ -87,10 +87,11 @@
87 #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */
88 #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */
89 #define TIMELINE_UCOLOR 0x0080 /* Background color by user */
90 #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
91 #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
92 #define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */
93 #endif
94
95 /*
96 ** Hash a string and use the hash to determine a background color.
97 */
@@ -404,10 +405,13 @@
405 }
406 }else if( zType[0]=='e' && tagid ){
407 hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
408 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
409 hyperlink_to_uuid(zUuid);
410 }
411 if( tmFlags & TIMELINE_SHOWRID ){
412 @ (%d(rid))
413 }
414 db_column_blob(pQuery, commentColumn, &comment);
415 if( zType[0]!='c' ){
416 /* Comments for anything other than a check-in are generated by
417 ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
@@ -604,12 +608,12 @@
608 ** for the upward portion of a merge arrow. The merge arrow goes up
609 ** to the row identified by mu:. If this value is zero then
610 ** node has no merge children and no merge-out line is drawn.
611 ** mu: The id of the row which is the top of the merge-out arrow.
612 ** u: Draw a thick child-line out of the top of this node and up to
613 ** the node with an id equal to this value. 0 if it is straight to
614 ** the top of the page, -1 if there is no thick-line riser.
615 ** f: 0x01: a leaf node.
616 ** au: An array of integers that define thick-line risers for branches.
617 ** The integers are in pairs. For each pair, the first integer is
618 ** is the rail on which the riser should run and the second integer
619 ** is the id of the node upto which the riser should run.
@@ -1070,11 +1074,11 @@
1074 const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */
1075 const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/
1076 int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
1077 int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */
1078 int tagid; /* Tag ID */
1079 int tmFlags = 0; /* Timeline flags */
1080 const char *zThisTag = 0; /* Suppress links to this tag */
1081 const char *zThisUser = 0; /* Suppress links to this user */
1082 HQuery url; /* URL for various branch links */
1083 int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
1084 int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */
@@ -1110,13 +1114,13 @@
1114 ){
1115 zCirca = zBefore = zAfter = 0;
1116 nEntry = -1;
1117 }
1118 if( zType[0]=='a' ){
1119 tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH;
1120 }else{
1121 tmFlags |= TIMELINE_GRAPH;
1122 }
1123 if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry));
1124 if( P("ng")!=0 || zSearch!=0 ){
1125 tmFlags &= ~TIMELINE_GRAPH;
1126 url_add_parameter(&url, "ng", 0);
@@ -1206,10 +1210,11 @@
1210 }else if( (p_rid || d_rid) && g.perm.Read ){
1211 /* If p= or d= is present, ignore all other parameters other than n= */
1212 char *zUuid;
1213 int np, nd;
1214
1215 tmFlags |= TIMELINE_DISJOINT;
1216 if( p_rid && d_rid ){
1217 if( p_rid!=d_rid ) p_rid = d_rid;
1218 if( P("n")==0 ) nEntry = 10;
1219 }
1220 db_multi_exec(
@@ -1460,11 +1465,11 @@
1465 n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/");
1466 if( zYearMonth ){
1467 blob_appendf(&desc, "%s events for %h", zEType, zYearMonth);
1468 }else if( zYearWeek ){
1469 blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek);
1470 }else if( zAfter==0 && zBefore==0 && zCirca==0 && n>=nEntry && nEntry>0 ){
1471 blob_appendf(&desc, "%d most recent %ss", n, zEType);
1472 }else{
1473 blob_appendf(&desc, "%d %ss", n, zEType);
1474 }
1475 if( zUses ){
@@ -1511,11 +1516,11 @@
1516 }
1517 if( zBefore || (zAfter && n==nEntry) ){
1518 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
1519 timeline_submenu(&url, "Newer", "a", zDate, "b");
1520 free(zDate);
1521 }else if( tagid==0 && zUses==0 ){
1522 if( zType[0]!='a' ){
1523 timeline_submenu(&url, "All Types", "y", "all", 0);
1524 }
1525 if( zType[0]!='w' && g.perm.RdWiki ){
1526 timeline_submenu(&url, "Wiki Only", "y", "w", 0);
@@ -1552,10 +1557,11 @@
1557 }
1558 }
1559 if( P("showsql") ){
1560 @ <blockquote>%h(blob_sql_text(&sql))</blockquote>
1561 }
1562 if( P("showrid") ) tmFlags |= TIMELINE_SHOWRID;
1563 blob_zero(&sql);
1564 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
1565 @ <h2>%b(&desc)</h2>
1566 blob_reset(&desc);
1567 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
@@ -2393,11 +2399,11 @@
2399 @ <br><div>Total events: %d(nEventTotal)
2400 @ <br>Average per active %s(zAvgLabel): %d(nAvg)
2401 @ </div>
2402 }
2403 if( !includeMonth ){
2404 output_table_sorting_javascript("statsTable","tnx",-1);
2405 }
2406 }
2407
2408 /*
2409 ** Implements the "byuser" view for /reports.
@@ -2444,11 +2450,11 @@
2450 rowClass = ++nRowNumber % 2;
2451 nEventTotal += nCount;
2452 @<tr class='row%d(rowClass)'>
2453 @ <td>
2454 @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2455 @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td>
2456 @ <td>
2457 @ <div class='statistics-report-graph-line'
2458 @ style='width:%d(nSize)%%;'>&nbsp;</div>
2459 @ </td>
2460 @</tr>
@@ -2457,11 +2463,11 @@
2463 use percent-based graph bars.
2464 */
2465 }
2466 @ </tbody></table>
2467 db_finalize(&query);
2468 output_table_sorting_javascript("statsTable","tkx",2);
2469 }
2470
2471 /*
2472 ** Implements the "byweekday" view for /reports.
2473 */
@@ -2522,11 +2528,11 @@
2528 @ </td>
2529 @</tr>
2530 }
2531 @ </tbody></table>
2532 db_finalize(&query);
2533 output_table_sorting_javascript("statsTable","ntnx",1);
2534 }
2535
2536
2537 /*
2538 ** Helper for stats_report_by_month_year(), which generates a list of
@@ -2655,11 +2661,11 @@
2661 int nAvg = iterations ? (total/iterations) : 0;
2662 cgi_printf("<br><div>Total events: %d<br>"
2663 "Average per active week: %d</div>",
2664 total, nAvg);
2665 }
2666 output_table_sorting_javascript("statsTable","tnx",-1);
2667 }
2668 }
2669
2670 /*
2671 ** WEBPAGE: reports
2672
+1 -3
--- src/undo.c
+++ src/undo.c
@@ -127,11 +127,10 @@
127127
** Undo or redo all undoable or redoable changes.
128128
*/
129129
static void undo_all(int redoFlag){
130130
int ucid;
131131
int ncid;
132
- const char *zDb = db_name("localdb");
133132
undo_all_filesystem(redoFlag);
134133
db_multi_exec(
135134
"CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;"
136135
"DELETE FROM vfile;"
137136
"INSERT INTO vfile SELECT * FROM undo_vfile;"
@@ -143,12 +142,11 @@
143142
"INSERT INTO vmerge SELECT * FROM undo_vmerge;"
144143
"DELETE FROM undo_vmerge;"
145144
"INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;"
146145
"DROP TABLE undo_vmerge_2;"
147146
);
148
- if(db_exists("SELECT 1 FROM \"%w\".sqlite_master"
149
- " WHERE name='undo_stash'", zDb) ){
147
+ if( db_table_exists("localdb", "undo_stash") ){
150148
if( redoFlag ){
151149
db_multi_exec(
152150
"DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);"
153151
"DELETE FROM stashfile"
154152
" WHERE stashid NOT IN (SELECT stashid FROM stash);"
155153
--- src/undo.c
+++ src/undo.c
@@ -127,11 +127,10 @@
127 ** Undo or redo all undoable or redoable changes.
128 */
129 static void undo_all(int redoFlag){
130 int ucid;
131 int ncid;
132 const char *zDb = db_name("localdb");
133 undo_all_filesystem(redoFlag);
134 db_multi_exec(
135 "CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;"
136 "DELETE FROM vfile;"
137 "INSERT INTO vfile SELECT * FROM undo_vfile;"
@@ -143,12 +142,11 @@
143 "INSERT INTO vmerge SELECT * FROM undo_vmerge;"
144 "DELETE FROM undo_vmerge;"
145 "INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;"
146 "DROP TABLE undo_vmerge_2;"
147 );
148 if(db_exists("SELECT 1 FROM \"%w\".sqlite_master"
149 " WHERE name='undo_stash'", zDb) ){
150 if( redoFlag ){
151 db_multi_exec(
152 "DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);"
153 "DELETE FROM stashfile"
154 " WHERE stashid NOT IN (SELECT stashid FROM stash);"
155
--- src/undo.c
+++ src/undo.c
@@ -127,11 +127,10 @@
127 ** Undo or redo all undoable or redoable changes.
128 */
129 static void undo_all(int redoFlag){
130 int ucid;
131 int ncid;
 
132 undo_all_filesystem(redoFlag);
133 db_multi_exec(
134 "CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;"
135 "DELETE FROM vfile;"
136 "INSERT INTO vfile SELECT * FROM undo_vfile;"
@@ -143,12 +142,11 @@
142 "INSERT INTO vmerge SELECT * FROM undo_vmerge;"
143 "DELETE FROM undo_vmerge;"
144 "INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;"
145 "DROP TABLE undo_vmerge_2;"
146 );
147 if( db_table_exists("localdb", "undo_stash") ){
 
148 if( redoFlag ){
149 db_multi_exec(
150 "DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);"
151 "DELETE FROM stashfile"
152 " WHERE stashid NOT IN (SELECT stashid FROM stash);"
153
+1 -1
--- src/xfer.c
+++ src/xfer.c
@@ -532,11 +532,11 @@
532532
** private artifacts if we are not doing a private transfer.
533533
*/
534534
static void request_phantoms(Xfer *pXfer, int maxReq){
535535
Stmt q;
536536
db_prepare(&q,
537
- "SELECT uuid FROM phantom JOIN blob USING(rid)"
537
+ "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/"
538538
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
539539
(pXfer->syncPrivate ? "" :
540540
" AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)")
541541
);
542542
while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){
543543
--- src/xfer.c
+++ src/xfer.c
@@ -532,11 +532,11 @@
532 ** private artifacts if we are not doing a private transfer.
533 */
534 static void request_phantoms(Xfer *pXfer, int maxReq){
535 Stmt q;
536 db_prepare(&q,
537 "SELECT uuid FROM phantom JOIN blob USING(rid)"
538 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
539 (pXfer->syncPrivate ? "" :
540 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)")
541 );
542 while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){
543
--- src/xfer.c
+++ src/xfer.c
@@ -532,11 +532,11 @@
532 ** private artifacts if we are not doing a private transfer.
533 */
534 static void request_phantoms(Xfer *pXfer, int maxReq){
535 Stmt q;
536 db_prepare(&q,
537 "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/"
538 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
539 (pXfer->syncPrivate ? "" :
540 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)")
541 );
542 while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){
543
--- test/valgrind-www.tcl
+++ test/valgrind-www.tcl
@@ -1,10 +1,10 @@
11
#!/usr/bin/tclsh
22
#
3
-# Run this script in an open Fossil checkout at the top-level with a
3
+# Run this script in an open Fossil checkout at the top-level with a
44
# fresh build of Fossil itself. This script will run fossil on hundreds
5
-# of different web-pages looking for memory allocation problems using
5
+# of different web-pages looking for memory allocation problems using
66
# valgrind. Valgrind output appears on stderr. Suggested test scenario:
77
#
88
# make
99
# tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt
1010
#
1111
--- test/valgrind-www.tcl
+++ test/valgrind-www.tcl
@@ -1,10 +1,10 @@
1 #!/usr/bin/tclsh
2 #
3 # Run this script in an open Fossil checkout at the top-level with a
4 # fresh build of Fossil itself. This script will run fossil on hundreds
5 # of different web-pages looking for memory allocation problems using
6 # valgrind. Valgrind output appears on stderr. Suggested test scenario:
7 #
8 # make
9 # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt
10 #
11
--- test/valgrind-www.tcl
+++ test/valgrind-www.tcl
@@ -1,10 +1,10 @@
1 #!/usr/bin/tclsh
2 #
3 # Run this script in an open Fossil checkout at the top-level with a
4 # fresh build of Fossil itself. This script will run fossil on hundreds
5 # of different web-pages looking for memory allocation problems using
6 # valgrind. Valgrind output appears on stderr. Suggested test scenario:
7 #
8 # make
9 # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt
10 #
11
--- tools/fossil_chat.tcl
+++ tools/fossil_chat.tcl
@@ -84,11 +84,11 @@
8484
catch {close $SOCKET}
8585
if {[catch {
8686
if {$::PROXYHOST ne {}} {
8787
set SOCKET [socket $::PROXYHOST $::PROXYPORT]
8888
puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1"
89
- puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT"
89
+ puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT"
9090
puts $SOCKET ""
9191
} else {
9292
set SOCKET [socket $::SERVERHOST $::SERVERPORT]
9393
}
9494
fconfigure $SOCKET -translation binary -blocking 0
@@ -142,11 +142,11 @@
142142
#
143143
proc delete_files {} {
144144
global FILES
145145
.mb.files delete 3 end
146146
array unset FILES
147
- .mb.files entryconfigure 1 -state disabled
147
+ .mb.files entryconfigure 1 -state disabled
148148
}
149149
150150
# Prompt the user to select a file from the disk. Then send that
151151
# file to all chat participants.
152152
#
@@ -188,11 +188,11 @@
188188
if {![info exists prior] || $filename!=$prior} {
189189
.mb.files add command -label "Save \"$filename\"" \
190190
-command [list save_file $filename]
191191
}
192192
set FILES($filename) $data
193
- .mb.files entryconfigure 1 -state active
193
+ .mb.files entryconfigure 1 -state active
194194
set time [clock format [clock seconds] -format {%H:%M} -gmt 1]
195195
.msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm
196196
.msg.t see end
197197
}
198198
@@ -232,11 +232,11 @@
232232
} elseif {$cmd=="file"} {
233233
if {[info commands handle_file]=="handle_file"} {
234234
handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3]
235235
}
236236
}
237
-}
237
+}
238238
239239
# Handle a broken socket connection
240240
#
241241
proc disconnect {} {
242242
global SOCKET
243243
--- tools/fossil_chat.tcl
+++ tools/fossil_chat.tcl
@@ -84,11 +84,11 @@
84 catch {close $SOCKET}
85 if {[catch {
86 if {$::PROXYHOST ne {}} {
87 set SOCKET [socket $::PROXYHOST $::PROXYPORT]
88 puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1"
89 puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT"
90 puts $SOCKET ""
91 } else {
92 set SOCKET [socket $::SERVERHOST $::SERVERPORT]
93 }
94 fconfigure $SOCKET -translation binary -blocking 0
@@ -142,11 +142,11 @@
142 #
143 proc delete_files {} {
144 global FILES
145 .mb.files delete 3 end
146 array unset FILES
147 .mb.files entryconfigure 1 -state disabled
148 }
149
150 # Prompt the user to select a file from the disk. Then send that
151 # file to all chat participants.
152 #
@@ -188,11 +188,11 @@
188 if {![info exists prior] || $filename!=$prior} {
189 .mb.files add command -label "Save \"$filename\"" \
190 -command [list save_file $filename]
191 }
192 set FILES($filename) $data
193 .mb.files entryconfigure 1 -state active
194 set time [clock format [clock seconds] -format {%H:%M} -gmt 1]
195 .msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm
196 .msg.t see end
197 }
198
@@ -232,11 +232,11 @@
232 } elseif {$cmd=="file"} {
233 if {[info commands handle_file]=="handle_file"} {
234 handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3]
235 }
236 }
237 }
238
239 # Handle a broken socket connection
240 #
241 proc disconnect {} {
242 global SOCKET
243
--- tools/fossil_chat.tcl
+++ tools/fossil_chat.tcl
@@ -84,11 +84,11 @@
84 catch {close $SOCKET}
85 if {[catch {
86 if {$::PROXYHOST ne {}} {
87 set SOCKET [socket $::PROXYHOST $::PROXYPORT]
88 puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1"
89 puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT"
90 puts $SOCKET ""
91 } else {
92 set SOCKET [socket $::SERVERHOST $::SERVERPORT]
93 }
94 fconfigure $SOCKET -translation binary -blocking 0
@@ -142,11 +142,11 @@
142 #
143 proc delete_files {} {
144 global FILES
145 .mb.files delete 3 end
146 array unset FILES
147 .mb.files entryconfigure 1 -state disabled
148 }
149
150 # Prompt the user to select a file from the disk. Then send that
151 # file to all chat participants.
152 #
@@ -188,11 +188,11 @@
188 if {![info exists prior] || $filename!=$prior} {
189 .mb.files add command -label "Save \"$filename\"" \
190 -command [list save_file $filename]
191 }
192 set FILES($filename) $data
193 .mb.files entryconfigure 1 -state active
194 set time [clock format [clock seconds] -format {%H:%M} -gmt 1]
195 .msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm
196 .msg.t see end
197 }
198
@@ -232,11 +232,11 @@
232 } elseif {$cmd=="file"} {
233 if {[info commands handle_file]=="handle_file"} {
234 handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3]
235 }
236 }
237 }
238
239 # Handle a broken socket connection
240 #
241 proc disconnect {} {
242 global SOCKET
243
+10 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
2828
2929
SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
3030
3131
SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
33
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
33
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
35
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
35
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3636
3737
3838
RC=$(DMDIR)\bin\rcc
3939
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
4040
@@ -49,11 +49,11 @@
4949
5050
$(OBJDIR)\fossil.res: $B\win\fossil.rc
5151
$(RC) $(RCFLAGS) -o$@ $**
5252
5353
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54
- +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
54
+ +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
5555
+echo fossil >> $@
5656
+echo fossil >> $@
5757
+echo $(LIBS) >> $@
5858
+echo. >> $@
5959
+echo fossil >> $@
@@ -644,10 +644,16 @@
644644
$(OBJDIR)\shun$O : shun_.c shun.h
645645
$(TCC) -o$@ -c shun_.c
646646
647647
shun_.c : $(SRCDIR)\shun.c
648648
+translate$E $** > $@
649
+
650
+$(OBJDIR)\sitemap$O : sitemap_.c sitemap.h
651
+ $(TCC) -o$@ -c sitemap_.c
652
+
653
+sitemap_.c : $(SRCDIR)\sitemap.c
654
+ +translate$E $** > $@
649655
650656
$(OBJDIR)\skins$O : skins_.c skins.h
651657
$(TCC) -o$@ -c skins_.c
652658
653659
skins_.c : $(SRCDIR)\skins.c
@@ -820,7 +826,7 @@
820826
821827
zip_.c : $(SRCDIR)\zip.c
822828
+translate$E $** > $@
823829
824830
headers: makeheaders$E page_index.h builtin_data.h VERSION.h
825
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
831
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
826832
@copy /Y nul: headers
827833
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -644,10 +644,16 @@
644 $(OBJDIR)\shun$O : shun_.c shun.h
645 $(TCC) -o$@ -c shun_.c
646
647 shun_.c : $(SRCDIR)\shun.c
648 +translate$E $** > $@
 
 
 
 
 
 
649
650 $(OBJDIR)\skins$O : skins_.c skins.h
651 $(TCC) -o$@ -c skins_.c
652
653 skins_.c : $(SRCDIR)\skins.c
@@ -820,7 +826,7 @@
820
821 zip_.c : $(SRCDIR)\zip.c
822 +translate$E $** > $@
823
824 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
825 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
826 @copy /Y nul: headers
827
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -644,10 +644,16 @@
644 $(OBJDIR)\shun$O : shun_.c shun.h
645 $(TCC) -o$@ -c shun_.c
646
647 shun_.c : $(SRCDIR)\shun.c
648 +translate$E $** > $@
649
650 $(OBJDIR)\sitemap$O : sitemap_.c sitemap.h
651 $(TCC) -o$@ -c sitemap_.c
652
653 sitemap_.c : $(SRCDIR)\sitemap.c
654 +translate$E $** > $@
655
656 $(OBJDIR)\skins$O : skins_.c skins.h
657 $(TCC) -o$@ -c skins_.c
658
659 skins_.c : $(SRCDIR)\skins.c
@@ -820,7 +826,7 @@
826
827 zip_.c : $(SRCDIR)\zip.c
828 +translate$E $** > $@
829
830 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
831 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
832 @copy /Y nul: headers
833
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -87,11 +87,12 @@
8787
# This is useful when Tcl has been compiled statically with MinGW.
8888
#
8989
FOSSIL_TCL_SOURCE = 1
9090
9191
#### Check if the workaround for the MinGW command line handling needs to
92
-# be enabled by default.
92
+# be enabled by default. This check may be somewhat fragile due to the
93
+# use of "findstring".
9394
#
9495
ifndef MINGW_IS_32BIT_ONLY
9596
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
9697
MINGW_IS_32BIT_ONLY = 1
9798
endif
@@ -100,31 +101,46 @@
100101
#### The directories where the zlib include and library files are located.
101102
#
102103
ZINCDIR = $(SRCDIR)/../compat/zlib
103104
ZLIBDIR = $(SRCDIR)/../compat/zlib
104105
106
+#### Make an attempt to detect if Fossil is being built for the x64 processor
107
+# architecture. This check may be somewhat fragile due to "findstring".
108
+#
105109
ifndef X64
106110
ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
107111
X64 = 1
108112
endif
109113
endif
110114
115
+#### Determine if the optimized assembly routines provided with zlib should be
116
+# used, taking into account whether zlib is actually enabled and the target
117
+# processor architecture.
118
+#
111119
ifndef X64
112120
SSLCONFIG = mingw
113121
ifndef FOSSIL_ENABLE_MINIZ
114122
ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
115123
LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
116124
else
117
-ZLIBCONFIG =
125
+ZLIBCONFIG =
118126
LIBTARGETS =
119127
endif
120128
else
121129
SSLCONFIG = mingw64
122
-ZLIBCONFIG =
130
+ZLIBCONFIG =
123131
LIBTARGETS =
124132
endif
125133
134
+#### Disable creation of the OpenSSL shared libraries. Also, disable support
135
+# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS).
136
+#
137
+SSLCONFIG += no-ssl2 no-ssl3 no-shared
138
+
139
+#### When using zlib, make sure that OpenSSL is configured to use the zlib
140
+# that Fossil knows about (i.e. the one within the source tree).
141
+#
126142
ifndef FOSSIL_ENABLE_MINIZ
127143
SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
128144
endif
129145
130146
#### The directories where the OpenSSL include and library files are located.
@@ -435,10 +451,11 @@
435451
$(SRCDIR)/schema.c \
436452
$(SRCDIR)/search.c \
437453
$(SRCDIR)/setup.c \
438454
$(SRCDIR)/sha1.c \
439455
$(SRCDIR)/shun.c \
456
+ $(SRCDIR)/sitemap.c \
440457
$(SRCDIR)/skins.c \
441458
$(SRCDIR)/sqlcmd.c \
442459
$(SRCDIR)/stash.c \
443460
$(SRCDIR)/stat.c \
444461
$(SRCDIR)/style.c \
@@ -556,10 +573,11 @@
556573
$(OBJDIR)/schema_.c \
557574
$(OBJDIR)/search_.c \
558575
$(OBJDIR)/setup_.c \
559576
$(OBJDIR)/sha1_.c \
560577
$(OBJDIR)/shun_.c \
578
+ $(OBJDIR)/sitemap_.c \
561579
$(OBJDIR)/skins_.c \
562580
$(OBJDIR)/sqlcmd_.c \
563581
$(OBJDIR)/stash_.c \
564582
$(OBJDIR)/stat_.c \
565583
$(OBJDIR)/style_.c \
@@ -674,10 +692,11 @@
674692
$(OBJDIR)/schema.o \
675693
$(OBJDIR)/search.o \
676694
$(OBJDIR)/setup.o \
677695
$(OBJDIR)/sha1.o \
678696
$(OBJDIR)/shun.o \
697
+ $(OBJDIR)/sitemap.o \
679698
$(OBJDIR)/skins.o \
680699
$(OBJDIR)/sqlcmd.o \
681700
$(OBJDIR)/stash.o \
682701
$(OBJDIR)/stat.o \
683702
$(OBJDIR)/style.o \
@@ -985,10 +1004,11 @@
9851004
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
9861005
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
9871006
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
9881007
$(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
9891008
$(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
1009
+ $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
9901010
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
9911011
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
9921012
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
9931013
$(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
9941014
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1718,10 +1738,18 @@
17181738
17191739
$(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
17201740
$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
17211741
17221742
$(OBJDIR)/shun.h: $(OBJDIR)/headers
1743
+
1744
+$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE)
1745
+ $(TRANSLATE) $(SRCDIR)/sitemap.c >$@
1746
+
1747
+$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h
1748
+ $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c
1749
+
1750
+$(OBJDIR)/sitemap.h: $(OBJDIR)/headers
17231751
17241752
$(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE)
17251753
$(TRANSLATE) $(SRCDIR)/skins.c >$@
17261754
17271755
$(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
17281756
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -87,11 +87,12 @@
87 # This is useful when Tcl has been compiled statically with MinGW.
88 #
89 FOSSIL_TCL_SOURCE = 1
90
91 #### Check if the workaround for the MinGW command line handling needs to
92 # be enabled by default.
 
93 #
94 ifndef MINGW_IS_32BIT_ONLY
95 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
96 MINGW_IS_32BIT_ONLY = 1
97 endif
@@ -100,31 +101,46 @@
100 #### The directories where the zlib include and library files are located.
101 #
102 ZINCDIR = $(SRCDIR)/../compat/zlib
103 ZLIBDIR = $(SRCDIR)/../compat/zlib
104
 
 
 
105 ifndef X64
106 ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
107 X64 = 1
108 endif
109 endif
110
 
 
 
 
111 ifndef X64
112 SSLCONFIG = mingw
113 ifndef FOSSIL_ENABLE_MINIZ
114 ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
115 LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
116 else
117 ZLIBCONFIG =
118 LIBTARGETS =
119 endif
120 else
121 SSLCONFIG = mingw64
122 ZLIBCONFIG =
123 LIBTARGETS =
124 endif
125
 
 
 
 
 
 
 
 
126 ifndef FOSSIL_ENABLE_MINIZ
127 SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
128 endif
129
130 #### The directories where the OpenSSL include and library files are located.
@@ -435,10 +451,11 @@
435 $(SRCDIR)/schema.c \
436 $(SRCDIR)/search.c \
437 $(SRCDIR)/setup.c \
438 $(SRCDIR)/sha1.c \
439 $(SRCDIR)/shun.c \
 
440 $(SRCDIR)/skins.c \
441 $(SRCDIR)/sqlcmd.c \
442 $(SRCDIR)/stash.c \
443 $(SRCDIR)/stat.c \
444 $(SRCDIR)/style.c \
@@ -556,10 +573,11 @@
556 $(OBJDIR)/schema_.c \
557 $(OBJDIR)/search_.c \
558 $(OBJDIR)/setup_.c \
559 $(OBJDIR)/sha1_.c \
560 $(OBJDIR)/shun_.c \
 
561 $(OBJDIR)/skins_.c \
562 $(OBJDIR)/sqlcmd_.c \
563 $(OBJDIR)/stash_.c \
564 $(OBJDIR)/stat_.c \
565 $(OBJDIR)/style_.c \
@@ -674,10 +692,11 @@
674 $(OBJDIR)/schema.o \
675 $(OBJDIR)/search.o \
676 $(OBJDIR)/setup.o \
677 $(OBJDIR)/sha1.o \
678 $(OBJDIR)/shun.o \
 
679 $(OBJDIR)/skins.o \
680 $(OBJDIR)/sqlcmd.o \
681 $(OBJDIR)/stash.o \
682 $(OBJDIR)/stat.o \
683 $(OBJDIR)/style.o \
@@ -985,10 +1004,11 @@
985 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
986 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
987 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
988 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
989 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
 
990 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
991 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
992 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
993 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
994 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1718,10 +1738,18 @@
1718
1719 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1720 $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
1721
1722 $(OBJDIR)/shun.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1723
1724 $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE)
1725 $(TRANSLATE) $(SRCDIR)/skins.c >$@
1726
1727 $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
1728
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -87,11 +87,12 @@
87 # This is useful when Tcl has been compiled statically with MinGW.
88 #
89 FOSSIL_TCL_SOURCE = 1
90
91 #### Check if the workaround for the MinGW command line handling needs to
92 # be enabled by default. This check may be somewhat fragile due to the
93 # use of "findstring".
94 #
95 ifndef MINGW_IS_32BIT_ONLY
96 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
97 MINGW_IS_32BIT_ONLY = 1
98 endif
@@ -100,31 +101,46 @@
101 #### The directories where the zlib include and library files are located.
102 #
103 ZINCDIR = $(SRCDIR)/../compat/zlib
104 ZLIBDIR = $(SRCDIR)/../compat/zlib
105
106 #### Make an attempt to detect if Fossil is being built for the x64 processor
107 # architecture. This check may be somewhat fragile due to "findstring".
108 #
109 ifndef X64
110 ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
111 X64 = 1
112 endif
113 endif
114
115 #### Determine if the optimized assembly routines provided with zlib should be
116 # used, taking into account whether zlib is actually enabled and the target
117 # processor architecture.
118 #
119 ifndef X64
120 SSLCONFIG = mingw
121 ifndef FOSSIL_ENABLE_MINIZ
122 ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
123 LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
124 else
125 ZLIBCONFIG =
126 LIBTARGETS =
127 endif
128 else
129 SSLCONFIG = mingw64
130 ZLIBCONFIG =
131 LIBTARGETS =
132 endif
133
134 #### Disable creation of the OpenSSL shared libraries. Also, disable support
135 # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS).
136 #
137 SSLCONFIG += no-ssl2 no-ssl3 no-shared
138
139 #### When using zlib, make sure that OpenSSL is configured to use the zlib
140 # that Fossil knows about (i.e. the one within the source tree).
141 #
142 ifndef FOSSIL_ENABLE_MINIZ
143 SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
144 endif
145
146 #### The directories where the OpenSSL include and library files are located.
@@ -435,10 +451,11 @@
451 $(SRCDIR)/schema.c \
452 $(SRCDIR)/search.c \
453 $(SRCDIR)/setup.c \
454 $(SRCDIR)/sha1.c \
455 $(SRCDIR)/shun.c \
456 $(SRCDIR)/sitemap.c \
457 $(SRCDIR)/skins.c \
458 $(SRCDIR)/sqlcmd.c \
459 $(SRCDIR)/stash.c \
460 $(SRCDIR)/stat.c \
461 $(SRCDIR)/style.c \
@@ -556,10 +573,11 @@
573 $(OBJDIR)/schema_.c \
574 $(OBJDIR)/search_.c \
575 $(OBJDIR)/setup_.c \
576 $(OBJDIR)/sha1_.c \
577 $(OBJDIR)/shun_.c \
578 $(OBJDIR)/sitemap_.c \
579 $(OBJDIR)/skins_.c \
580 $(OBJDIR)/sqlcmd_.c \
581 $(OBJDIR)/stash_.c \
582 $(OBJDIR)/stat_.c \
583 $(OBJDIR)/style_.c \
@@ -674,10 +692,11 @@
692 $(OBJDIR)/schema.o \
693 $(OBJDIR)/search.o \
694 $(OBJDIR)/setup.o \
695 $(OBJDIR)/sha1.o \
696 $(OBJDIR)/shun.o \
697 $(OBJDIR)/sitemap.o \
698 $(OBJDIR)/skins.o \
699 $(OBJDIR)/sqlcmd.o \
700 $(OBJDIR)/stash.o \
701 $(OBJDIR)/stat.o \
702 $(OBJDIR)/style.o \
@@ -985,10 +1004,11 @@
1004 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
1005 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
1006 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
1007 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
1008 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
1009 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1010 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1011 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1012 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
1013 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
1014 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1718,10 +1738,18 @@
1738
1739 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1740 $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
1741
1742 $(OBJDIR)/shun.h: $(OBJDIR)/headers
1743
1744 $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE)
1745 $(TRANSLATE) $(SRCDIR)/sitemap.c >$@
1746
1747 $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h
1748 $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c
1749
1750 $(OBJDIR)/sitemap.h: $(OBJDIR)/headers
1751
1752 $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE)
1753 $(TRANSLATE) $(SRCDIR)/skins.c >$@
1754
1755 $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
1756
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -87,11 +87,12 @@
8787
# This is useful when Tcl has been compiled statically with MinGW.
8888
#
8989
FOSSIL_TCL_SOURCE = 1
9090
9191
#### Check if the workaround for the MinGW command line handling needs to
92
-# be enabled by default.
92
+# be enabled by default. This check may be somewhat fragile due to the
93
+# use of "findstring".
9394
#
9495
ifndef MINGW_IS_32BIT_ONLY
9596
ifeq (,$(findstring w64-mingw32,$(PREFIX)))
9697
MINGW_IS_32BIT_ONLY = 1
9798
endif
@@ -100,26 +101,46 @@
100101
#### The directories where the zlib include and library files are located.
101102
#
102103
ZINCDIR = $(SRCDIR)/../compat/zlib
103104
ZLIBDIR = $(SRCDIR)/../compat/zlib
104105
106
+#### Make an attempt to detect if Fossil is being built for the x64 processor
107
+# architecture. This check may be somewhat fragile due to "findstring".
108
+#
105109
ifndef X64
106110
ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
107111
X64 = 1
108112
endif
109113
endif
110114
115
+#### Determine if the optimized assembly routines provided with zlib should be
116
+# used, taking into account whether zlib is actually enabled and the target
117
+# processor architecture.
118
+#
111119
ifndef X64
112120
SSLCONFIG = mingw
121
+ifndef FOSSIL_ENABLE_MINIZ
113122
ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
114123
LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
124
+else
125
+ZLIBCONFIG =
126
+LIBTARGETS =
127
+endif
115128
else
116129
SSLCONFIG = mingw64
117
-ZLIBCONFIG =
130
+ZLIBCONFIG =
118131
LIBTARGETS =
119132
endif
120133
134
+#### Disable creation of the OpenSSL shared libraries. Also, disable support
135
+# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS).
136
+#
137
+SSLCONFIG += no-ssl2 no-ssl3 no-shared
138
+
139
+#### When using zlib, make sure that OpenSSL is configured to use the zlib
140
+# that Fossil knows about (i.e. the one within the source tree).
141
+#
121142
ifndef FOSSIL_ENABLE_MINIZ
122143
SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
123144
endif
124145
125146
#### The directories where the OpenSSL include and library files are located.
@@ -352,10 +373,11 @@
352373
$(SRCDIR)/bisect.c \
353374
$(SRCDIR)/blob.c \
354375
$(SRCDIR)/branch.c \
355376
$(SRCDIR)/browse.c \
356377
$(SRCDIR)/builtin.c \
378
+ $(SRCDIR)/bundle.c \
357379
$(SRCDIR)/cache.c \
358380
$(SRCDIR)/captcha.c \
359381
$(SRCDIR)/cgi.c \
360382
$(SRCDIR)/checkin.c \
361383
$(SRCDIR)/checkout.c \
@@ -374,10 +396,11 @@
374396
$(SRCDIR)/encode.c \
375397
$(SRCDIR)/event.c \
376398
$(SRCDIR)/export.c \
377399
$(SRCDIR)/file.c \
378400
$(SRCDIR)/finfo.c \
401
+ $(SRCDIR)/foci.c \
379402
$(SRCDIR)/fusefs.c \
380403
$(SRCDIR)/glob.c \
381404
$(SRCDIR)/graph.c \
382405
$(SRCDIR)/gzip.c \
383406
$(SRCDIR)/http.c \
@@ -417,19 +440,22 @@
417440
$(SRCDIR)/path.c \
418441
$(SRCDIR)/pivot.c \
419442
$(SRCDIR)/popen.c \
420443
$(SRCDIR)/pqueue.c \
421444
$(SRCDIR)/printf.c \
445
+ $(SRCDIR)/publish.c \
446
+ $(SRCDIR)/purge.c \
422447
$(SRCDIR)/rebuild.c \
423448
$(SRCDIR)/regexp.c \
424449
$(SRCDIR)/report.c \
425450
$(SRCDIR)/rss.c \
426451
$(SRCDIR)/schema.c \
427452
$(SRCDIR)/search.c \
428453
$(SRCDIR)/setup.c \
429454
$(SRCDIR)/sha1.c \
430455
$(SRCDIR)/shun.c \
456
+ $(SRCDIR)/sitemap.c \
431457
$(SRCDIR)/skins.c \
432458
$(SRCDIR)/sqlcmd.c \
433459
$(SRCDIR)/stash.c \
434460
$(SRCDIR)/stat.c \
435461
$(SRCDIR)/style.c \
@@ -469,10 +495,11 @@
469495
$(OBJDIR)/bisect_.c \
470496
$(OBJDIR)/blob_.c \
471497
$(OBJDIR)/branch_.c \
472498
$(OBJDIR)/browse_.c \
473499
$(OBJDIR)/builtin_.c \
500
+ $(OBJDIR)/bundle_.c \
474501
$(OBJDIR)/cache_.c \
475502
$(OBJDIR)/captcha_.c \
476503
$(OBJDIR)/cgi_.c \
477504
$(OBJDIR)/checkin_.c \
478505
$(OBJDIR)/checkout_.c \
@@ -491,10 +518,11 @@
491518
$(OBJDIR)/encode_.c \
492519
$(OBJDIR)/event_.c \
493520
$(OBJDIR)/export_.c \
494521
$(OBJDIR)/file_.c \
495522
$(OBJDIR)/finfo_.c \
523
+ $(OBJDIR)/foci_.c \
496524
$(OBJDIR)/fusefs_.c \
497525
$(OBJDIR)/glob_.c \
498526
$(OBJDIR)/graph_.c \
499527
$(OBJDIR)/gzip_.c \
500528
$(OBJDIR)/http_.c \
@@ -534,19 +562,22 @@
534562
$(OBJDIR)/path_.c \
535563
$(OBJDIR)/pivot_.c \
536564
$(OBJDIR)/popen_.c \
537565
$(OBJDIR)/pqueue_.c \
538566
$(OBJDIR)/printf_.c \
567
+ $(OBJDIR)/publish_.c \
568
+ $(OBJDIR)/purge_.c \
539569
$(OBJDIR)/rebuild_.c \
540570
$(OBJDIR)/regexp_.c \
541571
$(OBJDIR)/report_.c \
542572
$(OBJDIR)/rss_.c \
543573
$(OBJDIR)/schema_.c \
544574
$(OBJDIR)/search_.c \
545575
$(OBJDIR)/setup_.c \
546576
$(OBJDIR)/sha1_.c \
547577
$(OBJDIR)/shun_.c \
578
+ $(OBJDIR)/sitemap_.c \
548579
$(OBJDIR)/skins_.c \
549580
$(OBJDIR)/sqlcmd_.c \
550581
$(OBJDIR)/stash_.c \
551582
$(OBJDIR)/stat_.c \
552583
$(OBJDIR)/style_.c \
@@ -583,10 +614,11 @@
583614
$(OBJDIR)/bisect.o \
584615
$(OBJDIR)/blob.o \
585616
$(OBJDIR)/branch.o \
586617
$(OBJDIR)/browse.o \
587618
$(OBJDIR)/builtin.o \
619
+ $(OBJDIR)/bundle.o \
588620
$(OBJDIR)/cache.o \
589621
$(OBJDIR)/captcha.o \
590622
$(OBJDIR)/cgi.o \
591623
$(OBJDIR)/checkin.o \
592624
$(OBJDIR)/checkout.o \
@@ -605,10 +637,11 @@
605637
$(OBJDIR)/encode.o \
606638
$(OBJDIR)/event.o \
607639
$(OBJDIR)/export.o \
608640
$(OBJDIR)/file.o \
609641
$(OBJDIR)/finfo.o \
642
+ $(OBJDIR)/foci.o \
610643
$(OBJDIR)/fusefs.o \
611644
$(OBJDIR)/glob.o \
612645
$(OBJDIR)/graph.o \
613646
$(OBJDIR)/gzip.o \
614647
$(OBJDIR)/http.o \
@@ -648,19 +681,22 @@
648681
$(OBJDIR)/path.o \
649682
$(OBJDIR)/pivot.o \
650683
$(OBJDIR)/popen.o \
651684
$(OBJDIR)/pqueue.o \
652685
$(OBJDIR)/printf.o \
686
+ $(OBJDIR)/publish.o \
687
+ $(OBJDIR)/purge.o \
653688
$(OBJDIR)/rebuild.o \
654689
$(OBJDIR)/regexp.o \
655690
$(OBJDIR)/report.o \
656691
$(OBJDIR)/rss.o \
657692
$(OBJDIR)/schema.o \
658693
$(OBJDIR)/search.o \
659694
$(OBJDIR)/setup.o \
660695
$(OBJDIR)/sha1.o \
661696
$(OBJDIR)/shun.o \
697
+ $(OBJDIR)/sitemap.o \
662698
$(OBJDIR)/skins.o \
663699
$(OBJDIR)/sqlcmd.o \
664700
$(OBJDIR)/stash.o \
665701
$(OBJDIR)/stat.o \
666702
$(OBJDIR)/style.o \
@@ -890,10 +926,11 @@
890926
$(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \
891927
$(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \
892928
$(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \
893929
$(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \
894930
$(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \
931
+ $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \
895932
$(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \
896933
$(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \
897934
$(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \
898935
$(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \
899936
$(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \
@@ -912,10 +949,11 @@
912949
$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
913950
$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
914951
$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
915952
$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
916953
$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
954
+ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
917955
$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
918956
$(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
919957
$(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
920958
$(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
921959
$(OBJDIR)/http_.c:$(OBJDIR)/http.h \
@@ -955,19 +993,22 @@
955993
$(OBJDIR)/path_.c:$(OBJDIR)/path.h \
956994
$(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
957995
$(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
958996
$(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
959997
$(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
998
+ $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \
999
+ $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \
9601000
$(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
9611001
$(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
9621002
$(OBJDIR)/report_.c:$(OBJDIR)/report.h \
9631003
$(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
9641004
$(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
9651005
$(OBJDIR)/search_.c:$(OBJDIR)/search.h \
9661006
$(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
9671007
$(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
9681008
$(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
1009
+ $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
9691010
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
9701011
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
9711012
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
9721013
$(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
9731014
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1073,10 +1114,18 @@
10731114
10741115
$(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h
10751116
$(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c
10761117
10771118
$(OBJDIR)/builtin.h: $(OBJDIR)/headers
1119
+
1120
+$(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE)
1121
+ $(TRANSLATE) $(SRCDIR)/bundle.c >$@
1122
+
1123
+$(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h
1124
+ $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c
1125
+
1126
+$(OBJDIR)/bundle.h: $(OBJDIR)/headers
10781127
10791128
$(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE)
10801129
$(TRANSLATE) $(SRCDIR)/cache.c >$@
10811130
10821131
$(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h
@@ -1249,10 +1298,18 @@
12491298
12501299
$(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
12511300
$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
12521301
12531302
$(OBJDIR)/finfo.h: $(OBJDIR)/headers
1303
+
1304
+$(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(TRANSLATE)
1305
+ $(TRANSLATE) $(SRCDIR)/foci.c >$@
1306
+
1307
+$(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h
1308
+ $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c
1309
+
1310
+$(OBJDIR)/foci.h: $(OBJDIR)/headers
12541311
12551312
$(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE)
12561313
$(TRANSLATE) $(SRCDIR)/fusefs.c >$@
12571314
12581315
$(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h
@@ -1593,10 +1650,26 @@
15931650
15941651
$(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h
15951652
$(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c
15961653
15971654
$(OBJDIR)/printf.h: $(OBJDIR)/headers
1655
+
1656
+$(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE)
1657
+ $(TRANSLATE) $(SRCDIR)/publish.c >$@
1658
+
1659
+$(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h
1660
+ $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c
1661
+
1662
+$(OBJDIR)/publish.h: $(OBJDIR)/headers
1663
+
1664
+$(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE)
1665
+ $(TRANSLATE) $(SRCDIR)/purge.c >$@
1666
+
1667
+$(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h
1668
+ $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c
1669
+
1670
+$(OBJDIR)/purge.h: $(OBJDIR)/headers
15981671
15991672
$(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE)
16001673
$(TRANSLATE) $(SRCDIR)/rebuild.c >$@
16011674
16021675
$(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
@@ -1665,10 +1738,18 @@
16651738
16661739
$(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
16671740
$(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
16681741
16691742
$(OBJDIR)/shun.h: $(OBJDIR)/headers
1743
+
1744
+$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE)
1745
+ $(TRANSLATE) $(SRCDIR)/sitemap.c >$@
1746
+
1747
+$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h
1748
+ $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c
1749
+
1750
+$(OBJDIR)/sitemap.h: $(OBJDIR)/headers
16701751
16711752
$(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE)
16721753
$(TRANSLATE) $(SRCDIR)/skins.c >$@
16731754
16741755
$(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
16751756
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -87,11 +87,12 @@
87 # This is useful when Tcl has been compiled statically with MinGW.
88 #
89 FOSSIL_TCL_SOURCE = 1
90
91 #### Check if the workaround for the MinGW command line handling needs to
92 # be enabled by default.
 
93 #
94 ifndef MINGW_IS_32BIT_ONLY
95 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
96 MINGW_IS_32BIT_ONLY = 1
97 endif
@@ -100,26 +101,46 @@
100 #### The directories where the zlib include and library files are located.
101 #
102 ZINCDIR = $(SRCDIR)/../compat/zlib
103 ZLIBDIR = $(SRCDIR)/../compat/zlib
104
 
 
 
105 ifndef X64
106 ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
107 X64 = 1
108 endif
109 endif
110
 
 
 
 
111 ifndef X64
112 SSLCONFIG = mingw
 
113 ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
114 LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
 
 
 
 
115 else
116 SSLCONFIG = mingw64
117 ZLIBCONFIG =
118 LIBTARGETS =
119 endif
120
 
 
 
 
 
 
 
 
121 ifndef FOSSIL_ENABLE_MINIZ
122 SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
123 endif
124
125 #### The directories where the OpenSSL include and library files are located.
@@ -352,10 +373,11 @@
352 $(SRCDIR)/bisect.c \
353 $(SRCDIR)/blob.c \
354 $(SRCDIR)/branch.c \
355 $(SRCDIR)/browse.c \
356 $(SRCDIR)/builtin.c \
 
357 $(SRCDIR)/cache.c \
358 $(SRCDIR)/captcha.c \
359 $(SRCDIR)/cgi.c \
360 $(SRCDIR)/checkin.c \
361 $(SRCDIR)/checkout.c \
@@ -374,10 +396,11 @@
374 $(SRCDIR)/encode.c \
375 $(SRCDIR)/event.c \
376 $(SRCDIR)/export.c \
377 $(SRCDIR)/file.c \
378 $(SRCDIR)/finfo.c \
 
379 $(SRCDIR)/fusefs.c \
380 $(SRCDIR)/glob.c \
381 $(SRCDIR)/graph.c \
382 $(SRCDIR)/gzip.c \
383 $(SRCDIR)/http.c \
@@ -417,19 +440,22 @@
417 $(SRCDIR)/path.c \
418 $(SRCDIR)/pivot.c \
419 $(SRCDIR)/popen.c \
420 $(SRCDIR)/pqueue.c \
421 $(SRCDIR)/printf.c \
 
 
422 $(SRCDIR)/rebuild.c \
423 $(SRCDIR)/regexp.c \
424 $(SRCDIR)/report.c \
425 $(SRCDIR)/rss.c \
426 $(SRCDIR)/schema.c \
427 $(SRCDIR)/search.c \
428 $(SRCDIR)/setup.c \
429 $(SRCDIR)/sha1.c \
430 $(SRCDIR)/shun.c \
 
431 $(SRCDIR)/skins.c \
432 $(SRCDIR)/sqlcmd.c \
433 $(SRCDIR)/stash.c \
434 $(SRCDIR)/stat.c \
435 $(SRCDIR)/style.c \
@@ -469,10 +495,11 @@
469 $(OBJDIR)/bisect_.c \
470 $(OBJDIR)/blob_.c \
471 $(OBJDIR)/branch_.c \
472 $(OBJDIR)/browse_.c \
473 $(OBJDIR)/builtin_.c \
 
474 $(OBJDIR)/cache_.c \
475 $(OBJDIR)/captcha_.c \
476 $(OBJDIR)/cgi_.c \
477 $(OBJDIR)/checkin_.c \
478 $(OBJDIR)/checkout_.c \
@@ -491,10 +518,11 @@
491 $(OBJDIR)/encode_.c \
492 $(OBJDIR)/event_.c \
493 $(OBJDIR)/export_.c \
494 $(OBJDIR)/file_.c \
495 $(OBJDIR)/finfo_.c \
 
496 $(OBJDIR)/fusefs_.c \
497 $(OBJDIR)/glob_.c \
498 $(OBJDIR)/graph_.c \
499 $(OBJDIR)/gzip_.c \
500 $(OBJDIR)/http_.c \
@@ -534,19 +562,22 @@
534 $(OBJDIR)/path_.c \
535 $(OBJDIR)/pivot_.c \
536 $(OBJDIR)/popen_.c \
537 $(OBJDIR)/pqueue_.c \
538 $(OBJDIR)/printf_.c \
 
 
539 $(OBJDIR)/rebuild_.c \
540 $(OBJDIR)/regexp_.c \
541 $(OBJDIR)/report_.c \
542 $(OBJDIR)/rss_.c \
543 $(OBJDIR)/schema_.c \
544 $(OBJDIR)/search_.c \
545 $(OBJDIR)/setup_.c \
546 $(OBJDIR)/sha1_.c \
547 $(OBJDIR)/shun_.c \
 
548 $(OBJDIR)/skins_.c \
549 $(OBJDIR)/sqlcmd_.c \
550 $(OBJDIR)/stash_.c \
551 $(OBJDIR)/stat_.c \
552 $(OBJDIR)/style_.c \
@@ -583,10 +614,11 @@
583 $(OBJDIR)/bisect.o \
584 $(OBJDIR)/blob.o \
585 $(OBJDIR)/branch.o \
586 $(OBJDIR)/browse.o \
587 $(OBJDIR)/builtin.o \
 
588 $(OBJDIR)/cache.o \
589 $(OBJDIR)/captcha.o \
590 $(OBJDIR)/cgi.o \
591 $(OBJDIR)/checkin.o \
592 $(OBJDIR)/checkout.o \
@@ -605,10 +637,11 @@
605 $(OBJDIR)/encode.o \
606 $(OBJDIR)/event.o \
607 $(OBJDIR)/export.o \
608 $(OBJDIR)/file.o \
609 $(OBJDIR)/finfo.o \
 
610 $(OBJDIR)/fusefs.o \
611 $(OBJDIR)/glob.o \
612 $(OBJDIR)/graph.o \
613 $(OBJDIR)/gzip.o \
614 $(OBJDIR)/http.o \
@@ -648,19 +681,22 @@
648 $(OBJDIR)/path.o \
649 $(OBJDIR)/pivot.o \
650 $(OBJDIR)/popen.o \
651 $(OBJDIR)/pqueue.o \
652 $(OBJDIR)/printf.o \
 
 
653 $(OBJDIR)/rebuild.o \
654 $(OBJDIR)/regexp.o \
655 $(OBJDIR)/report.o \
656 $(OBJDIR)/rss.o \
657 $(OBJDIR)/schema.o \
658 $(OBJDIR)/search.o \
659 $(OBJDIR)/setup.o \
660 $(OBJDIR)/sha1.o \
661 $(OBJDIR)/shun.o \
 
662 $(OBJDIR)/skins.o \
663 $(OBJDIR)/sqlcmd.o \
664 $(OBJDIR)/stash.o \
665 $(OBJDIR)/stat.o \
666 $(OBJDIR)/style.o \
@@ -890,10 +926,11 @@
890 $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \
891 $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \
892 $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \
893 $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \
894 $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \
 
895 $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \
896 $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \
897 $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \
898 $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \
899 $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \
@@ -912,10 +949,11 @@
912 $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
913 $(OBJDIR)/event_.c:$(OBJDIR)/event.h \
914 $(OBJDIR)/export_.c:$(OBJDIR)/export.h \
915 $(OBJDIR)/file_.c:$(OBJDIR)/file.h \
916 $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
 
917 $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
918 $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
919 $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
920 $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
921 $(OBJDIR)/http_.c:$(OBJDIR)/http.h \
@@ -955,19 +993,22 @@
955 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
956 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
957 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
958 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
959 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
 
 
960 $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
961 $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
962 $(OBJDIR)/report_.c:$(OBJDIR)/report.h \
963 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
964 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
965 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
966 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
967 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
968 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
 
969 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
970 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
971 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
972 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
973 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1073,10 +1114,18 @@
1073
1074 $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h
1075 $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c
1076
1077 $(OBJDIR)/builtin.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1078
1079 $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE)
1080 $(TRANSLATE) $(SRCDIR)/cache.c >$@
1081
1082 $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h
@@ -1249,10 +1298,18 @@
1249
1250 $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
1251 $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
1252
1253 $(OBJDIR)/finfo.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1254
1255 $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE)
1256 $(TRANSLATE) $(SRCDIR)/fusefs.c >$@
1257
1258 $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h
@@ -1593,10 +1650,26 @@
1593
1594 $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h
1595 $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c
1596
1597 $(OBJDIR)/printf.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1598
1599 $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE)
1600 $(TRANSLATE) $(SRCDIR)/rebuild.c >$@
1601
1602 $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
@@ -1665,10 +1738,18 @@
1665
1666 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1667 $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
1668
1669 $(OBJDIR)/shun.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1670
1671 $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE)
1672 $(TRANSLATE) $(SRCDIR)/skins.c >$@
1673
1674 $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
1675
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -87,11 +87,12 @@
87 # This is useful when Tcl has been compiled statically with MinGW.
88 #
89 FOSSIL_TCL_SOURCE = 1
90
91 #### Check if the workaround for the MinGW command line handling needs to
92 # be enabled by default. This check may be somewhat fragile due to the
93 # use of "findstring".
94 #
95 ifndef MINGW_IS_32BIT_ONLY
96 ifeq (,$(findstring w64-mingw32,$(PREFIX)))
97 MINGW_IS_32BIT_ONLY = 1
98 endif
@@ -100,26 +101,46 @@
101 #### The directories where the zlib include and library files are located.
102 #
103 ZINCDIR = $(SRCDIR)/../compat/zlib
104 ZLIBDIR = $(SRCDIR)/../compat/zlib
105
106 #### Make an attempt to detect if Fossil is being built for the x64 processor
107 # architecture. This check may be somewhat fragile due to "findstring".
108 #
109 ifndef X64
110 ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX)))
111 X64 = 1
112 endif
113 endif
114
115 #### Determine if the optimized assembly routines provided with zlib should be
116 # used, taking into account whether zlib is actually enabled and the target
117 # processor architecture.
118 #
119 ifndef X64
120 SSLCONFIG = mingw
121 ifndef FOSSIL_ENABLE_MINIZ
122 ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o"
123 LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o
124 else
125 ZLIBCONFIG =
126 LIBTARGETS =
127 endif
128 else
129 SSLCONFIG = mingw64
130 ZLIBCONFIG =
131 LIBTARGETS =
132 endif
133
134 #### Disable creation of the OpenSSL shared libraries. Also, disable support
135 # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS).
136 #
137 SSLCONFIG += no-ssl2 no-ssl3 no-shared
138
139 #### When using zlib, make sure that OpenSSL is configured to use the zlib
140 # that Fossil knows about (i.e. the one within the source tree).
141 #
142 ifndef FOSSIL_ENABLE_MINIZ
143 SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib
144 endif
145
146 #### The directories where the OpenSSL include and library files are located.
@@ -352,10 +373,11 @@
373 $(SRCDIR)/bisect.c \
374 $(SRCDIR)/blob.c \
375 $(SRCDIR)/branch.c \
376 $(SRCDIR)/browse.c \
377 $(SRCDIR)/builtin.c \
378 $(SRCDIR)/bundle.c \
379 $(SRCDIR)/cache.c \
380 $(SRCDIR)/captcha.c \
381 $(SRCDIR)/cgi.c \
382 $(SRCDIR)/checkin.c \
383 $(SRCDIR)/checkout.c \
@@ -374,10 +396,11 @@
396 $(SRCDIR)/encode.c \
397 $(SRCDIR)/event.c \
398 $(SRCDIR)/export.c \
399 $(SRCDIR)/file.c \
400 $(SRCDIR)/finfo.c \
401 $(SRCDIR)/foci.c \
402 $(SRCDIR)/fusefs.c \
403 $(SRCDIR)/glob.c \
404 $(SRCDIR)/graph.c \
405 $(SRCDIR)/gzip.c \
406 $(SRCDIR)/http.c \
@@ -417,19 +440,22 @@
440 $(SRCDIR)/path.c \
441 $(SRCDIR)/pivot.c \
442 $(SRCDIR)/popen.c \
443 $(SRCDIR)/pqueue.c \
444 $(SRCDIR)/printf.c \
445 $(SRCDIR)/publish.c \
446 $(SRCDIR)/purge.c \
447 $(SRCDIR)/rebuild.c \
448 $(SRCDIR)/regexp.c \
449 $(SRCDIR)/report.c \
450 $(SRCDIR)/rss.c \
451 $(SRCDIR)/schema.c \
452 $(SRCDIR)/search.c \
453 $(SRCDIR)/setup.c \
454 $(SRCDIR)/sha1.c \
455 $(SRCDIR)/shun.c \
456 $(SRCDIR)/sitemap.c \
457 $(SRCDIR)/skins.c \
458 $(SRCDIR)/sqlcmd.c \
459 $(SRCDIR)/stash.c \
460 $(SRCDIR)/stat.c \
461 $(SRCDIR)/style.c \
@@ -469,10 +495,11 @@
495 $(OBJDIR)/bisect_.c \
496 $(OBJDIR)/blob_.c \
497 $(OBJDIR)/branch_.c \
498 $(OBJDIR)/browse_.c \
499 $(OBJDIR)/builtin_.c \
500 $(OBJDIR)/bundle_.c \
501 $(OBJDIR)/cache_.c \
502 $(OBJDIR)/captcha_.c \
503 $(OBJDIR)/cgi_.c \
504 $(OBJDIR)/checkin_.c \
505 $(OBJDIR)/checkout_.c \
@@ -491,10 +518,11 @@
518 $(OBJDIR)/encode_.c \
519 $(OBJDIR)/event_.c \
520 $(OBJDIR)/export_.c \
521 $(OBJDIR)/file_.c \
522 $(OBJDIR)/finfo_.c \
523 $(OBJDIR)/foci_.c \
524 $(OBJDIR)/fusefs_.c \
525 $(OBJDIR)/glob_.c \
526 $(OBJDIR)/graph_.c \
527 $(OBJDIR)/gzip_.c \
528 $(OBJDIR)/http_.c \
@@ -534,19 +562,22 @@
562 $(OBJDIR)/path_.c \
563 $(OBJDIR)/pivot_.c \
564 $(OBJDIR)/popen_.c \
565 $(OBJDIR)/pqueue_.c \
566 $(OBJDIR)/printf_.c \
567 $(OBJDIR)/publish_.c \
568 $(OBJDIR)/purge_.c \
569 $(OBJDIR)/rebuild_.c \
570 $(OBJDIR)/regexp_.c \
571 $(OBJDIR)/report_.c \
572 $(OBJDIR)/rss_.c \
573 $(OBJDIR)/schema_.c \
574 $(OBJDIR)/search_.c \
575 $(OBJDIR)/setup_.c \
576 $(OBJDIR)/sha1_.c \
577 $(OBJDIR)/shun_.c \
578 $(OBJDIR)/sitemap_.c \
579 $(OBJDIR)/skins_.c \
580 $(OBJDIR)/sqlcmd_.c \
581 $(OBJDIR)/stash_.c \
582 $(OBJDIR)/stat_.c \
583 $(OBJDIR)/style_.c \
@@ -583,10 +614,11 @@
614 $(OBJDIR)/bisect.o \
615 $(OBJDIR)/blob.o \
616 $(OBJDIR)/branch.o \
617 $(OBJDIR)/browse.o \
618 $(OBJDIR)/builtin.o \
619 $(OBJDIR)/bundle.o \
620 $(OBJDIR)/cache.o \
621 $(OBJDIR)/captcha.o \
622 $(OBJDIR)/cgi.o \
623 $(OBJDIR)/checkin.o \
624 $(OBJDIR)/checkout.o \
@@ -605,10 +637,11 @@
637 $(OBJDIR)/encode.o \
638 $(OBJDIR)/event.o \
639 $(OBJDIR)/export.o \
640 $(OBJDIR)/file.o \
641 $(OBJDIR)/finfo.o \
642 $(OBJDIR)/foci.o \
643 $(OBJDIR)/fusefs.o \
644 $(OBJDIR)/glob.o \
645 $(OBJDIR)/graph.o \
646 $(OBJDIR)/gzip.o \
647 $(OBJDIR)/http.o \
@@ -648,19 +681,22 @@
681 $(OBJDIR)/path.o \
682 $(OBJDIR)/pivot.o \
683 $(OBJDIR)/popen.o \
684 $(OBJDIR)/pqueue.o \
685 $(OBJDIR)/printf.o \
686 $(OBJDIR)/publish.o \
687 $(OBJDIR)/purge.o \
688 $(OBJDIR)/rebuild.o \
689 $(OBJDIR)/regexp.o \
690 $(OBJDIR)/report.o \
691 $(OBJDIR)/rss.o \
692 $(OBJDIR)/schema.o \
693 $(OBJDIR)/search.o \
694 $(OBJDIR)/setup.o \
695 $(OBJDIR)/sha1.o \
696 $(OBJDIR)/shun.o \
697 $(OBJDIR)/sitemap.o \
698 $(OBJDIR)/skins.o \
699 $(OBJDIR)/sqlcmd.o \
700 $(OBJDIR)/stash.o \
701 $(OBJDIR)/stat.o \
702 $(OBJDIR)/style.o \
@@ -890,10 +926,11 @@
926 $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \
927 $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \
928 $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \
929 $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \
930 $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \
931 $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \
932 $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \
933 $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \
934 $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \
935 $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \
936 $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \
@@ -912,10 +949,11 @@
949 $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
950 $(OBJDIR)/event_.c:$(OBJDIR)/event.h \
951 $(OBJDIR)/export_.c:$(OBJDIR)/export.h \
952 $(OBJDIR)/file_.c:$(OBJDIR)/file.h \
953 $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
954 $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
955 $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
956 $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \
957 $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \
958 $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \
959 $(OBJDIR)/http_.c:$(OBJDIR)/http.h \
@@ -955,19 +993,22 @@
993 $(OBJDIR)/path_.c:$(OBJDIR)/path.h \
994 $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \
995 $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \
996 $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \
997 $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \
998 $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \
999 $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \
1000 $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \
1001 $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \
1002 $(OBJDIR)/report_.c:$(OBJDIR)/report.h \
1003 $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \
1004 $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \
1005 $(OBJDIR)/search_.c:$(OBJDIR)/search.h \
1006 $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \
1007 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \
1008 $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \
1009 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1010 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1011 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1012 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
1013 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
1014 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
@@ -1073,10 +1114,18 @@
1114
1115 $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h
1116 $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c
1117
1118 $(OBJDIR)/builtin.h: $(OBJDIR)/headers
1119
1120 $(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE)
1121 $(TRANSLATE) $(SRCDIR)/bundle.c >$@
1122
1123 $(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h
1124 $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c
1125
1126 $(OBJDIR)/bundle.h: $(OBJDIR)/headers
1127
1128 $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE)
1129 $(TRANSLATE) $(SRCDIR)/cache.c >$@
1130
1131 $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h
@@ -1249,10 +1298,18 @@
1298
1299 $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
1300 $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
1301
1302 $(OBJDIR)/finfo.h: $(OBJDIR)/headers
1303
1304 $(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(TRANSLATE)
1305 $(TRANSLATE) $(SRCDIR)/foci.c >$@
1306
1307 $(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h
1308 $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c
1309
1310 $(OBJDIR)/foci.h: $(OBJDIR)/headers
1311
1312 $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE)
1313 $(TRANSLATE) $(SRCDIR)/fusefs.c >$@
1314
1315 $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h
@@ -1593,10 +1650,26 @@
1650
1651 $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h
1652 $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c
1653
1654 $(OBJDIR)/printf.h: $(OBJDIR)/headers
1655
1656 $(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE)
1657 $(TRANSLATE) $(SRCDIR)/publish.c >$@
1658
1659 $(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h
1660 $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c
1661
1662 $(OBJDIR)/publish.h: $(OBJDIR)/headers
1663
1664 $(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE)
1665 $(TRANSLATE) $(SRCDIR)/purge.c >$@
1666
1667 $(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h
1668 $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c
1669
1670 $(OBJDIR)/purge.h: $(OBJDIR)/headers
1671
1672 $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE)
1673 $(TRANSLATE) $(SRCDIR)/rebuild.c >$@
1674
1675 $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h
@@ -1665,10 +1738,18 @@
1738
1739 $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h
1740 $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c
1741
1742 $(OBJDIR)/shun.h: $(OBJDIR)/headers
1743
1744 $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE)
1745 $(TRANSLATE) $(SRCDIR)/sitemap.c >$@
1746
1747 $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h
1748 $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c
1749
1750 $(OBJDIR)/sitemap.h: $(OBJDIR)/headers
1751
1752 $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE)
1753 $(TRANSLATE) $(SRCDIR)/skins.c >$@
1754
1755 $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h
1756
+24 -5
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -62,23 +62,32 @@
6262
SSLLIBDIR = $(SSLDIR)\out32
6363
SSLLFLAGS = /nologo /opt:ref /debug
6464
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
6565
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
6666
!message Using 'x64' platform for OpenSSL...
67
-SSLCONFIG = VC-WIN64A no-asm
67
+# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
68
+# SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared
69
+SSLCONFIG = VC-WIN64A no-asm no-shared
6870
SSLSETUP = ms\do_win64a.bat
6971
SSLNMAKE = ms\nt.mak all
72
+SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
7073
!elseif "$(PLATFORM)"=="ia64"
7174
!message Using 'ia64' platform for OpenSSL...
72
-SSLCONFIG = VC-WIN64I no-asm
75
+# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
76
+# SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared
77
+SSLCONFIG = VC-WIN64I no-asm no-shared
7378
SSLSETUP = ms\do_win64i.bat
7479
SSLNMAKE = ms\nt.mak all
80
+SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
7581
!else
7682
!message Assuming 'x86' platform for OpenSSL...
77
-SSLCONFIG = VC-WIN32 no-asm
83
+# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
84
+# SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared
85
+SSLCONFIG = VC-WIN32 no-asm no-shared
7886
SSLSETUP = ms\do_ms.bat
7987
SSLNMAKE = ms\nt.mak all
88
+SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
8089
!endif
8190
!endif
8291
8392
!ifdef FOSSIL_ENABLE_TCL
8493
TCLDIR = $(B)\compat\tcl-8.6
@@ -282,10 +291,11 @@
282291
schema_.c \
283292
search_.c \
284293
setup_.c \
285294
sha1_.c \
286295
shun_.c \
296
+ sitemap_.c \
287297
skins_.c \
288298
sqlcmd_.c \
289299
stash_.c \
290300
stat_.c \
291301
style_.c \
@@ -403,10 +413,11 @@
403413
$(OX)\search$O \
404414
$(OX)\setup$O \
405415
$(OX)\sha1$O \
406416
$(OX)\shell$O \
407417
$(OX)\shun$O \
418
+ $(OX)\sitemap$O \
408419
$(OX)\skins$O \
409420
$(OX)\sqlcmd$O \
410421
$(OX)\sqlite3$O \
411422
$(OX)\stash$O \
412423
$(OX)\stat$O \
@@ -465,13 +476,13 @@
465476
@set PATH=$(PERLDIR);$(PATH)
466477
!endif
467478
@pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
468479
@pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
469480
!ifdef FOSSIL_ENABLE_WINXP
470
- @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
481
+ @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
471482
!else
472
- @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd
483
+ @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd
473484
!endif
474485
!endif
475486
476487
!ifndef FOSSIL_ENABLE_MINIZ
477488
APPTARGETS = $(APPTARGETS) zlib
@@ -576,10 +587,11 @@
576587
echo $(OX)\search.obj >> $@
577588
echo $(OX)\setup.obj >> $@
578589
echo $(OX)\sha1.obj >> $@
579590
echo $(OX)\shell.obj >> $@
580591
echo $(OX)\shun.obj >> $@
592
+ echo $(OX)\sitemap.obj >> $@
581593
echo $(OX)\skins.obj >> $@
582594
echo $(OX)\sqlcmd.obj >> $@
583595
echo $(OX)\sqlite3.obj >> $@
584596
echo $(OX)\stash.obj >> $@
585597
echo $(OX)\stat.obj >> $@
@@ -1229,10 +1241,16 @@
12291241
$(OX)\shun$O : shun_.c shun.h
12301242
$(TCC) /Fo$@ -c shun_.c
12311243
12321244
shun_.c : $(SRCDIR)\shun.c
12331245
translate$E $** > $@
1246
+
1247
+$(OX)\sitemap$O : sitemap_.c sitemap.h
1248
+ $(TCC) /Fo$@ -c sitemap_.c
1249
+
1250
+sitemap_.c : $(SRCDIR)\sitemap.c
1251
+ translate$E $** > $@
12341252
12351253
$(OX)\skins$O : skins_.c skins.h
12361254
$(TCC) /Fo$@ -c skins_.c
12371255
12381256
skins_.c : $(SRCDIR)\skins.c
@@ -1495,10 +1513,11 @@
14951513
schema_.c:schema.h \
14961514
search_.c:search.h \
14971515
setup_.c:setup.h \
14981516
sha1_.c:sha1.h \
14991517
shun_.c:shun.h \
1518
+ sitemap_.c:sitemap.h \
15001519
skins_.c:skins.h \
15011520
sqlcmd_.c:sqlcmd.h \
15021521
stash_.c:stash.h \
15031522
stat_.c:stat.h \
15041523
style_.c:style.h \
15051524
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -62,23 +62,32 @@
62 SSLLIBDIR = $(SSLDIR)\out32
63 SSLLFLAGS = /nologo /opt:ref /debug
64 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
65 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
66 !message Using 'x64' platform for OpenSSL...
67 SSLCONFIG = VC-WIN64A no-asm
 
 
68 SSLSETUP = ms\do_win64a.bat
69 SSLNMAKE = ms\nt.mak all
 
70 !elseif "$(PLATFORM)"=="ia64"
71 !message Using 'ia64' platform for OpenSSL...
72 SSLCONFIG = VC-WIN64I no-asm
 
 
73 SSLSETUP = ms\do_win64i.bat
74 SSLNMAKE = ms\nt.mak all
 
75 !else
76 !message Assuming 'x86' platform for OpenSSL...
77 SSLCONFIG = VC-WIN32 no-asm
 
 
78 SSLSETUP = ms\do_ms.bat
79 SSLNMAKE = ms\nt.mak all
 
80 !endif
81 !endif
82
83 !ifdef FOSSIL_ENABLE_TCL
84 TCLDIR = $(B)\compat\tcl-8.6
@@ -282,10 +291,11 @@
282 schema_.c \
283 search_.c \
284 setup_.c \
285 sha1_.c \
286 shun_.c \
 
287 skins_.c \
288 sqlcmd_.c \
289 stash_.c \
290 stat_.c \
291 style_.c \
@@ -403,10 +413,11 @@
403 $(OX)\search$O \
404 $(OX)\setup$O \
405 $(OX)\sha1$O \
406 $(OX)\shell$O \
407 $(OX)\shun$O \
 
408 $(OX)\skins$O \
409 $(OX)\sqlcmd$O \
410 $(OX)\sqlite3$O \
411 $(OX)\stash$O \
412 $(OX)\stat$O \
@@ -465,13 +476,13 @@
465 @set PATH=$(PERLDIR);$(PATH)
466 !endif
467 @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
468 @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
469 !ifdef FOSSIL_ENABLE_WINXP
470 @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
471 !else
472 @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd
473 !endif
474 !endif
475
476 !ifndef FOSSIL_ENABLE_MINIZ
477 APPTARGETS = $(APPTARGETS) zlib
@@ -576,10 +587,11 @@
576 echo $(OX)\search.obj >> $@
577 echo $(OX)\setup.obj >> $@
578 echo $(OX)\sha1.obj >> $@
579 echo $(OX)\shell.obj >> $@
580 echo $(OX)\shun.obj >> $@
 
581 echo $(OX)\skins.obj >> $@
582 echo $(OX)\sqlcmd.obj >> $@
583 echo $(OX)\sqlite3.obj >> $@
584 echo $(OX)\stash.obj >> $@
585 echo $(OX)\stat.obj >> $@
@@ -1229,10 +1241,16 @@
1229 $(OX)\shun$O : shun_.c shun.h
1230 $(TCC) /Fo$@ -c shun_.c
1231
1232 shun_.c : $(SRCDIR)\shun.c
1233 translate$E $** > $@
 
 
 
 
 
 
1234
1235 $(OX)\skins$O : skins_.c skins.h
1236 $(TCC) /Fo$@ -c skins_.c
1237
1238 skins_.c : $(SRCDIR)\skins.c
@@ -1495,10 +1513,11 @@
1495 schema_.c:schema.h \
1496 search_.c:search.h \
1497 setup_.c:setup.h \
1498 sha1_.c:sha1.h \
1499 shun_.c:shun.h \
 
1500 skins_.c:skins.h \
1501 sqlcmd_.c:sqlcmd.h \
1502 stash_.c:stash.h \
1503 stat_.c:stat.h \
1504 style_.c:style.h \
1505
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -62,23 +62,32 @@
62 SSLLIBDIR = $(SSLDIR)\out32
63 SSLLFLAGS = /nologo /opt:ref /debug
64 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
65 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
66 !message Using 'x64' platform for OpenSSL...
67 # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
68 # SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared
69 SSLCONFIG = VC-WIN64A no-asm no-shared
70 SSLSETUP = ms\do_win64a.bat
71 SSLNMAKE = ms\nt.mak all
72 SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
73 !elseif "$(PLATFORM)"=="ia64"
74 !message Using 'ia64' platform for OpenSSL...
75 # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
76 # SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared
77 SSLCONFIG = VC-WIN64I no-asm no-shared
78 SSLSETUP = ms\do_win64i.bat
79 SSLNMAKE = ms\nt.mak all
80 SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
81 !else
82 !message Assuming 'x86' platform for OpenSSL...
83 # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
84 # SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared
85 SSLCONFIG = VC-WIN32 no-asm no-shared
86 SSLSETUP = ms\do_ms.bat
87 SSLNMAKE = ms\nt.mak all
88 SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3
89 !endif
90 !endif
91
92 !ifdef FOSSIL_ENABLE_TCL
93 TCLDIR = $(B)\compat\tcl-8.6
@@ -282,10 +291,11 @@
291 schema_.c \
292 search_.c \
293 setup_.c \
294 sha1_.c \
295 shun_.c \
296 sitemap_.c \
297 skins_.c \
298 sqlcmd_.c \
299 stash_.c \
300 stat_.c \
301 style_.c \
@@ -403,10 +413,11 @@
413 $(OX)\search$O \
414 $(OX)\setup$O \
415 $(OX)\sha1$O \
416 $(OX)\shell$O \
417 $(OX)\shun$O \
418 $(OX)\sitemap$O \
419 $(OX)\skins$O \
420 $(OX)\sqlcmd$O \
421 $(OX)\sqlite3$O \
422 $(OX)\stash$O \
423 $(OX)\stat$O \
@@ -465,13 +476,13 @@
476 @set PATH=$(PERLDIR);$(PATH)
477 !endif
478 @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
479 @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
480 !ifdef FOSSIL_ENABLE_WINXP
481 @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
482 !else
483 @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd
484 !endif
485 !endif
486
487 !ifndef FOSSIL_ENABLE_MINIZ
488 APPTARGETS = $(APPTARGETS) zlib
@@ -576,10 +587,11 @@
587 echo $(OX)\search.obj >> $@
588 echo $(OX)\setup.obj >> $@
589 echo $(OX)\sha1.obj >> $@
590 echo $(OX)\shell.obj >> $@
591 echo $(OX)\shun.obj >> $@
592 echo $(OX)\sitemap.obj >> $@
593 echo $(OX)\skins.obj >> $@
594 echo $(OX)\sqlcmd.obj >> $@
595 echo $(OX)\sqlite3.obj >> $@
596 echo $(OX)\stash.obj >> $@
597 echo $(OX)\stat.obj >> $@
@@ -1229,10 +1241,16 @@
1241 $(OX)\shun$O : shun_.c shun.h
1242 $(TCC) /Fo$@ -c shun_.c
1243
1244 shun_.c : $(SRCDIR)\shun.c
1245 translate$E $** > $@
1246
1247 $(OX)\sitemap$O : sitemap_.c sitemap.h
1248 $(TCC) /Fo$@ -c sitemap_.c
1249
1250 sitemap_.c : $(SRCDIR)\sitemap.c
1251 translate$E $** > $@
1252
1253 $(OX)\skins$O : skins_.c skins.h
1254 $(TCC) /Fo$@ -c skins_.c
1255
1256 skins_.c : $(SRCDIR)\skins.c
@@ -1495,10 +1513,11 @@
1513 schema_.c:schema.h \
1514 search_.c:search.h \
1515 setup_.c:setup.h \
1516 sha1_.c:sha1.h \
1517 shun_.c:shun.h \
1518 sitemap_.c:sitemap.h \
1519 skins_.c:skins.h \
1520 sqlcmd_.c:sqlcmd.h \
1521 stash_.c:stash.h \
1522 stat_.c:stat.h \
1523 style_.c:style.h \
1524
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -405,11 +405,11 @@
405405
can do pushes or pulls against your server. Use the <b>--port</b>
406406
option to the server command to specify a different TCP port. If
407407
you do not have a local source tree, use the <b>-R</b> command-line
408408
option to specify the repository file.
409409
410
-A stand-alone server is a great way to set of transient connections
410
+The "fossil server" command is a great way to set of transient connections
411411
between coworkers for doing quick pushes or pulls. But you can also
412412
set up a permanent stand-alone server if you prefer. Just make
413413
arrangements for fossil to be launched with appropriate arguments
414414
after every reboot.
415415
416416
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -405,11 +405,11 @@
405 can do pushes or pulls against your server. Use the <b>--port</b>
406 option to the server command to specify a different TCP port. If
407 you do not have a local source tree, use the <b>-R</b> command-line
408 option to specify the repository file.
409
410 A stand-alone server is a great way to set of transient connections
411 between coworkers for doing quick pushes or pulls. But you can also
412 set up a permanent stand-alone server if you prefer. Just make
413 arrangements for fossil to be launched with appropriate arguments
414 after every reboot.
415
416
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -405,11 +405,11 @@
405 can do pushes or pulls against your server. Use the <b>--port</b>
406 option to the server command to specify a different TCP port. If
407 you do not have a local source tree, use the <b>-R</b> command-line
408 option to specify the repository file.
409
410 The "fossil server" command is a great way to set of transient connections
411 between coworkers for doing quick pushes or pulls. But you can also
412 set up a permanent stand-alone server if you prefer. Just make
413 arrangements for fossil to be launched with appropriate arguments
414 after every reboot.
415
416
+8 -8
--- www/faq.tcl
+++ www/faq.tcl
@@ -55,12 +55,12 @@
5555
If you already have a fork in your check-in tree and you want to convert
5656
that fork to a branch, you can do this from the web interface.
5757
First locate the check-in that you want to be
5858
the initial check-in of your branch on the timeline and click on its
5959
link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>"
60
- link (near the "Commands:" label) and click on that. On the
61
- "Edit Check-in" page, check the box beside "Branching:" and fill in
60
+ link (near the "Commands:" label) and click on that. On the
61
+ "Edit Check-in" page, check the box beside "Branching:" and fill in
6262
the name of your new branch to the right and press the "Apply Changes"
6363
button.
6464
}
6565
6666
faq {
@@ -83,31 +83,31 @@
8383
8484
The CHECK-IN in the previous line can be any
8585
[./checkin_names.wiki | valid check-in name format].
8686
8787
You can also add (and remove) tags from a check-in using the
88
- [./webui.wiki | web interface]. First locate the check-in that you
88
+ [./webui.wiki | web interface]. First locate the check-in that you
8989
what to tag on the tmline, then click on the link to go the detailed
9090
information page for that check-in. Then find the "<b>edit</b>"
9191
link (near the "Commands:" label) and click on that. There are
9292
controls on the edit page that allow new tags to be added and existing
9393
tags to be removed.
94
-}
94
+}
9595
9696
faq {
9797
How do I create a private branch that won't get pushed back to the
9898
main repository.
9999
} {
100
- Use the <b>--private</b> command-line option on the
100
+ Use the <b>--private</b> command-line option on the
101101
<b>commit</b> command. The result will be a check-in which exists on
102
- your local repository only and is never pushed to other repositories.
102
+ your local repository only and is never pushed to other repositories.
103103
All descendents of a private check-in are also private.
104
-
104
+
105105
Unless you specify something different using the <b>--branch</b> and/or
106106
<b>--bgcolor</b> options, the new private check-in will be put on a branch
107107
named "private" with an orange background color.
108
-
108
+
109109
You can merge from the trunk into your private branch in order to keep
110110
your private branch in sync with the latest changes on the trunk. Once
111111
you have everything in your private branch the way you want it, you can
112112
then merge your private branch back into the trunk and push. Only the
113113
final merge operation will appear in other repositories. It will seem
114114
--- www/faq.tcl
+++ www/faq.tcl
@@ -55,12 +55,12 @@
55 If you already have a fork in your check-in tree and you want to convert
56 that fork to a branch, you can do this from the web interface.
57 First locate the check-in that you want to be
58 the initial check-in of your branch on the timeline and click on its
59 link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>"
60 link (near the "Commands:" label) and click on that. On the
61 "Edit Check-in" page, check the box beside "Branching:" and fill in
62 the name of your new branch to the right and press the "Apply Changes"
63 button.
64 }
65
66 faq {
@@ -83,31 +83,31 @@
83
84 The CHECK-IN in the previous line can be any
85 [./checkin_names.wiki | valid check-in name format].
86
87 You can also add (and remove) tags from a check-in using the
88 [./webui.wiki | web interface]. First locate the check-in that you
89 what to tag on the tmline, then click on the link to go the detailed
90 information page for that check-in. Then find the "<b>edit</b>"
91 link (near the "Commands:" label) and click on that. There are
92 controls on the edit page that allow new tags to be added and existing
93 tags to be removed.
94 }
95
96 faq {
97 How do I create a private branch that won't get pushed back to the
98 main repository.
99 } {
100 Use the <b>--private</b> command-line option on the
101 <b>commit</b> command. The result will be a check-in which exists on
102 your local repository only and is never pushed to other repositories.
103 All descendents of a private check-in are also private.
104
105 Unless you specify something different using the <b>--branch</b> and/or
106 <b>--bgcolor</b> options, the new private check-in will be put on a branch
107 named "private" with an orange background color.
108
109 You can merge from the trunk into your private branch in order to keep
110 your private branch in sync with the latest changes on the trunk. Once
111 you have everything in your private branch the way you want it, you can
112 then merge your private branch back into the trunk and push. Only the
113 final merge operation will appear in other repositories. It will seem
114
--- www/faq.tcl
+++ www/faq.tcl
@@ -55,12 +55,12 @@
55 If you already have a fork in your check-in tree and you want to convert
56 that fork to a branch, you can do this from the web interface.
57 First locate the check-in that you want to be
58 the initial check-in of your branch on the timeline and click on its
59 link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>"
60 link (near the "Commands:" label) and click on that. On the
61 "Edit Check-in" page, check the box beside "Branching:" and fill in
62 the name of your new branch to the right and press the "Apply Changes"
63 button.
64 }
65
66 faq {
@@ -83,31 +83,31 @@
83
84 The CHECK-IN in the previous line can be any
85 [./checkin_names.wiki | valid check-in name format].
86
87 You can also add (and remove) tags from a check-in using the
88 [./webui.wiki | web interface]. First locate the check-in that you
89 what to tag on the tmline, then click on the link to go the detailed
90 information page for that check-in. Then find the "<b>edit</b>"
91 link (near the "Commands:" label) and click on that. There are
92 controls on the edit page that allow new tags to be added and existing
93 tags to be removed.
94 }
95
96 faq {
97 How do I create a private branch that won't get pushed back to the
98 main repository.
99 } {
100 Use the <b>--private</b> command-line option on the
101 <b>commit</b> command. The result will be a check-in which exists on
102 your local repository only and is never pushed to other repositories.
103 All descendents of a private check-in are also private.
104
105 Unless you specify something different using the <b>--branch</b> and/or
106 <b>--bgcolor</b> options, the new private check-in will be put on a branch
107 named "private" with an orange background color.
108
109 You can merge from the trunk into your private branch in order to keep
110 your private branch in sync with the latest changes on the trunk. Once
111 you have everything in your private branch the way you want it, you can
112 then merge your private branch back into the trunk and push. Only the
113 final merge operation will appear in other repositories. It will seem
114
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -49,11 +49,11 @@
4949
</ul>
5050
5151
These seven artifact types are described in the following sections.
5252
5353
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
54
+make up a fossil repository are stored as delta- and zlib-compressed
5555
blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This
5656
is an implementation detail and might change in a future release. For
5757
the purpose of this article "file format" means the format of the artifacts,
5858
not how the artifacts are stored on disk. It is the artifact format that
5959
is intended to be enduring. The specifics of how artifacts are stored on
@@ -184,11 +184,11 @@
184184
ancestor, the Q-card is used to identify a single check-in or a small
185185
range of check-ins which were cherry-picked for inclusion in or
186186
exclusion from the current manifest. The first argument of
187187
the Q-card is the artifact ID of another manifest (the "target")
188188
which has had its changes included or excluded in the current manifest.
189
-The target is preceeded by "+" or "-" to show inclusion or
189
+The target is preceded by "+" or "-" to show inclusion or
190190
exclusion, respectively. The optional second argument to the
191191
Q-card is another manifest artifact ID which is the "baseline"
192192
for the cherry-pick. If omitted, the baseline is the primary
193193
parent of the target. The
194194
changes included or excluded consist of all changes moving from
@@ -315,11 +315,11 @@
315315
is either "+", "-", or "*". The "+" means the tag should be added
316316
to the artifact. The "-" means the tag should be removed.
317317
The "*" character means the tag should be added to the artifact
318318
and all direct descendants (but not descendents through a merge) down
319319
to but not including the first descendant that contains a
320
-more recent "-" or "+" tag with the same name.
320
+more recent "-", "*", or "+" tag with the same name.
321321
The optional third argument is the value of the tag. A tag
322322
without a value is a boolean.
323323
324324
When two or more tags with the same name are applied to the
325325
same artifact, the tag with the latest (most recent) date is
@@ -362,11 +362,11 @@
362362
gives the name of the wiki page. The optional N card specifies
363363
the mimetype of the wiki text. If the N card is omitted, the
364364
mimetype is assumed to be text/x-fossil-wiki.
365365
The U card specifies the login
366366
of the user who made this edit to the wiki page. The Z card is
367
-the usual checksum over the either artifact and is required.
367
+the usual checksum over the entire artifact and is required.
368368
369369
The W card is used to specify the text of the wiki page. The
370370
argument to the W card is an integer which is the number of bytes
371371
of text in the wiki page. That text follows the newline character
372372
that terminates the W card. The wiki text is always followed by one
@@ -453,11 +453,11 @@
453453
454454
There may be zero or one N cards. The N card specifies the mimetype of the
455455
comment text provided in the C card. If the N card is omitted, the C card
456456
mimetype is taken to be text/plain.
457457
458
-A single U card gives the name of the user to added the attachment.
458
+A single U card gives the name of the user who added the attachment.
459459
If an attachment is added anonymously, then the U card may be omitted.
460460
461461
The Z card is the usual checksum over the rest of the attachment artifact.
462462
The Z card is required.
463463
464464
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -49,11 +49,11 @@
49 </ul>
50
51 These seven artifact types are described in the following sections.
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
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
@@ -184,11 +184,11 @@
184 ancestor, the Q-card is used to identify a single check-in or a small
185 range of check-ins which were cherry-picked for inclusion in or
186 exclusion from the current manifest. The first argument of
187 the Q-card is the artifact ID of another manifest (the "target")
188 which has had its changes included or excluded in the current manifest.
189 The target is preceeded by "+" or "-" to show inclusion or
190 exclusion, respectively. The optional second argument to the
191 Q-card is another manifest artifact ID which is the "baseline"
192 for the cherry-pick. If omitted, the baseline is the primary
193 parent of the target. The
194 changes included or excluded consist of all changes moving from
@@ -315,11 +315,11 @@
315 is either "+", "-", or "*". The "+" means the tag should be added
316 to the artifact. The "-" means the tag should be removed.
317 The "*" character means the tag should be added to the artifact
318 and all direct descendants (but not descendents through a merge) down
319 to but not including the first descendant that contains a
320 more recent "-" or "+" tag with the same name.
321 The optional third argument is the value of the tag. A tag
322 without a value is a boolean.
323
324 When two or more tags with the same name are applied to the
325 same artifact, the tag with the latest (most recent) date is
@@ -362,11 +362,11 @@
362 gives the name of the wiki page. The optional N card specifies
363 the mimetype of the wiki text. If the N card is omitted, the
364 mimetype is assumed to be text/x-fossil-wiki.
365 The U card specifies the login
366 of the user who made this edit to the wiki page. The Z card is
367 the usual checksum over the either artifact and is required.
368
369 The W card is used to specify the text of the wiki page. The
370 argument to the W card is an integer which is the number of bytes
371 of text in the wiki page. That text follows the newline character
372 that terminates the W card. The wiki text is always followed by one
@@ -453,11 +453,11 @@
453
454 There may be zero or one N cards. The N card specifies the mimetype of the
455 comment text provided in the C card. If the N card is omitted, the C card
456 mimetype is taken to be text/plain.
457
458 A single U card gives the name of the user to added the attachment.
459 If an attachment is added anonymously, then the U card may be omitted.
460
461 The Z card is the usual checksum over the rest of the attachment artifact.
462 The Z card is required.
463
464
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -49,11 +49,11 @@
49 </ul>
50
51 These seven artifact types are described in the following sections.
52
53 In the current implementation (as of 2009-01-25) the artifacts that
54 make up a fossil repository are stored 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
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
@@ -184,11 +184,11 @@
184 ancestor, the Q-card is used to identify a single check-in or a small
185 range of check-ins which were cherry-picked for inclusion in or
186 exclusion from the current manifest. The first argument of
187 the Q-card is the artifact ID of another manifest (the "target")
188 which has had its changes included or excluded in the current manifest.
189 The target is preceded by "+" or "-" to show inclusion or
190 exclusion, respectively. The optional second argument to the
191 Q-card is another manifest artifact ID which is the "baseline"
192 for the cherry-pick. If omitted, the baseline is the primary
193 parent of the target. The
194 changes included or excluded consist of all changes moving from
@@ -315,11 +315,11 @@
315 is either "+", "-", or "*". The "+" means the tag should be added
316 to the artifact. The "-" means the tag should be removed.
317 The "*" character means the tag should be added to the artifact
318 and all direct descendants (but not descendents through a merge) down
319 to but not including the first descendant that contains a
320 more recent "-", "*", or "+" tag with the same name.
321 The optional third argument is the value of the tag. A tag
322 without a value is a boolean.
323
324 When two or more tags with the same name are applied to the
325 same artifact, the tag with the latest (most recent) date is
@@ -362,11 +362,11 @@
362 gives the name of the wiki page. The optional N card specifies
363 the mimetype of the wiki text. If the N card is omitted, the
364 mimetype is assumed to be text/x-fossil-wiki.
365 The U card specifies the login
366 of the user who made this edit to the wiki page. The Z card is
367 the usual checksum over the entire artifact and is required.
368
369 The W card is used to specify the text of the wiki page. The
370 argument to the W card is an integer which is the number of bytes
371 of text in the wiki page. That text follows the newline character
372 that terminates the W card. The wiki text is always followed by one
@@ -453,11 +453,11 @@
453
454 There may be zero or one N cards. The N card specifies the mimetype of the
455 comment text provided in the C card. If the N card is omitted, the C card
456 mimetype is taken to be text/plain.
457
458 A single U card gives the name of the user who added the attachment.
459 If an attachment is added anonymously, then the U card may be omitted.
460
461 The Z card is the usual checksum over the rest of the attachment artifact.
462 The Z card is required.
463
464
--- www/foss-cklist.wiki
+++ www/foss-cklist.wiki
@@ -5,11 +5,11 @@
55
blog post <a href="http://spot.livejournal.com/308370.html">
66
http://spot.livejournal.com/308370.html</a> (see also
77
<a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and
88
<a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>).
99
Tom's original post assigned point scores to the various elements and
10
-by adding together the individual points, the reader is suppose to be able
10
+by adding together the individual points, the reader is supposed to be able
1111
to judge the likelihood that the project will fail.
1212
The point scores, and the items on the list, clearly reflect Tom's
1313
biases and are not necessarily those of the larger open-source community.
1414
Nevertheless, the policy of the Fossil shall be to strive for a perfect
1515
score.</p>
1616
--- www/foss-cklist.wiki
+++ www/foss-cklist.wiki
@@ -5,11 +5,11 @@
5 blog post <a href="http://spot.livejournal.com/308370.html">
6 http://spot.livejournal.com/308370.html</a> (see also
7 <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and
8 <a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>).
9 Tom's original post assigned point scores to the various elements and
10 by adding together the individual points, the reader is suppose to be able
11 to judge the likelihood that the project will fail.
12 The point scores, and the items on the list, clearly reflect Tom's
13 biases and are not necessarily those of the larger open-source community.
14 Nevertheless, the policy of the Fossil shall be to strive for a perfect
15 score.</p>
16
--- www/foss-cklist.wiki
+++ www/foss-cklist.wiki
@@ -5,11 +5,11 @@
5 blog post <a href="http://spot.livejournal.com/308370.html">
6 http://spot.livejournal.com/308370.html</a> (see also
7 <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and
8 <a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>).
9 Tom's original post assigned point scores to the various elements and
10 by adding together the individual points, the reader is supposed to be able
11 to judge the likelihood that the project will fail.
12 The point scores, and the items on the list, clearly reflect Tom's
13 biases and are not necessarily those of the larger open-source community.
14 Nevertheless, the policy of the Fossil shall be to strive for a perfect
15 score.</p>
16
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -185,11 +185,11 @@
185185
between repositories and working checkouts. A power-loss or system crash
186186
in the middle of Git operation can damage or corrupt the Git repository.
187187
188188
A Fossil repository consists of a single disk file. A single Fossil
189189
repository can serve multiple simultaneous working checkouts.
190
-A Fossil repository is an SQLite database, so it highly resistant
190
+A Fossil repository is an SQLite database, so it is highly resistant
191191
to damage from a power-loss or system crash - incomplete transactions
192192
are simply rolled back after the system reboots.
193193
194194
<h3>3.8 Audit Trail</h3>
195195
196196
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -185,11 +185,11 @@
185 between repositories and working checkouts. A power-loss or system crash
186 in the middle of Git operation can damage or corrupt the Git repository.
187
188 A Fossil repository consists of a single disk file. A single Fossil
189 repository can serve multiple simultaneous working checkouts.
190 A Fossil repository is an SQLite database, so it highly resistant
191 to damage from a power-loss or system crash - incomplete transactions
192 are simply rolled back after the system reboots.
193
194 <h3>3.8 Audit Trail</h3>
195
196
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -185,11 +185,11 @@
185 between repositories and working checkouts. A power-loss or system crash
186 in the middle of Git operation can damage or corrupt the Git repository.
187
188 A Fossil repository consists of a single disk file. A single Fossil
189 repository can serve multiple simultaneous working checkouts.
190 A Fossil repository is an SQLite database, so it is highly resistant
191 to damage from a power-loss or system crash - incomplete transactions
192 are simply rolled back after the system reboots.
193
194 <h3>3.8 Audit Trail</h3>
195
196
--- www/index.wiki
+++ www/index.wiki
@@ -110,10 +110,14 @@
110110
a Fossil repository.
111111
112112
<hr>
113113
<h3>Links For Fossil Users:</h3>
114114
115
+ * "Fuel" is cross-platform GUI front-end for Fossil
116
+ written in Qt. [http://fuelscm.org/].
117
+ Fuel is an independent project run by a different group of
118
+ developers.
115119
* [./reviews.wiki | Testimonials] from satisfied fossil users and
116120
[./quotes.wiki | Quotes] about Fossil and other DVCSes.
117121
* [./faq.wiki | FAQ]
118122
* The [./concepts.wiki | concepts] behind fossil
119123
* [./quickstart.wiki | Quick Start] guide to using fossil
120124
--- www/index.wiki
+++ www/index.wiki
@@ -110,10 +110,14 @@
110 a Fossil repository.
111
112 <hr>
113 <h3>Links For Fossil Users:</h3>
114
 
 
 
 
115 * [./reviews.wiki | Testimonials] from satisfied fossil users and
116 [./quotes.wiki | Quotes] about Fossil and other DVCSes.
117 * [./faq.wiki | FAQ]
118 * The [./concepts.wiki | concepts] behind fossil
119 * [./quickstart.wiki | Quick Start] guide to using fossil
120
--- www/index.wiki
+++ www/index.wiki
@@ -110,10 +110,14 @@
110 a Fossil repository.
111
112 <hr>
113 <h3>Links For Fossil Users:</h3>
114
115 * "Fuel" is cross-platform GUI front-end for Fossil
116 written in Qt. [http://fuelscm.org/].
117 Fuel is an independent project run by a different group of
118 developers.
119 * [./reviews.wiki | Testimonials] from satisfied fossil users and
120 [./quotes.wiki | Quotes] about Fossil and other DVCSes.
121 * [./faq.wiki | FAQ]
122 * The [./concepts.wiki | concepts] behind fossil
123 * [./quickstart.wiki | Quick Start] guide to using fossil
124
+1 -1
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -1,8 +1,8 @@
11
#!/bin/sh
22
#
3
-# Run this TCL script to generate a WIKI page that contains a
3
+# Run this TCL script to generate a WIKI page that contains a
44
# permuted index of the various documentation files.
55
#
66
# tclsh mkindex.tcl >permutedindex.wiki
77
#
88
99
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -1,8 +1,8 @@
1 #!/bin/sh
2 #
3 # Run this TCL script to generate a WIKI page that contains a
4 # permuted index of the various documentation files.
5 #
6 # tclsh mkindex.tcl >permutedindex.wiki
7 #
8
9
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -1,8 +1,8 @@
1 #!/bin/sh
2 #
3 # Run this TCL script to generate a WIKI page that contains a
4 # permuted index of the various documentation files.
5 #
6 # tclsh mkindex.tcl >permutedindex.wiki
7 #
8
9
+1 -1
--- www/server.wiki
+++ www/server.wiki
@@ -70,11 +70,11 @@
7070
need to modify the pathnames for your particular setup.
7171
The final argument is either the name of the fossil repository to be served,
7272
or a directory containing multiple repositories.
7373
</p>
7474
<p>
75
-If you system is running xinetd, then the configuration is likely to be
75
+If your system is running xinetd, then the configuration is likely to be
7676
in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
7777
An xinetd configuration file will appear like this:</p>
7878
<blockquote>
7979
<pre>
8080
service http-alt
8181
--- www/server.wiki
+++ www/server.wiki
@@ -70,11 +70,11 @@
70 need to modify the pathnames for your particular setup.
71 The final argument is either the name of the fossil repository to be served,
72 or a directory containing multiple repositories.
73 </p>
74 <p>
75 If you system is running xinetd, then the configuration is likely to be
76 in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
77 An xinetd configuration file will appear like this:</p>
78 <blockquote>
79 <pre>
80 service http-alt
81
--- www/server.wiki
+++ www/server.wiki
@@ -70,11 +70,11 @@
70 need to modify the pathnames for your particular setup.
71 The final argument is either the name of the fossil repository to be served,
72 or a directory containing multiple repositories.
73 </p>
74 <p>
75 If your system is running xinetd, then the configuration is likely to be
76 in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
77 An xinetd configuration file will appear like this:</p>
78 <blockquote>
79 <pre>
80 service http-alt
81

Keyboard Shortcuts

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