Fossil SCM

Merge the latest trunk changes into the arjen-doc-updates branch.

drh 2011-05-24 12:00 UTC arjen-doc-updates merge
Commit 5d4ef37a9d222f11ee972ac7734e9c1154ade5cc
89 files changed +1 -1 +140 -243 +4 -4 +4 -4 +8 -8 +8 -8 +43 -5 +25 -11 +25 -11 +1 -1 +29 -8 +41 -102 +41 -102 +6 -6 +6 -6 +2 -2 +12 -12 +12 -12 +6 -6 +7 -15 +479 -91 +479 -91 +9 -5 +60 -47 +7 -13 +26 -11 +88 -18 +5 -5 +4 -4 +4 -4 +176 -28 +34 -11 +88 +35 -15 +15 -13 +9 +6 -5 +8 -8 +35 -26 +51 -3 +26 -16 +42 -35 +12 -2 +6 -8 +18 -16 +2 -2 +19 -17 +19 -20 +5 -5 +10 -9 +27 -1 +127 -40 +18 -12 +41 -21 +7 -6 +2 -2 +11 -8 +15 -1 +27 -18 +59 +1584 -416 +341 -77 +14 -14 +11 +5 -5 +5 -5 +19 -33 +2 -1 +15 -14 +30 -24 +15 -15 +15 -14 +70 -15 +5 -5 +1 +8 -8 +53 -75 +3 -3 +63 -22 +44 -18 +30 -28 +1 -1 +11 -7 +12 -2 +11 -7 +52 -26 +1 -1 +8 -3
+1 -1
--- Makefile
+++ Makefile
@@ -58,11 +58,11 @@
5858
5959
# You should not need to change anything below this line
6060
###############################################################################
6161
#
6262
# Automatic platform-specific options.
63
-HOST_OS!= uname -s
63
+HOST_OS :sh = uname -s
6464
6565
LIB.SunOS= -lsocket -lnsl
6666
LIB += $(LIB.$(HOST_OS))
6767
6868
TCC.DragonFly += -DUSE_PREAD
6969
--- Makefile
+++ Makefile
@@ -58,11 +58,11 @@
58
59 # You should not need to change anything below this line
60 ###############################################################################
61 #
62 # Automatic platform-specific options.
63 HOST_OS!= uname -s
64
65 LIB.SunOS= -lsocket -lnsl
66 LIB += $(LIB.$(HOST_OS))
67
68 TCC.DragonFly += -DUSE_PREAD
69
--- Makefile
+++ Makefile
@@ -58,11 +58,11 @@
58
59 # You should not need to change anything below this line
60 ###############################################################################
61 #
62 # Automatic platform-specific options.
63 HOST_OS :sh = uname -s
64
65 LIB.SunOS= -lsocket -lnsl
66 LIB += $(LIB.$(HOST_OS))
67
68 TCC.DragonFly += -DUSE_PREAD
69
+140 -243
--- src/add.c
+++ src/add.c
@@ -85,132 +85,77 @@
8585
zAll = blob_str(&x);
8686
}
8787
return zAll;
8888
}
8989
90
-
91
-/*
92
-** The pIgnore statement is query of the form:
93
-**
94
-** SELECT (:x GLOB ... OR :x GLOB ... OR ...)
95
-**
96
-** In other words, it is a query that returns true if the :x value
97
-** should be ignored. Evaluate the query and return true to ignore
98
-** and false to not ignore.
99
-**
100
-** If pIgnore is NULL, then do not ignore.
101
-*/
102
-static int shouldBeIgnored(Stmt *pIgnore, const char *zName){
103
- int rc = 0;
104
- if( pIgnore ){
105
- db_bind_text(pIgnore, ":x", zName);
106
- db_step(pIgnore);
107
- rc = db_column_int(pIgnore, 0);
108
- db_reset(pIgnore);
109
- }
110
- return rc;
111
-}
112
-
113
-
11490
/*
11591
** Add a single file named zName to the VFILE table with vid.
11692
**
11793
** Omit any file whose name is pOmit.
11894
*/
119
-static void add_one_file(
120
- const char *zName, /* Name of file to add */
121
- int vid, /* Add to this VFILE */
122
- Blob *pOmit
123
-){
124
- Blob pathname;
125
- const char *zPath;
126
- int i;
127
- const char *zReserved;
128
-
129
- file_tree_name(zName, &pathname, 1);
130
- zPath = blob_str(&pathname);
131
- for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
132
- if( fossil_strcmp(zPath, zReserved)==0 ) break;
133
- }
134
- if( zReserved || (pOmit && blob_compare(&pathname, pOmit)==0) ){
135
- fossil_warning("cannot add %s", zPath);
136
- }else{
137
- if( !file_is_simple_pathname(zPath) ){
138
- fossil_fatal("filename contains illegal characters: %s", zPath);
139
- }
140
-#if defined(_WIN32)
141
- if( db_exists("SELECT 1 FROM vfile"
142
- " WHERE pathname=%Q COLLATE nocase", zPath) ){
143
- db_multi_exec("UPDATE vfile SET deleted=0"
144
- " WHERE pathname=%Q COLLATE nocase", zPath);
145
- }
146
-#else
147
- if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
148
- db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
149
- }
150
-#endif
151
- else{
152
- db_multi_exec(
153
- "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
154
- "VALUES(%d,0,0,0,%Q,%d)",
155
- vid, zPath,file_isexe(zName));
156
- }
157
- printf("ADDED %s\n", zPath);
158
- }
159
- blob_reset(&pathname);
160
-}
161
-
162
-/*
163
-** All content of the zDir directory to the SFILE table.
164
-*/
165
-void add_directory_content(const char *zDir, Stmt *pIgnore){
166
- DIR *d;
167
- int origSize;
168
- struct dirent *pEntry;
169
- Blob path;
170
-
171
- blob_zero(&path);
172
- blob_append(&path, zDir, -1);
173
- origSize = blob_size(&path);
174
- d = opendir(zDir);
175
- if( d ){
176
- while( (pEntry=readdir(d))!=0 ){
177
- char *zPath;
178
- if( pEntry->d_name[0]=='.' ){
179
- if( !includeDotFiles ) continue;
180
- if( pEntry->d_name[1]==0 ) continue;
181
- if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
182
- }
183
- blob_appendf(&path, "/%s", pEntry->d_name);
184
- zPath = blob_str(&path);
185
- if( shouldBeIgnored(pIgnore, zPath) ){
186
- /* Noop */
187
- }else if( file_isdir(zPath)==1 ){
188
- add_directory_content(zPath, pIgnore);
189
- }else if( file_isfile(zPath) ){
190
- db_multi_exec("INSERT INTO sfile VALUES(%Q)", zPath);
191
- }
192
- blob_resize(&path, origSize);
193
- }
194
- closedir(d);
195
- }
196
- blob_reset(&path);
197
-}
198
-
199
-/*
200
-** Add all content of a directory.
201
-*/
202
-void add_directory(const char *zDir, int vid, Blob *pOmit, Stmt *pIgnore){
203
- Stmt q;
204
- add_directory_content(zDir, pIgnore);
205
- db_prepare(&q, "SELECT x FROM sfile ORDER BY x");
206
- while( db_step(&q)==SQLITE_ROW ){
207
- const char *zName = db_column_text(&q, 0);
208
- add_one_file(zName, vid, pOmit);
209
- }
210
- db_finalize(&q);
211
- db_multi_exec("DELETE FROM sfile");
95
+static int add_one_file(
96
+ const char *zPath, /* Tree-name of file to add. */
97
+ int vid /* Add to this VFILE */
98
+){
99
+ if( !file_is_simple_pathname(zPath) ){
100
+ fossil_fatal("filename contains illegal characters: %s", zPath);
101
+ }
102
+#if defined(_WIN32)
103
+ if( db_exists("SELECT 1 FROM vfile"
104
+ " WHERE pathname=%Q COLLATE nocase", zPath) ){
105
+ db_multi_exec("UPDATE vfile SET deleted=0"
106
+ " WHERE pathname=%Q COLLATE nocase", zPath);
107
+ }
108
+#else
109
+ if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
110
+ db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
111
+ }
112
+#endif
113
+ else{
114
+ char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
115
+ db_multi_exec(
116
+ "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
117
+ "VALUES(%d,0,0,0,%Q,%d)",
118
+ vid, zPath, file_isexe(zFullname));
119
+ fossil_free(zFullname);
120
+ }
121
+ fossil_print("ADDED %s\n", zPath);
122
+ return 1;
123
+}
124
+
125
+/*
126
+** Add all files in the sfile temp table.
127
+**
128
+** Automatically exclude the repository file.
129
+*/
130
+static int add_files_in_sfile(int vid){
131
+ const char *zRepo; /* Name of the repository database file */
132
+ int nAdd = 0; /* Number of files added */
133
+ int i; /* Loop counter */
134
+ const char *zReserved; /* Name of a reserved file */
135
+ Blob repoName; /* Treename of the repository */
136
+ Stmt loop; /* SQL to loop over all files to add */
137
+
138
+ if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
139
+ blob_zero(&repoName);
140
+ zRepo = "";
141
+ }else{
142
+ zRepo = blob_str(&repoName);
143
+ }
144
+ db_prepare(&loop, "SELECT x FROM sfile ORDER BY x");
145
+ while( db_step(&loop)==SQLITE_ROW ){
146
+ const char *zToAdd = db_column_text(&loop, 0);
147
+ if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
148
+ for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
149
+ if( fossil_strcmp(zToAdd, zReserved)==0 ) break;
150
+ }
151
+ if( zReserved ) continue;
152
+ nAdd += add_one_file(zToAdd, vid);
153
+ }
154
+ db_finalize(&loop);
155
+ blob_reset(&repoName);
156
+ return nAdd;
212157
}
213158
214159
/*
215160
** COMMAND: add
216161
**
@@ -221,26 +166,24 @@
221166
**
222167
** When adding files or directories recursively, filenames that begin
223168
** with "." are excluded by default. To include such files, add
224169
** the "--dotfiles" option to the command-line.
225170
**
226
-** The --ignore option specifies the patterns for files to be excluded,
227
-** like *.o,*.obj,*.exe. If not specified, the "ignore-glob" setting is
228
-** used. See ** documentation on the "settings" command for further
229
-** information.
230
-**
171
+** The --ignore option is a comma-separate list of glob patterns for files
172
+** to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore option
173
+** does not appear on the command line then the "ignore-glob" setting is
174
+** used.
231175
**
232176
** SUMMARY: fossil add ?OPTIONS? FILE1 ?FILE2 ...?
233177
** Options: --dotfiles, --ignore
234178
*/
235179
void add_cmd(void){
236
- int i;
237
- int vid;
238
- const char *zIgnoreFlag;
239
- Blob repo;
240
- Stmt ignoreTest; /* Test to see if a name should be ignored */
241
- Stmt *pIgnore; /* Pointer to ignoreTest or to NULL */
180
+ int i; /* Loop counter */
181
+ int vid; /* Currently checked out version */
182
+ int nRoot; /* Full path characters in g.zLocalRoot */
183
+ const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
184
+ Glob *pIgnore; /* Ignore everything matching this glob pattern */
242185
243186
zIgnoreFlag = find_option("ignore",0,1);
244187
includeDotFiles = find_option("dotfiles",0,0)!=0;
245188
db_must_be_within_tree();
246189
if( zIgnoreFlag==0 ){
@@ -249,101 +192,49 @@
249192
vid = db_lget_int("checkout",0);
250193
if( vid==0 ){
251194
fossil_panic("no checkout to add to");
252195
}
253196
db_begin_transaction();
254
- if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
255
- blob_zero(&repo);
256
- }
257197
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
258198
#if defined(_WIN32)
259199
db_multi_exec(
260200
"CREATE INDEX IF NOT EXISTS vfile_pathname "
261201
" ON vfile(pathname COLLATE nocase)"
262202
);
263203
#endif
264
- if( zIgnoreFlag && zIgnoreFlag[0] ){
265
- db_prepare(&ignoreTest, "SELECT %s", glob_expr(":x", zIgnoreFlag));
266
- pIgnore = &ignoreTest;
267
- }else{
268
- pIgnore = 0;
269
- }
204
+ pIgnore = glob_create(zIgnoreFlag);
205
+ nRoot = strlen(g.zLocalRoot);
206
+
207
+ /* Load the names of all files that are to be added into sfile temp table */
270208
for(i=2; i<g.argc; i++){
271209
char *zName;
272210
int isDir;
211
+ Blob fullName;
273212
274
- zName = mprintf("%/", g.argv[i]);
213
+ file_canonical_name(g.argv[i], &fullName);
214
+ zName = blob_str(&fullName);
275215
isDir = file_isdir(zName);
276216
if( isDir==1 ){
277
- int sz = strlen(zName);
278
- if( sz>0 && zName[sz-1]=='/' ){ zName[sz-1] = 0; }
279
- add_directory(zName, vid, &repo, pIgnore);
217
+ vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
280218
}else if( isDir==0 ){
281219
fossil_fatal("not found: %s", zName);
282
- }else if( access(zName, R_OK) ){
220
+ }else if( file_access(zName, R_OK) ){
283221
fossil_fatal("cannot open %s", zName);
284222
}else{
285
- add_one_file(zName, vid, &repo);
286
- }
287
- free(zName);
288
- }
289
- if( pIgnore ) db_finalize(pIgnore);
290
- db_end_transaction(0);
291
-}
292
-
293
-
294
-/*
295
-** Unmangage a single file.
296
-*/
297
-void delete_one_file(const char *zName){
298
- char *zPath;
299
- Blob pathname;
300
- file_tree_name(zName, &pathname, 1);
301
- zPath = blob_str(&pathname);
302
- if( !db_exists(
303
- "SELECT 1 FROM vfile WHERE pathname=%Q AND NOT deleted", zPath) ){
304
- fossil_fatal("not in the repository: %s", zName);
305
- }else{
306
- db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zPath);
307
- printf("DELETED %s\n", zPath);
308
- }
309
- blob_reset(&pathname);
310
-}
311
-
312
-/*
313
-** Remove all contents of zDir
314
-*/
315
-void del_directory_content(const char *zDir){
316
- DIR *d;
317
- int origSize;
318
- struct dirent *pEntry;
319
- Blob path;
320
-
321
- blob_zero(&path);
322
- blob_append(&path, zDir, -1);
323
- origSize = blob_size(&path);
324
- d = opendir(zDir);
325
- if( d ){
326
- while( (pEntry=readdir(d))!=0 ){
327
- char *zPath;
328
- if( pEntry->d_name[0]=='.'){
329
- if( !includeDotFiles ) continue;
330
- if( pEntry->d_name[1]==0 ) continue;
331
- if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
332
- }
333
- blob_appendf(&path, "/%s", pEntry->d_name);
334
- zPath = blob_str(&path);
335
- if( file_isdir(zPath)==1 ){
336
- del_directory_content(zPath);
337
- }else if( file_isfile(zPath) ){
338
- delete_one_file(zPath);
339
- }
340
- blob_resize(&path, origSize);
341
- }
342
- closedir(d);
343
- }
344
- blob_reset(&path);
223
+ char *zTreeName = &zName[nRoot];
224
+ db_multi_exec(
225
+ "INSERT OR IGNORE INTO sfile(x)"
226
+ " SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=%Q)",
227
+ zTreeName, zTreeName
228
+ );
229
+ }
230
+ blob_reset(&fullName);
231
+ }
232
+ glob_free(pIgnore);
233
+
234
+ add_files_in_sfile(vid);
235
+ db_end_transaction(0);
345236
}
346237
347238
/*
348239
** COMMAND: rm
349240
** COMMAND: delete
@@ -361,31 +252,45 @@
361252
** or: fossil delete FILE1 ?FILE2 ...?
362253
*/
363254
void delete_cmd(void){
364255
int i;
365256
int vid;
257
+ Stmt loop;
366258
367259
db_must_be_within_tree();
368260
vid = db_lget_int("checkout", 0);
369261
if( vid==0 ){
370262
fossil_panic("no checkout to remove from");
371263
}
372264
db_begin_transaction();
265
+ db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
373266
for(i=2; i<g.argc; i++){
374
- char *zName;
375
-
376
- zName = mprintf("%/", g.argv[i]);
377
- if( file_isdir(zName) == 1 ){
378
- int sz = strlen(zName);
379
- if( sz>0 && zName[sz-1]=='/' ){ zName[sz-1] = 0; }
380
- del_directory_content(zName);
381
- } else {
382
- delete_one_file(zName);
383
- }
384
- free(zName);
385
- }
386
- db_multi_exec("DELETE FROM vfile WHERE deleted AND rid=0");
267
+ Blob treeName;
268
+ char *zTreeName;
269
+
270
+ file_tree_name(g.argv[i], &treeName, 1);
271
+ zTreeName = blob_str(&treeName);
272
+ db_multi_exec(
273
+ "INSERT OR IGNORE INTO sfile"
274
+ " SELECT pathname FROM vfile"
275
+ " WHERE (pathname=%Q"
276
+ " OR (pathname>'%q/' AND pathname<'%q0'))"
277
+ " AND NOT deleted",
278
+ zTreeName, zTreeName, zTreeName
279
+ );
280
+ blob_reset(&treeName);
281
+ }
282
+
283
+ db_prepare(&loop, "SELECT x FROM sfile");
284
+ while( db_step(&loop)==SQLITE_ROW ){
285
+ fossil_print("DELETED %s\n", db_column_text(&loop, 0));
286
+ }
287
+ db_finalize(&loop);
288
+ db_multi_exec(
289
+ "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
290
+ "DELETE FROM vfile WHERE rid=0 AND deleted;"
291
+ );
387292
db_end_transaction(0);
388293
}
389294
390295
/*
391296
** COMMAND: addremove
@@ -426,13 +331,13 @@
426331
int allFlag = find_option("dotfiles",0,0)!=0;
427332
int isTest = find_option("test",0,0)!=0;
428333
int n;
429334
Stmt q;
430335
int vid;
431
- Blob repo;
432336
int nAdd = 0;
433337
int nDelete = 0;
338
+ Glob *pIgnore;
434339
435340
db_must_be_within_tree();
436341
if( zIgnoreFlag==0 ){
437342
zIgnoreFlag = db_get("ignore-glob", 0);
438343
}
@@ -439,38 +344,30 @@
439344
vid = db_lget_int("checkout",0);
440345
if( vid==0 ){
441346
fossil_panic("no checkout to add to");
442347
}
443348
db_begin_transaction();
349
+
350
+ /* step 1:
351
+ ** Populate the temp table "sfile" with the names of all unmanged
352
+ ** files currently in the check-out, except for files that match the
353
+ ** --ignore or ignore-glob patterns and dot-files. Then add all of
354
+ ** the files in the sfile temp table to the set of managed files.
355
+ */
444356
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
445357
n = strlen(g.zLocalRoot);
446358
blob_init(&path, g.zLocalRoot, n-1);
447359
/* now we read the complete file structure into a temp table */
448
- vfile_scan(0, &path, blob_size(&path), allFlag);
449
- if( file_tree_name(g.zRepositoryName, &repo, 0) ){
450
- db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
451
- }
452
-
453
- /* step 1: search for extra files */
454
- db_prepare(&q,
455
- "SELECT x, %Q || x FROM sfile"
456
- " WHERE x NOT IN (%s)"
457
- " AND NOT %s"
458
- " ORDER BY 1",
459
- g.zLocalRoot,
460
- fossil_all_reserved_names(),
461
- glob_expr("x", zIgnoreFlag)
462
- );
463
- while( db_step(&q)==SQLITE_ROW ){
464
- add_one_file(db_column_text(&q, 1), vid, 0);
465
- nAdd++;
466
- }
467
- db_finalize(&q);
360
+ pIgnore = glob_create(zIgnoreFlag);
361
+ vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
362
+ glob_free(pIgnore);
363
+ nAdd = add_files_in_sfile(vid);
364
+
468365
/* step 2: search for missing files */
469366
db_prepare(&q,
470
- "SELECT pathname,%Q || pathname,deleted FROM vfile"
471
- " WHERE deleted!=1"
367
+ "SELECT pathname, %Q || pathname, deleted FROM vfile"
368
+ " WHERE NOT deleted"
472369
" ORDER BY 1",
473370
g.zLocalRoot
474371
);
475372
while( db_step(&q)==SQLITE_ROW ){
476373
const char * zFile;
@@ -480,17 +377,17 @@
480377
zPath = db_column_text(&q, 1);
481378
if( !file_isfile(zPath) ){
482379
if( !isTest ){
483380
db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
484381
}
485
- printf("DELETED %s\n", zFile);
382
+ fossil_print("DELETED %s\n", zFile);
486383
nDelete++;
487384
}
488385
}
489386
db_finalize(&q);
490387
/* show cmmand summary */
491
- printf("added %d files, deleted %d files\n", nAdd, nDelete);
388
+ fossil_print("added %d files, deleted %d files\n", nAdd, nDelete);
492389
493390
db_end_transaction(isTest);
494391
}
495392
496393
@@ -498,11 +395,11 @@
498395
** Rename a single file.
499396
**
500397
** The original name of the file is zOrig. The new filename is zNew.
501398
*/
502399
static void mv_one_file(int vid, const char *zOrig, const char *zNew){
503
- printf("RENAME %s %s\n", zOrig, zNew);
400
+ fossil_print("RENAME %s %s\n", zOrig, zNew);
504401
db_multi_exec(
505402
"UPDATE vfile SET pathname='%s' WHERE pathname='%s' AND vid=%d",
506403
zNew, zOrig, vid
507404
);
508405
}
@@ -572,13 +469,13 @@
572469
zOrig = blob_str(&orig);
573470
nOrig = blob_size(&orig);
574471
db_prepare(&q,
575472
"SELECT pathname FROM vfile"
576473
" WHERE vid=%d"
577
- " AND (pathname='%s' OR pathname GLOB '%s/*')"
474
+ " AND (pathname='%q' OR (pathname>'%q/' AND pathname<'%q0'))"
578475
" ORDER BY 1",
579
- vid, zOrig, zOrig
476
+ vid, zOrig, zOrig, zOrig
580477
);
581478
while( db_step(&q)==SQLITE_ROW ){
582479
const char *zPath = db_column_text(&q, 0);
583480
int nPath = db_column_bytes(&q, 0);
584481
const char *zTail;
585482
--- src/add.c
+++ src/add.c
@@ -85,132 +85,77 @@
85 zAll = blob_str(&x);
86 }
87 return zAll;
88 }
89
90
91 /*
92 ** The pIgnore statement is query of the form:
93 **
94 ** SELECT (:x GLOB ... OR :x GLOB ... OR ...)
95 **
96 ** In other words, it is a query that returns true if the :x value
97 ** should be ignored. Evaluate the query and return true to ignore
98 ** and false to not ignore.
99 **
100 ** If pIgnore is NULL, then do not ignore.
101 */
102 static int shouldBeIgnored(Stmt *pIgnore, const char *zName){
103 int rc = 0;
104 if( pIgnore ){
105 db_bind_text(pIgnore, ":x", zName);
106 db_step(pIgnore);
107 rc = db_column_int(pIgnore, 0);
108 db_reset(pIgnore);
109 }
110 return rc;
111 }
112
113
114 /*
115 ** Add a single file named zName to the VFILE table with vid.
116 **
117 ** Omit any file whose name is pOmit.
118 */
119 static void add_one_file(
120 const char *zName, /* Name of file to add */
121 int vid, /* Add to this VFILE */
122 Blob *pOmit
123 ){
124 Blob pathname;
125 const char *zPath;
126 int i;
127 const char *zReserved;
128
129 file_tree_name(zName, &pathname, 1);
130 zPath = blob_str(&pathname);
131 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
132 if( fossil_strcmp(zPath, zReserved)==0 ) break;
133 }
134 if( zReserved || (pOmit && blob_compare(&pathname, pOmit)==0) ){
135 fossil_warning("cannot add %s", zPath);
136 }else{
137 if( !file_is_simple_pathname(zPath) ){
138 fossil_fatal("filename contains illegal characters: %s", zPath);
139 }
140 #if defined(_WIN32)
141 if( db_exists("SELECT 1 FROM vfile"
142 " WHERE pathname=%Q COLLATE nocase", zPath) ){
143 db_multi_exec("UPDATE vfile SET deleted=0"
144 " WHERE pathname=%Q COLLATE nocase", zPath);
145 }
146 #else
147 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
148 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
149 }
150 #endif
151 else{
152 db_multi_exec(
153 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
154 "VALUES(%d,0,0,0,%Q,%d)",
155 vid, zPath,file_isexe(zName));
156 }
157 printf("ADDED %s\n", zPath);
158 }
159 blob_reset(&pathname);
160 }
161
162 /*
163 ** All content of the zDir directory to the SFILE table.
164 */
165 void add_directory_content(const char *zDir, Stmt *pIgnore){
166 DIR *d;
167 int origSize;
168 struct dirent *pEntry;
169 Blob path;
170
171 blob_zero(&path);
172 blob_append(&path, zDir, -1);
173 origSize = blob_size(&path);
174 d = opendir(zDir);
175 if( d ){
176 while( (pEntry=readdir(d))!=0 ){
177 char *zPath;
178 if( pEntry->d_name[0]=='.' ){
179 if( !includeDotFiles ) continue;
180 if( pEntry->d_name[1]==0 ) continue;
181 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
182 }
183 blob_appendf(&path, "/%s", pEntry->d_name);
184 zPath = blob_str(&path);
185 if( shouldBeIgnored(pIgnore, zPath) ){
186 /* Noop */
187 }else if( file_isdir(zPath)==1 ){
188 add_directory_content(zPath, pIgnore);
189 }else if( file_isfile(zPath) ){
190 db_multi_exec("INSERT INTO sfile VALUES(%Q)", zPath);
191 }
192 blob_resize(&path, origSize);
193 }
194 closedir(d);
195 }
196 blob_reset(&path);
197 }
198
199 /*
200 ** Add all content of a directory.
201 */
202 void add_directory(const char *zDir, int vid, Blob *pOmit, Stmt *pIgnore){
203 Stmt q;
204 add_directory_content(zDir, pIgnore);
205 db_prepare(&q, "SELECT x FROM sfile ORDER BY x");
206 while( db_step(&q)==SQLITE_ROW ){
207 const char *zName = db_column_text(&q, 0);
208 add_one_file(zName, vid, pOmit);
209 }
210 db_finalize(&q);
211 db_multi_exec("DELETE FROM sfile");
212 }
213
214 /*
215 ** COMMAND: add
216 **
@@ -221,26 +166,24 @@
221 **
222 ** When adding files or directories recursively, filenames that begin
223 ** with "." are excluded by default. To include such files, add
224 ** the "--dotfiles" option to the command-line.
225 **
226 ** The --ignore option specifies the patterns for files to be excluded,
227 ** like *.o,*.obj,*.exe. If not specified, the "ignore-glob" setting is
228 ** used. See ** documentation on the "settings" command for further
229 ** information.
230 **
231 **
232 ** SUMMARY: fossil add ?OPTIONS? FILE1 ?FILE2 ...?
233 ** Options: --dotfiles, --ignore
234 */
235 void add_cmd(void){
236 int i;
237 int vid;
238 const char *zIgnoreFlag;
239 Blob repo;
240 Stmt ignoreTest; /* Test to see if a name should be ignored */
241 Stmt *pIgnore; /* Pointer to ignoreTest or to NULL */
242
243 zIgnoreFlag = find_option("ignore",0,1);
244 includeDotFiles = find_option("dotfiles",0,0)!=0;
245 db_must_be_within_tree();
246 if( zIgnoreFlag==0 ){
@@ -249,101 +192,49 @@
249 vid = db_lget_int("checkout",0);
250 if( vid==0 ){
251 fossil_panic("no checkout to add to");
252 }
253 db_begin_transaction();
254 if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
255 blob_zero(&repo);
256 }
257 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
258 #if defined(_WIN32)
259 db_multi_exec(
260 "CREATE INDEX IF NOT EXISTS vfile_pathname "
261 " ON vfile(pathname COLLATE nocase)"
262 );
263 #endif
264 if( zIgnoreFlag && zIgnoreFlag[0] ){
265 db_prepare(&ignoreTest, "SELECT %s", glob_expr(":x", zIgnoreFlag));
266 pIgnore = &ignoreTest;
267 }else{
268 pIgnore = 0;
269 }
270 for(i=2; i<g.argc; i++){
271 char *zName;
272 int isDir;
 
273
274 zName = mprintf("%/", g.argv[i]);
 
275 isDir = file_isdir(zName);
276 if( isDir==1 ){
277 int sz = strlen(zName);
278 if( sz>0 && zName[sz-1]=='/' ){ zName[sz-1] = 0; }
279 add_directory(zName, vid, &repo, pIgnore);
280 }else if( isDir==0 ){
281 fossil_fatal("not found: %s", zName);
282 }else if( access(zName, R_OK) ){
283 fossil_fatal("cannot open %s", zName);
284 }else{
285 add_one_file(zName, vid, &repo);
286 }
287 free(zName);
288 }
289 if( pIgnore ) db_finalize(pIgnore);
290 db_end_transaction(0);
291 }
292
293
294 /*
295 ** Unmangage a single file.
296 */
297 void delete_one_file(const char *zName){
298 char *zPath;
299 Blob pathname;
300 file_tree_name(zName, &pathname, 1);
301 zPath = blob_str(&pathname);
302 if( !db_exists(
303 "SELECT 1 FROM vfile WHERE pathname=%Q AND NOT deleted", zPath) ){
304 fossil_fatal("not in the repository: %s", zName);
305 }else{
306 db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zPath);
307 printf("DELETED %s\n", zPath);
308 }
309 blob_reset(&pathname);
310 }
311
312 /*
313 ** Remove all contents of zDir
314 */
315 void del_directory_content(const char *zDir){
316 DIR *d;
317 int origSize;
318 struct dirent *pEntry;
319 Blob path;
320
321 blob_zero(&path);
322 blob_append(&path, zDir, -1);
323 origSize = blob_size(&path);
324 d = opendir(zDir);
325 if( d ){
326 while( (pEntry=readdir(d))!=0 ){
327 char *zPath;
328 if( pEntry->d_name[0]=='.'){
329 if( !includeDotFiles ) continue;
330 if( pEntry->d_name[1]==0 ) continue;
331 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
332 }
333 blob_appendf(&path, "/%s", pEntry->d_name);
334 zPath = blob_str(&path);
335 if( file_isdir(zPath)==1 ){
336 del_directory_content(zPath);
337 }else if( file_isfile(zPath) ){
338 delete_one_file(zPath);
339 }
340 blob_resize(&path, origSize);
341 }
342 closedir(d);
343 }
344 blob_reset(&path);
345 }
346
347 /*
348 ** COMMAND: rm
349 ** COMMAND: delete
@@ -361,31 +252,45 @@
361 ** or: fossil delete FILE1 ?FILE2 ...?
362 */
363 void delete_cmd(void){
364 int i;
365 int vid;
 
366
367 db_must_be_within_tree();
368 vid = db_lget_int("checkout", 0);
369 if( vid==0 ){
370 fossil_panic("no checkout to remove from");
371 }
372 db_begin_transaction();
 
373 for(i=2; i<g.argc; i++){
374 char *zName;
375
376 zName = mprintf("%/", g.argv[i]);
377 if( file_isdir(zName) == 1 ){
378 int sz = strlen(zName);
379 if( sz>0 && zName[sz-1]=='/' ){ zName[sz-1] = 0; }
380 del_directory_content(zName);
381 } else {
382 delete_one_file(zName);
383 }
384 free(zName);
385 }
386 db_multi_exec("DELETE FROM vfile WHERE deleted AND rid=0");
 
 
 
 
 
 
 
 
 
 
 
 
387 db_end_transaction(0);
388 }
389
390 /*
391 ** COMMAND: addremove
@@ -426,13 +331,13 @@
426 int allFlag = find_option("dotfiles",0,0)!=0;
427 int isTest = find_option("test",0,0)!=0;
428 int n;
429 Stmt q;
430 int vid;
431 Blob repo;
432 int nAdd = 0;
433 int nDelete = 0;
 
434
435 db_must_be_within_tree();
436 if( zIgnoreFlag==0 ){
437 zIgnoreFlag = db_get("ignore-glob", 0);
438 }
@@ -439,38 +344,30 @@
439 vid = db_lget_int("checkout",0);
440 if( vid==0 ){
441 fossil_panic("no checkout to add to");
442 }
443 db_begin_transaction();
 
 
 
 
 
 
 
444 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
445 n = strlen(g.zLocalRoot);
446 blob_init(&path, g.zLocalRoot, n-1);
447 /* now we read the complete file structure into a temp table */
448 vfile_scan(0, &path, blob_size(&path), allFlag);
449 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
450 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
451 }
452
453 /* step 1: search for extra files */
454 db_prepare(&q,
455 "SELECT x, %Q || x FROM sfile"
456 " WHERE x NOT IN (%s)"
457 " AND NOT %s"
458 " ORDER BY 1",
459 g.zLocalRoot,
460 fossil_all_reserved_names(),
461 glob_expr("x", zIgnoreFlag)
462 );
463 while( db_step(&q)==SQLITE_ROW ){
464 add_one_file(db_column_text(&q, 1), vid, 0);
465 nAdd++;
466 }
467 db_finalize(&q);
468 /* step 2: search for missing files */
469 db_prepare(&q,
470 "SELECT pathname,%Q || pathname,deleted FROM vfile"
471 " WHERE deleted!=1"
472 " ORDER BY 1",
473 g.zLocalRoot
474 );
475 while( db_step(&q)==SQLITE_ROW ){
476 const char * zFile;
@@ -480,17 +377,17 @@
480 zPath = db_column_text(&q, 1);
481 if( !file_isfile(zPath) ){
482 if( !isTest ){
483 db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
484 }
485 printf("DELETED %s\n", zFile);
486 nDelete++;
487 }
488 }
489 db_finalize(&q);
490 /* show cmmand summary */
491 printf("added %d files, deleted %d files\n", nAdd, nDelete);
492
493 db_end_transaction(isTest);
494 }
495
496
@@ -498,11 +395,11 @@
498 ** Rename a single file.
499 **
500 ** The original name of the file is zOrig. The new filename is zNew.
501 */
502 static void mv_one_file(int vid, const char *zOrig, const char *zNew){
503 printf("RENAME %s %s\n", zOrig, zNew);
504 db_multi_exec(
505 "UPDATE vfile SET pathname='%s' WHERE pathname='%s' AND vid=%d",
506 zNew, zOrig, vid
507 );
508 }
@@ -572,13 +469,13 @@
572 zOrig = blob_str(&orig);
573 nOrig = blob_size(&orig);
574 db_prepare(&q,
575 "SELECT pathname FROM vfile"
576 " WHERE vid=%d"
577 " AND (pathname='%s' OR pathname GLOB '%s/*')"
578 " ORDER BY 1",
579 vid, zOrig, zOrig
580 );
581 while( db_step(&q)==SQLITE_ROW ){
582 const char *zPath = db_column_text(&q, 0);
583 int nPath = db_column_bytes(&q, 0);
584 const char *zTail;
585
--- src/add.c
+++ src/add.c
@@ -85,132 +85,77 @@
85 zAll = blob_str(&x);
86 }
87 return zAll;
88 }
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90 /*
91 ** Add a single file named zName to the VFILE table with vid.
92 **
93 ** Omit any file whose name is pOmit.
94 */
95 static int add_one_file(
96 const char *zPath, /* Tree-name of file to add. */
97 int vid /* Add to this VFILE */
98 ){
99 if( !file_is_simple_pathname(zPath) ){
100 fossil_fatal("filename contains illegal characters: %s", zPath);
101 }
102 #if defined(_WIN32)
103 if( db_exists("SELECT 1 FROM vfile"
104 " WHERE pathname=%Q COLLATE nocase", zPath) ){
105 db_multi_exec("UPDATE vfile SET deleted=0"
106 " WHERE pathname=%Q COLLATE nocase", zPath);
107 }
108 #else
109 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
110 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
111 }
112 #endif
113 else{
114 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
115 db_multi_exec(
116 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
117 "VALUES(%d,0,0,0,%Q,%d)",
118 vid, zPath, file_isexe(zFullname));
119 fossil_free(zFullname);
120 }
121 fossil_print("ADDED %s\n", zPath);
122 return 1;
123 }
124
125 /*
126 ** Add all files in the sfile temp table.
127 **
128 ** Automatically exclude the repository file.
129 */
130 static int add_files_in_sfile(int vid){
131 const char *zRepo; /* Name of the repository database file */
132 int nAdd = 0; /* Number of files added */
133 int i; /* Loop counter */
134 const char *zReserved; /* Name of a reserved file */
135 Blob repoName; /* Treename of the repository */
136 Stmt loop; /* SQL to loop over all files to add */
137
138 if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
139 blob_zero(&repoName);
140 zRepo = "";
141 }else{
142 zRepo = blob_str(&repoName);
143 }
144 db_prepare(&loop, "SELECT x FROM sfile ORDER BY x");
145 while( db_step(&loop)==SQLITE_ROW ){
146 const char *zToAdd = db_column_text(&loop, 0);
147 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
148 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
149 if( fossil_strcmp(zToAdd, zReserved)==0 ) break;
150 }
151 if( zReserved ) continue;
152 nAdd += add_one_file(zToAdd, vid);
153 }
154 db_finalize(&loop);
155 blob_reset(&repoName);
156 return nAdd;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157 }
158
159 /*
160 ** COMMAND: add
161 **
@@ -221,26 +166,24 @@
166 **
167 ** When adding files or directories recursively, filenames that begin
168 ** with "." are excluded by default. To include such files, add
169 ** the "--dotfiles" option to the command-line.
170 **
171 ** The --ignore option is a comma-separate list of glob patterns for files
172 ** to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore option
173 ** does not appear on the command line then the "ignore-glob" setting is
174 ** used.
 
175 **
176 ** SUMMARY: fossil add ?OPTIONS? FILE1 ?FILE2 ...?
177 ** Options: --dotfiles, --ignore
178 */
179 void add_cmd(void){
180 int i; /* Loop counter */
181 int vid; /* Currently checked out version */
182 int nRoot; /* Full path characters in g.zLocalRoot */
183 const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
184 Glob *pIgnore; /* Ignore everything matching this glob pattern */
 
185
186 zIgnoreFlag = find_option("ignore",0,1);
187 includeDotFiles = find_option("dotfiles",0,0)!=0;
188 db_must_be_within_tree();
189 if( zIgnoreFlag==0 ){
@@ -249,101 +192,49 @@
192 vid = db_lget_int("checkout",0);
193 if( vid==0 ){
194 fossil_panic("no checkout to add to");
195 }
196 db_begin_transaction();
 
 
 
197 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
198 #if defined(_WIN32)
199 db_multi_exec(
200 "CREATE INDEX IF NOT EXISTS vfile_pathname "
201 " ON vfile(pathname COLLATE nocase)"
202 );
203 #endif
204 pIgnore = glob_create(zIgnoreFlag);
205 nRoot = strlen(g.zLocalRoot);
206
207 /* Load the names of all files that are to be added into sfile temp table */
 
 
208 for(i=2; i<g.argc; i++){
209 char *zName;
210 int isDir;
211 Blob fullName;
212
213 file_canonical_name(g.argv[i], &fullName);
214 zName = blob_str(&fullName);
215 isDir = file_isdir(zName);
216 if( isDir==1 ){
217 vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
 
 
218 }else if( isDir==0 ){
219 fossil_fatal("not found: %s", zName);
220 }else if( file_access(zName, R_OK) ){
221 fossil_fatal("cannot open %s", zName);
222 }else{
223 char *zTreeName = &zName[nRoot];
224 db_multi_exec(
225 "INSERT OR IGNORE INTO sfile(x)"
226 " SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=%Q)",
227 zTreeName, zTreeName
228 );
229 }
230 blob_reset(&fullName);
231 }
232 glob_free(pIgnore);
233
234 add_files_in_sfile(vid);
235 db_end_transaction(0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236 }
237
238 /*
239 ** COMMAND: rm
240 ** COMMAND: delete
@@ -361,31 +252,45 @@
252 ** or: fossil delete FILE1 ?FILE2 ...?
253 */
254 void delete_cmd(void){
255 int i;
256 int vid;
257 Stmt loop;
258
259 db_must_be_within_tree();
260 vid = db_lget_int("checkout", 0);
261 if( vid==0 ){
262 fossil_panic("no checkout to remove from");
263 }
264 db_begin_transaction();
265 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
266 for(i=2; i<g.argc; i++){
267 Blob treeName;
268 char *zTreeName;
269
270 file_tree_name(g.argv[i], &treeName, 1);
271 zTreeName = blob_str(&treeName);
272 db_multi_exec(
273 "INSERT OR IGNORE INTO sfile"
274 " SELECT pathname FROM vfile"
275 " WHERE (pathname=%Q"
276 " OR (pathname>'%q/' AND pathname<'%q0'))"
277 " AND NOT deleted",
278 zTreeName, zTreeName, zTreeName
279 );
280 blob_reset(&treeName);
281 }
282
283 db_prepare(&loop, "SELECT x FROM sfile");
284 while( db_step(&loop)==SQLITE_ROW ){
285 fossil_print("DELETED %s\n", db_column_text(&loop, 0));
286 }
287 db_finalize(&loop);
288 db_multi_exec(
289 "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
290 "DELETE FROM vfile WHERE rid=0 AND deleted;"
291 );
292 db_end_transaction(0);
293 }
294
295 /*
296 ** COMMAND: addremove
@@ -426,13 +331,13 @@
331 int allFlag = find_option("dotfiles",0,0)!=0;
332 int isTest = find_option("test",0,0)!=0;
333 int n;
334 Stmt q;
335 int vid;
 
336 int nAdd = 0;
337 int nDelete = 0;
338 Glob *pIgnore;
339
340 db_must_be_within_tree();
341 if( zIgnoreFlag==0 ){
342 zIgnoreFlag = db_get("ignore-glob", 0);
343 }
@@ -439,38 +344,30 @@
344 vid = db_lget_int("checkout",0);
345 if( vid==0 ){
346 fossil_panic("no checkout to add to");
347 }
348 db_begin_transaction();
349
350 /* step 1:
351 ** Populate the temp table "sfile" with the names of all unmanged
352 ** files currently in the check-out, except for files that match the
353 ** --ignore or ignore-glob patterns and dot-files. Then add all of
354 ** the files in the sfile temp table to the set of managed files.
355 */
356 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
357 n = strlen(g.zLocalRoot);
358 blob_init(&path, g.zLocalRoot, n-1);
359 /* now we read the complete file structure into a temp table */
360 pIgnore = glob_create(zIgnoreFlag);
361 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
362 glob_free(pIgnore);
363 nAdd = add_files_in_sfile(vid);
364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365 /* step 2: search for missing files */
366 db_prepare(&q,
367 "SELECT pathname, %Q || pathname, deleted FROM vfile"
368 " WHERE NOT deleted"
369 " ORDER BY 1",
370 g.zLocalRoot
371 );
372 while( db_step(&q)==SQLITE_ROW ){
373 const char * zFile;
@@ -480,17 +377,17 @@
377 zPath = db_column_text(&q, 1);
378 if( !file_isfile(zPath) ){
379 if( !isTest ){
380 db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
381 }
382 fossil_print("DELETED %s\n", zFile);
383 nDelete++;
384 }
385 }
386 db_finalize(&q);
387 /* show cmmand summary */
388 fossil_print("added %d files, deleted %d files\n", nAdd, nDelete);
389
390 db_end_transaction(isTest);
391 }
392
393
@@ -498,11 +395,11 @@
395 ** Rename a single file.
396 **
397 ** The original name of the file is zOrig. The new filename is zNew.
398 */
399 static void mv_one_file(int vid, const char *zOrig, const char *zNew){
400 fossil_print("RENAME %s %s\n", zOrig, zNew);
401 db_multi_exec(
402 "UPDATE vfile SET pathname='%s' WHERE pathname='%s' AND vid=%d",
403 zNew, zOrig, vid
404 );
405 }
@@ -572,13 +469,13 @@
469 zOrig = blob_str(&orig);
470 nOrig = blob_size(&orig);
471 db_prepare(&q,
472 "SELECT pathname FROM vfile"
473 " WHERE vid=%d"
474 " AND (pathname='%q' OR (pathname>'%q/' AND pathname<'%q0'))"
475 " ORDER BY 1",
476 vid, zOrig, zOrig, zOrig
477 );
478 while( db_step(&q)==SQLITE_ROW ){
479 const char *zPath = db_column_text(&q, 0);
480 int nPath = db_column_bytes(&q, 0);
481 const char *zTail;
482
+4 -4
--- src/allrepo.c
+++ src/allrepo.c
@@ -137,22 +137,22 @@
137137
" FROM global_config"
138138
" WHERE substr(name, 1, 5)=='repo:' ORDER BY 1"
139139
);
140140
while( db_step(&q)==SQLITE_ROW ){
141141
const char *zFilename = db_column_text(&q, 0);
142
- if( access(zFilename, 0) ){
142
+ if( file_access(zFilename, 0) ){
143143
nMissing++;
144144
continue;
145145
}
146146
if( !file_is_canonical(zFilename) ) nMissing++;
147147
if( zCmd[0]=='l' ){
148
- printf("%s\n", zFilename);
148
+ fossil_print("%s\n", zFilename);
149149
continue;
150150
}
151151
zQFilename = quoteFilename(zFilename);
152152
zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename);
153
- printf("%s\n", zSyscmd);
153
+ fossil_print("%s\n", zSyscmd);
154154
fflush(stdout);
155155
rc = fossil_system(zSyscmd);
156156
free(zSyscmd);
157157
free(zQFilename);
158158
if( stopOnError && rc ){
@@ -167,11 +167,11 @@
167167
if( nMissing ){
168168
db_begin_transaction();
169169
db_reset(&q);
170170
while( db_step(&q)==SQLITE_ROW ){
171171
const char *zFilename = db_column_text(&q, 0);
172
- if( access(zFilename, 0) ){
172
+ if( file_access(zFilename, 0) ){
173173
char *zRepo = mprintf("repo:%s", zFilename);
174174
db_unset(zRepo, 1);
175175
free(zRepo);
176176
}else if( !file_is_canonical(zFilename) ){
177177
Blob cname;
178178
--- src/allrepo.c
+++ src/allrepo.c
@@ -137,22 +137,22 @@
137 " FROM global_config"
138 " WHERE substr(name, 1, 5)=='repo:' ORDER BY 1"
139 );
140 while( db_step(&q)==SQLITE_ROW ){
141 const char *zFilename = db_column_text(&q, 0);
142 if( access(zFilename, 0) ){
143 nMissing++;
144 continue;
145 }
146 if( !file_is_canonical(zFilename) ) nMissing++;
147 if( zCmd[0]=='l' ){
148 printf("%s\n", zFilename);
149 continue;
150 }
151 zQFilename = quoteFilename(zFilename);
152 zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename);
153 printf("%s\n", zSyscmd);
154 fflush(stdout);
155 rc = fossil_system(zSyscmd);
156 free(zSyscmd);
157 free(zQFilename);
158 if( stopOnError && rc ){
@@ -167,11 +167,11 @@
167 if( nMissing ){
168 db_begin_transaction();
169 db_reset(&q);
170 while( db_step(&q)==SQLITE_ROW ){
171 const char *zFilename = db_column_text(&q, 0);
172 if( access(zFilename, 0) ){
173 char *zRepo = mprintf("repo:%s", zFilename);
174 db_unset(zRepo, 1);
175 free(zRepo);
176 }else if( !file_is_canonical(zFilename) ){
177 Blob cname;
178
--- src/allrepo.c
+++ src/allrepo.c
@@ -137,22 +137,22 @@
137 " FROM global_config"
138 " WHERE substr(name, 1, 5)=='repo:' ORDER BY 1"
139 );
140 while( db_step(&q)==SQLITE_ROW ){
141 const char *zFilename = db_column_text(&q, 0);
142 if( file_access(zFilename, 0) ){
143 nMissing++;
144 continue;
145 }
146 if( !file_is_canonical(zFilename) ) nMissing++;
147 if( zCmd[0]=='l' ){
148 fossil_print("%s\n", zFilename);
149 continue;
150 }
151 zQFilename = quoteFilename(zFilename);
152 zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename);
153 fossil_print("%s\n", zSyscmd);
154 fflush(stdout);
155 rc = fossil_system(zSyscmd);
156 free(zSyscmd);
157 free(zQFilename);
158 if( stopOnError && rc ){
@@ -167,11 +167,11 @@
167 if( nMissing ){
168 db_begin_transaction();
169 db_reset(&q);
170 while( db_step(&q)==SQLITE_ROW ){
171 const char *zFilename = db_column_text(&q, 0);
172 if( file_access(zFilename, 0) ){
173 char *zRepo = mprintf("repo:%s", zFilename);
174 db_unset(zRepo, 1);
175 free(zRepo);
176 }else if( !file_is_canonical(zFilename) ){
177 Blob cname;
178
+4 -4
--- src/allrepo.c
+++ src/allrepo.c
@@ -137,22 +137,22 @@
137137
" FROM global_config"
138138
" WHERE substr(name, 1, 5)=='repo:' ORDER BY 1"
139139
);
140140
while( db_step(&q)==SQLITE_ROW ){
141141
const char *zFilename = db_column_text(&q, 0);
142
- if( access(zFilename, 0) ){
142
+ if( file_access(zFilename, 0) ){
143143
nMissing++;
144144
continue;
145145
}
146146
if( !file_is_canonical(zFilename) ) nMissing++;
147147
if( zCmd[0]=='l' ){
148
- printf("%s\n", zFilename);
148
+ fossil_print("%s\n", zFilename);
149149
continue;
150150
}
151151
zQFilename = quoteFilename(zFilename);
152152
zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename);
153
- printf("%s\n", zSyscmd);
153
+ fossil_print("%s\n", zSyscmd);
154154
fflush(stdout);
155155
rc = fossil_system(zSyscmd);
156156
free(zSyscmd);
157157
free(zQFilename);
158158
if( stopOnError && rc ){
@@ -167,11 +167,11 @@
167167
if( nMissing ){
168168
db_begin_transaction();
169169
db_reset(&q);
170170
while( db_step(&q)==SQLITE_ROW ){
171171
const char *zFilename = db_column_text(&q, 0);
172
- if( access(zFilename, 0) ){
172
+ if( file_access(zFilename, 0) ){
173173
char *zRepo = mprintf("repo:%s", zFilename);
174174
db_unset(zRepo, 1);
175175
free(zRepo);
176176
}else if( !file_is_canonical(zFilename) ){
177177
Blob cname;
178178
--- src/allrepo.c
+++ src/allrepo.c
@@ -137,22 +137,22 @@
137 " FROM global_config"
138 " WHERE substr(name, 1, 5)=='repo:' ORDER BY 1"
139 );
140 while( db_step(&q)==SQLITE_ROW ){
141 const char *zFilename = db_column_text(&q, 0);
142 if( access(zFilename, 0) ){
143 nMissing++;
144 continue;
145 }
146 if( !file_is_canonical(zFilename) ) nMissing++;
147 if( zCmd[0]=='l' ){
148 printf("%s\n", zFilename);
149 continue;
150 }
151 zQFilename = quoteFilename(zFilename);
152 zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename);
153 printf("%s\n", zSyscmd);
154 fflush(stdout);
155 rc = fossil_system(zSyscmd);
156 free(zSyscmd);
157 free(zQFilename);
158 if( stopOnError && rc ){
@@ -167,11 +167,11 @@
167 if( nMissing ){
168 db_begin_transaction();
169 db_reset(&q);
170 while( db_step(&q)==SQLITE_ROW ){
171 const char *zFilename = db_column_text(&q, 0);
172 if( access(zFilename, 0) ){
173 char *zRepo = mprintf("repo:%s", zFilename);
174 db_unset(zRepo, 1);
175 free(zRepo);
176 }else if( !file_is_canonical(zFilename) ){
177 Blob cname;
178
--- src/allrepo.c
+++ src/allrepo.c
@@ -137,22 +137,22 @@
137 " FROM global_config"
138 " WHERE substr(name, 1, 5)=='repo:' ORDER BY 1"
139 );
140 while( db_step(&q)==SQLITE_ROW ){
141 const char *zFilename = db_column_text(&q, 0);
142 if( file_access(zFilename, 0) ){
143 nMissing++;
144 continue;
145 }
146 if( !file_is_canonical(zFilename) ) nMissing++;
147 if( zCmd[0]=='l' ){
148 fossil_print("%s\n", zFilename);
149 continue;
150 }
151 zQFilename = quoteFilename(zFilename);
152 zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename);
153 fossil_print("%s\n", zSyscmd);
154 fflush(stdout);
155 rc = fossil_system(zSyscmd);
156 free(zSyscmd);
157 free(zQFilename);
158 if( stopOnError && rc ){
@@ -167,11 +167,11 @@
167 if( nMissing ){
168 db_begin_transaction();
169 db_reset(&q);
170 while( db_step(&q)==SQLITE_ROW ){
171 const char *zFilename = db_column_text(&q, 0);
172 if( file_access(zFilename, 0) ){
173 char *zRepo = mprintf("repo:%s", zFilename);
174 db_unset(zRepo, 1);
175 free(zRepo);
176 }else if( !file_is_canonical(zFilename) ){
177 Blob cname;
178
+8 -8
--- src/bisect.c
+++ src/bisect.c
@@ -191,11 +191,11 @@
191191
}else if( memcmp(zCmd, "options", n)==0 ){
192192
if( g.argc==3 ){
193193
unsigned int i;
194194
for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
195195
char *z = mprintf("bisect-%s", aBisectOption[i].zName);
196
- printf(" %-15s %-6s ", aBisectOption[i].zName,
196
+ fossil_print(" %-15s %-6s ", aBisectOption[i].zName,
197197
db_lget(z, (char*)aBisectOption[i].zDefault));
198198
fossil_free(z);
199199
comment_print(aBisectOption[i].zDesc, 27, 79);
200200
}
201201
}else if( g.argc==4 || g.argc==5 ){
@@ -205,11 +205,11 @@
205205
if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
206206
char *z = mprintf("bisect-%s", aBisectOption[i].zName);
207207
if( g.argc==5 ){
208208
db_lset(z, g.argv[4]);
209209
}
210
- printf("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
210
+ fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
211211
fossil_free(z);
212212
break;
213213
}
214214
}
215215
if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
@@ -237,19 +237,19 @@
237237
for(p=path_last(), n=0; p; p=p->pFrom, n++){
238238
const char *z;
239239
db_bind_int(&s, ":rid", p->rid);
240240
if( db_step(&s)==SQLITE_ROW ){
241241
z = db_column_text(&s, 0);
242
- printf("%s", z);
243
- if( p->rid==bisect.good ) printf(" GOOD");
244
- if( p->rid==bisect.bad ) printf(" BAD");
245
- if( p->rid==vid ) printf(" CURRENT");
246
- if( nStep>1 && n==nStep/2 ) printf(" NEXT");
247
- printf("\n");
242
+ fossil_print("%s", z);
243
+ if( p->rid==bisect.good ) fossil_print(" GOOD");
244
+ if( p->rid==bisect.bad ) fossil_print(" BAD");
245
+ if( p->rid==vid ) fossil_print(" CURRENT");
246
+ if( nStep>1 && n==nStep/2 ) fossil_print(" NEXT");
247
+ fossil_print("\n");
248248
}
249249
db_reset(&s);
250250
}
251251
db_finalize(&s);
252252
}else{
253253
usage("bad|good|next|reset|vlist ...");
254254
}
255255
}
256256
--- src/bisect.c
+++ src/bisect.c
@@ -191,11 +191,11 @@
191 }else if( memcmp(zCmd, "options", n)==0 ){
192 if( g.argc==3 ){
193 unsigned int i;
194 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
195 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
196 printf(" %-15s %-6s ", aBisectOption[i].zName,
197 db_lget(z, (char*)aBisectOption[i].zDefault));
198 fossil_free(z);
199 comment_print(aBisectOption[i].zDesc, 27, 79);
200 }
201 }else if( g.argc==4 || g.argc==5 ){
@@ -205,11 +205,11 @@
205 if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
206 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
207 if( g.argc==5 ){
208 db_lset(z, g.argv[4]);
209 }
210 printf("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
211 fossil_free(z);
212 break;
213 }
214 }
215 if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
@@ -237,19 +237,19 @@
237 for(p=path_last(), n=0; p; p=p->pFrom, n++){
238 const char *z;
239 db_bind_int(&s, ":rid", p->rid);
240 if( db_step(&s)==SQLITE_ROW ){
241 z = db_column_text(&s, 0);
242 printf("%s", z);
243 if( p->rid==bisect.good ) printf(" GOOD");
244 if( p->rid==bisect.bad ) printf(" BAD");
245 if( p->rid==vid ) printf(" CURRENT");
246 if( nStep>1 && n==nStep/2 ) printf(" NEXT");
247 printf("\n");
248 }
249 db_reset(&s);
250 }
251 db_finalize(&s);
252 }else{
253 usage("bad|good|next|reset|vlist ...");
254 }
255 }
256
--- src/bisect.c
+++ src/bisect.c
@@ -191,11 +191,11 @@
191 }else if( memcmp(zCmd, "options", n)==0 ){
192 if( g.argc==3 ){
193 unsigned int i;
194 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
195 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
196 fossil_print(" %-15s %-6s ", aBisectOption[i].zName,
197 db_lget(z, (char*)aBisectOption[i].zDefault));
198 fossil_free(z);
199 comment_print(aBisectOption[i].zDesc, 27, 79);
200 }
201 }else if( g.argc==4 || g.argc==5 ){
@@ -205,11 +205,11 @@
205 if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
206 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
207 if( g.argc==5 ){
208 db_lset(z, g.argv[4]);
209 }
210 fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
211 fossil_free(z);
212 break;
213 }
214 }
215 if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
@@ -237,19 +237,19 @@
237 for(p=path_last(), n=0; p; p=p->pFrom, n++){
238 const char *z;
239 db_bind_int(&s, ":rid", p->rid);
240 if( db_step(&s)==SQLITE_ROW ){
241 z = db_column_text(&s, 0);
242 fossil_print("%s", z);
243 if( p->rid==bisect.good ) fossil_print(" GOOD");
244 if( p->rid==bisect.bad ) fossil_print(" BAD");
245 if( p->rid==vid ) fossil_print(" CURRENT");
246 if( nStep>1 && n==nStep/2 ) fossil_print(" NEXT");
247 fossil_print("\n");
248 }
249 db_reset(&s);
250 }
251 db_finalize(&s);
252 }else{
253 usage("bad|good|next|reset|vlist ...");
254 }
255 }
256
+8 -8
--- src/bisect.c
+++ src/bisect.c
@@ -191,11 +191,11 @@
191191
}else if( memcmp(zCmd, "options", n)==0 ){
192192
if( g.argc==3 ){
193193
unsigned int i;
194194
for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
195195
char *z = mprintf("bisect-%s", aBisectOption[i].zName);
196
- printf(" %-15s %-6s ", aBisectOption[i].zName,
196
+ fossil_print(" %-15s %-6s ", aBisectOption[i].zName,
197197
db_lget(z, (char*)aBisectOption[i].zDefault));
198198
fossil_free(z);
199199
comment_print(aBisectOption[i].zDesc, 27, 79);
200200
}
201201
}else if( g.argc==4 || g.argc==5 ){
@@ -205,11 +205,11 @@
205205
if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
206206
char *z = mprintf("bisect-%s", aBisectOption[i].zName);
207207
if( g.argc==5 ){
208208
db_lset(z, g.argv[4]);
209209
}
210
- printf("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
210
+ fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
211211
fossil_free(z);
212212
break;
213213
}
214214
}
215215
if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
@@ -237,19 +237,19 @@
237237
for(p=path_last(), n=0; p; p=p->pFrom, n++){
238238
const char *z;
239239
db_bind_int(&s, ":rid", p->rid);
240240
if( db_step(&s)==SQLITE_ROW ){
241241
z = db_column_text(&s, 0);
242
- printf("%s", z);
243
- if( p->rid==bisect.good ) printf(" GOOD");
244
- if( p->rid==bisect.bad ) printf(" BAD");
245
- if( p->rid==vid ) printf(" CURRENT");
246
- if( nStep>1 && n==nStep/2 ) printf(" NEXT");
247
- printf("\n");
242
+ fossil_print("%s", z);
243
+ if( p->rid==bisect.good ) fossil_print(" GOOD");
244
+ if( p->rid==bisect.bad ) fossil_print(" BAD");
245
+ if( p->rid==vid ) fossil_print(" CURRENT");
246
+ if( nStep>1 && n==nStep/2 ) fossil_print(" NEXT");
247
+ fossil_print("\n");
248248
}
249249
db_reset(&s);
250250
}
251251
db_finalize(&s);
252252
}else{
253253
usage("bad|good|next|reset|vlist ...");
254254
}
255255
}
256256
--- src/bisect.c
+++ src/bisect.c
@@ -191,11 +191,11 @@
191 }else if( memcmp(zCmd, "options", n)==0 ){
192 if( g.argc==3 ){
193 unsigned int i;
194 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
195 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
196 printf(" %-15s %-6s ", aBisectOption[i].zName,
197 db_lget(z, (char*)aBisectOption[i].zDefault));
198 fossil_free(z);
199 comment_print(aBisectOption[i].zDesc, 27, 79);
200 }
201 }else if( g.argc==4 || g.argc==5 ){
@@ -205,11 +205,11 @@
205 if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
206 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
207 if( g.argc==5 ){
208 db_lset(z, g.argv[4]);
209 }
210 printf("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
211 fossil_free(z);
212 break;
213 }
214 }
215 if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
@@ -237,19 +237,19 @@
237 for(p=path_last(), n=0; p; p=p->pFrom, n++){
238 const char *z;
239 db_bind_int(&s, ":rid", p->rid);
240 if( db_step(&s)==SQLITE_ROW ){
241 z = db_column_text(&s, 0);
242 printf("%s", z);
243 if( p->rid==bisect.good ) printf(" GOOD");
244 if( p->rid==bisect.bad ) printf(" BAD");
245 if( p->rid==vid ) printf(" CURRENT");
246 if( nStep>1 && n==nStep/2 ) printf(" NEXT");
247 printf("\n");
248 }
249 db_reset(&s);
250 }
251 db_finalize(&s);
252 }else{
253 usage("bad|good|next|reset|vlist ...");
254 }
255 }
256
--- src/bisect.c
+++ src/bisect.c
@@ -191,11 +191,11 @@
191 }else if( memcmp(zCmd, "options", n)==0 ){
192 if( g.argc==3 ){
193 unsigned int i;
194 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
195 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
196 fossil_print(" %-15s %-6s ", aBisectOption[i].zName,
197 db_lget(z, (char*)aBisectOption[i].zDefault));
198 fossil_free(z);
199 comment_print(aBisectOption[i].zDesc, 27, 79);
200 }
201 }else if( g.argc==4 || g.argc==5 ){
@@ -205,11 +205,11 @@
205 if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
206 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
207 if( g.argc==5 ){
208 db_lset(z, g.argv[4]);
209 }
210 fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
211 fossil_free(z);
212 break;
213 }
214 }
215 if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
@@ -237,19 +237,19 @@
237 for(p=path_last(), n=0; p; p=p->pFrom, n++){
238 const char *z;
239 db_bind_int(&s, ":rid", p->rid);
240 if( db_step(&s)==SQLITE_ROW ){
241 z = db_column_text(&s, 0);
242 fossil_print("%s", z);
243 if( p->rid==bisect.good ) fossil_print(" GOOD");
244 if( p->rid==bisect.bad ) fossil_print(" BAD");
245 if( p->rid==vid ) fossil_print(" CURRENT");
246 if( nStep>1 && n==nStep/2 ) fossil_print(" NEXT");
247 fossil_print("\n");
248 }
249 db_reset(&s);
250 }
251 db_finalize(&s);
252 }else{
253 usage("bad|good|next|reset|vlist ...");
254 }
255 }
256
+43 -5
--- src/blob.c
+++ src/blob.c
@@ -111,11 +111,11 @@
111111
assert( fossil_isspace((char)i) );
112112
}else{
113113
assert( !fossil_isspace((char)i) );
114114
}
115115
}
116
- printf("All 256 characters OK\n");
116
+ fossil_print("All 256 characters OK\n");
117117
}
118118
119119
/*
120120
** This routine is called if a blob operation fails because we
121121
** have run out of memory.
@@ -494,10 +494,48 @@
494494
blob_extract(pFrom, i-pFrom->iCursor, pTo);
495495
while( i<n && fossil_isspace(aData[i]) ){ i++; }
496496
pFrom->iCursor = i;
497497
return pTo->nUsed;
498498
}
499
+
500
+/*
501
+** Extract a single SQL token from pFrom and use it to initialize pTo.
502
+** Return the number of bytes in the token. If no token is found,
503
+** return 0.
504
+**
505
+** An SQL token consists of one or more non-space characters. If the
506
+** first character is ' then the token is terminated by a matching '
507
+** (ignoring double '') or by the end of the string
508
+**
509
+** The cursor of pFrom is left pointing at the first character past
510
+** the end of the token.
511
+**
512
+** pTo will be an ephermeral blob. If pFrom changes, it might alter
513
+** pTo as well.
514
+*/
515
+int blob_sqltoken(Blob *pFrom, Blob *pTo){
516
+ char *aData = pFrom->aData;
517
+ int n = pFrom->nUsed;
518
+ int i = pFrom->iCursor;
519
+ while( i<n && fossil_isspace(aData[i]) ){ i++; }
520
+ pFrom->iCursor = i;
521
+ if( aData[i]=='\'' ){
522
+ i++;
523
+ while( i<n ){
524
+ if( aData[i]=='\'' ){
525
+ if( aData[++i]!='\'' ) break;
526
+ }
527
+ i++;
528
+ }
529
+ }else{
530
+ while( i<n && !fossil_isspace(aData[i]) ){ i++; }
531
+ }
532
+ blob_extract(pFrom, i-pFrom->iCursor, pTo);
533
+ while( i<n && fossil_isspace(aData[i]) ){ i++; }
534
+ pFrom->iCursor = i;
535
+ return pTo->nUsed;
536
+}
499537
500538
/*
501539
** Extract everything from the current cursor to the end of the blob
502540
** into a new blob. The new blob is an ephemerial reference to the
503541
** original blob. The cursor of the original blob is unchanged.
@@ -652,11 +690,11 @@
652690
}
653691
if( size==0 ){
654692
return 0;
655693
}
656694
blob_resize(pBlob, size);
657
- in = fopen(zFilename, "rb");
695
+ in = fossil_fopen(zFilename, "rb");
658696
if( in==0 ){
659697
fossil_panic("cannot open %s for reading", zFilename);
660698
}
661699
got = fread(blob_buffer(pBlob), 1, size, in);
662700
fclose(in);
@@ -712,11 +750,11 @@
712750
}
713751
#endif
714752
zName[i] = '/';
715753
}
716754
}
717
- out = fopen(zName, "wb");
755
+ out = fossil_fopen(zName, "wb");
718756
if( out==0 ){
719757
fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
720758
return 0;
721759
}
722760
needToClose = 1;
@@ -723,11 +761,11 @@
723761
if( zName!=zBuf ) free(zName);
724762
}
725763
blob_is_init(pBlob);
726764
wrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
727765
if( needToClose ) fclose(out);
728
- if( wrote!=blob_size(pBlob) ){
766
+ if( wrote!=blob_size(pBlob) && out!=stdout ){
729767
fossil_fatal_recursive("short write: %d of %d bytes to %s", wrote,
730768
blob_size(pBlob), zFilename);
731769
}
732770
return wrote;
733771
}
@@ -887,11 +925,11 @@
887925
}
888926
blob_reset(&b1);
889927
blob_reset(&b2);
890928
blob_reset(&b3);
891929
}
892
- printf("ok\n");
930
+ fossil_print("ok\n");
893931
}
894932
895933
#if defined(_WIN32)
896934
/*
897935
** Convert every \n character in the given blob into \r\n.
898936
--- src/blob.c
+++ src/blob.c
@@ -111,11 +111,11 @@
111 assert( fossil_isspace((char)i) );
112 }else{
113 assert( !fossil_isspace((char)i) );
114 }
115 }
116 printf("All 256 characters OK\n");
117 }
118
119 /*
120 ** This routine is called if a blob operation fails because we
121 ** have run out of memory.
@@ -494,10 +494,48 @@
494 blob_extract(pFrom, i-pFrom->iCursor, pTo);
495 while( i<n && fossil_isspace(aData[i]) ){ i++; }
496 pFrom->iCursor = i;
497 return pTo->nUsed;
498 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
500 /*
501 ** Extract everything from the current cursor to the end of the blob
502 ** into a new blob. The new blob is an ephemerial reference to the
503 ** original blob. The cursor of the original blob is unchanged.
@@ -652,11 +690,11 @@
652 }
653 if( size==0 ){
654 return 0;
655 }
656 blob_resize(pBlob, size);
657 in = fopen(zFilename, "rb");
658 if( in==0 ){
659 fossil_panic("cannot open %s for reading", zFilename);
660 }
661 got = fread(blob_buffer(pBlob), 1, size, in);
662 fclose(in);
@@ -712,11 +750,11 @@
712 }
713 #endif
714 zName[i] = '/';
715 }
716 }
717 out = fopen(zName, "wb");
718 if( out==0 ){
719 fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
720 return 0;
721 }
722 needToClose = 1;
@@ -723,11 +761,11 @@
723 if( zName!=zBuf ) free(zName);
724 }
725 blob_is_init(pBlob);
726 wrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
727 if( needToClose ) fclose(out);
728 if( wrote!=blob_size(pBlob) ){
729 fossil_fatal_recursive("short write: %d of %d bytes to %s", wrote,
730 blob_size(pBlob), zFilename);
731 }
732 return wrote;
733 }
@@ -887,11 +925,11 @@
887 }
888 blob_reset(&b1);
889 blob_reset(&b2);
890 blob_reset(&b3);
891 }
892 printf("ok\n");
893 }
894
895 #if defined(_WIN32)
896 /*
897 ** Convert every \n character in the given blob into \r\n.
898
--- src/blob.c
+++ src/blob.c
@@ -111,11 +111,11 @@
111 assert( fossil_isspace((char)i) );
112 }else{
113 assert( !fossil_isspace((char)i) );
114 }
115 }
116 fossil_print("All 256 characters OK\n");
117 }
118
119 /*
120 ** This routine is called if a blob operation fails because we
121 ** have run out of memory.
@@ -494,10 +494,48 @@
494 blob_extract(pFrom, i-pFrom->iCursor, pTo);
495 while( i<n && fossil_isspace(aData[i]) ){ i++; }
496 pFrom->iCursor = i;
497 return pTo->nUsed;
498 }
499
500 /*
501 ** Extract a single SQL token from pFrom and use it to initialize pTo.
502 ** Return the number of bytes in the token. If no token is found,
503 ** return 0.
504 **
505 ** An SQL token consists of one or more non-space characters. If the
506 ** first character is ' then the token is terminated by a matching '
507 ** (ignoring double '') or by the end of the string
508 **
509 ** The cursor of pFrom is left pointing at the first character past
510 ** the end of the token.
511 **
512 ** pTo will be an ephermeral blob. If pFrom changes, it might alter
513 ** pTo as well.
514 */
515 int blob_sqltoken(Blob *pFrom, Blob *pTo){
516 char *aData = pFrom->aData;
517 int n = pFrom->nUsed;
518 int i = pFrom->iCursor;
519 while( i<n && fossil_isspace(aData[i]) ){ i++; }
520 pFrom->iCursor = i;
521 if( aData[i]=='\'' ){
522 i++;
523 while( i<n ){
524 if( aData[i]=='\'' ){
525 if( aData[++i]!='\'' ) break;
526 }
527 i++;
528 }
529 }else{
530 while( i<n && !fossil_isspace(aData[i]) ){ i++; }
531 }
532 blob_extract(pFrom, i-pFrom->iCursor, pTo);
533 while( i<n && fossil_isspace(aData[i]) ){ i++; }
534 pFrom->iCursor = i;
535 return pTo->nUsed;
536 }
537
538 /*
539 ** Extract everything from the current cursor to the end of the blob
540 ** into a new blob. The new blob is an ephemerial reference to the
541 ** original blob. The cursor of the original blob is unchanged.
@@ -652,11 +690,11 @@
690 }
691 if( size==0 ){
692 return 0;
693 }
694 blob_resize(pBlob, size);
695 in = fossil_fopen(zFilename, "rb");
696 if( in==0 ){
697 fossil_panic("cannot open %s for reading", zFilename);
698 }
699 got = fread(blob_buffer(pBlob), 1, size, in);
700 fclose(in);
@@ -712,11 +750,11 @@
750 }
751 #endif
752 zName[i] = '/';
753 }
754 }
755 out = fossil_fopen(zName, "wb");
756 if( out==0 ){
757 fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
758 return 0;
759 }
760 needToClose = 1;
@@ -723,11 +761,11 @@
761 if( zName!=zBuf ) free(zName);
762 }
763 blob_is_init(pBlob);
764 wrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
765 if( needToClose ) fclose(out);
766 if( wrote!=blob_size(pBlob) && out!=stdout ){
767 fossil_fatal_recursive("short write: %d of %d bytes to %s", wrote,
768 blob_size(pBlob), zFilename);
769 }
770 return wrote;
771 }
@@ -887,11 +925,11 @@
925 }
926 blob_reset(&b1);
927 blob_reset(&b2);
928 blob_reset(&b3);
929 }
930 fossil_print("ok\n");
931 }
932
933 #if defined(_WIN32)
934 /*
935 ** Convert every \n character in the given blob into \r\n.
936
+25 -11
--- src/branch.c
+++ src/branch.c
@@ -157,13 +157,13 @@
157157
fossil_panic("unable to install new manifest");
158158
}
159159
assert( blob_is_reset(&branch) );
160160
content_deltify(rootid, brid, 0);
161161
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
162
- printf("New branch: %s\n", zUuid);
162
+ fossil_print("New branch: %s\n", zUuid);
163163
if( g.argc==3 ){
164
- printf(
164
+ fossil_print(
165165
"\n"
166166
"Note: the local check-out has not been updated to the new\n"
167167
" branch. To begin working on the new branch, do this:\n"
168168
"\n"
169169
" %s update %s\n",
@@ -234,11 +234,11 @@
234234
TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
235235
);
236236
while( db_step(&q)==SQLITE_ROW ){
237237
const char *zBr = db_column_text(&q, 0);
238238
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
239
- printf("%s%s\n", (isCur ? "* " : " "), zBr);
239
+ fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
240240
}
241241
db_finalize(&q);
242242
}else{
243243
fossil_panic("branch subcommand should be one of: "
244244
"new list ls");
@@ -281,18 +281,32 @@
281281
@ reopened)</li>
282282
@ </ol>
283283
style_sidebox_end();
284284
285285
cnt = 0;
286
- db_prepare(&q,
287
- "SELECT DISTINCT value FROM tagxref"
288
- " WHERE tagid=%d AND value NOT NULL"
289
- " AND rid IN leaf"
290
- " AND %s %z"
291
- " ORDER BY value /*sort*/",
292
- TAG_BRANCH, showClosed ? "" : "NOT", leaf_is_closed_sql("tagxref.rid")
293
- );
286
+ if( showClosed ){
287
+ db_prepare(&q,
288
+ "SELECT value FROM tagxref"
289
+ " WHERE tagid=%d AND value NOT NULL "
290
+ "EXCEPT "
291
+ "SELECT value FROM tagxref"
292
+ " WHERE tagid=%d"
293
+ " AND rid IN leaf"
294
+ " AND NOT %z"
295
+ " ORDER BY value /*sort*/",
296
+ TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
297
+ );
298
+ }else{
299
+ db_prepare(&q,
300
+ "SELECT DISTINCT value FROM tagxref"
301
+ " WHERE tagid=%d AND value NOT NULL"
302
+ " AND rid IN leaf"
303
+ " AND NOT %z"
304
+ " ORDER BY value /*sort*/",
305
+ TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
306
+ );
307
+ }
294308
while( db_step(&q)==SQLITE_ROW ){
295309
const char *zBr = db_column_text(&q, 0);
296310
if( cnt==0 ){
297311
if( showClosed ){
298312
@ <h2>Closed Branches:</h2>
299313
--- src/branch.c
+++ src/branch.c
@@ -157,13 +157,13 @@
157 fossil_panic("unable to install new manifest");
158 }
159 assert( blob_is_reset(&branch) );
160 content_deltify(rootid, brid, 0);
161 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
162 printf("New branch: %s\n", zUuid);
163 if( g.argc==3 ){
164 printf(
165 "\n"
166 "Note: the local check-out has not been updated to the new\n"
167 " branch. To begin working on the new branch, do this:\n"
168 "\n"
169 " %s update %s\n",
@@ -234,11 +234,11 @@
234 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
235 );
236 while( db_step(&q)==SQLITE_ROW ){
237 const char *zBr = db_column_text(&q, 0);
238 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
239 printf("%s%s\n", (isCur ? "* " : " "), zBr);
240 }
241 db_finalize(&q);
242 }else{
243 fossil_panic("branch subcommand should be one of: "
244 "new list ls");
@@ -281,18 +281,32 @@
281 @ reopened)</li>
282 @ </ol>
283 style_sidebox_end();
284
285 cnt = 0;
286 db_prepare(&q,
287 "SELECT DISTINCT value FROM tagxref"
288 " WHERE tagid=%d AND value NOT NULL"
289 " AND rid IN leaf"
290 " AND %s %z"
291 " ORDER BY value /*sort*/",
292 TAG_BRANCH, showClosed ? "" : "NOT", leaf_is_closed_sql("tagxref.rid")
293 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294 while( db_step(&q)==SQLITE_ROW ){
295 const char *zBr = db_column_text(&q, 0);
296 if( cnt==0 ){
297 if( showClosed ){
298 @ <h2>Closed Branches:</h2>
299
--- src/branch.c
+++ src/branch.c
@@ -157,13 +157,13 @@
157 fossil_panic("unable to install new manifest");
158 }
159 assert( blob_is_reset(&branch) );
160 content_deltify(rootid, brid, 0);
161 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
162 fossil_print("New branch: %s\n", zUuid);
163 if( g.argc==3 ){
164 fossil_print(
165 "\n"
166 "Note: the local check-out has not been updated to the new\n"
167 " branch. To begin working on the new branch, do this:\n"
168 "\n"
169 " %s update %s\n",
@@ -234,11 +234,11 @@
234 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
235 );
236 while( db_step(&q)==SQLITE_ROW ){
237 const char *zBr = db_column_text(&q, 0);
238 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
239 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
240 }
241 db_finalize(&q);
242 }else{
243 fossil_panic("branch subcommand should be one of: "
244 "new list ls");
@@ -281,18 +281,32 @@
281 @ reopened)</li>
282 @ </ol>
283 style_sidebox_end();
284
285 cnt = 0;
286 if( showClosed ){
287 db_prepare(&q,
288 "SELECT value FROM tagxref"
289 " WHERE tagid=%d AND value NOT NULL "
290 "EXCEPT "
291 "SELECT value FROM tagxref"
292 " WHERE tagid=%d"
293 " AND rid IN leaf"
294 " AND NOT %z"
295 " ORDER BY value /*sort*/",
296 TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
297 );
298 }else{
299 db_prepare(&q,
300 "SELECT DISTINCT value FROM tagxref"
301 " WHERE tagid=%d AND value NOT NULL"
302 " AND rid IN leaf"
303 " AND NOT %z"
304 " ORDER BY value /*sort*/",
305 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
306 );
307 }
308 while( db_step(&q)==SQLITE_ROW ){
309 const char *zBr = db_column_text(&q, 0);
310 if( cnt==0 ){
311 if( showClosed ){
312 @ <h2>Closed Branches:</h2>
313
+25 -11
--- src/branch.c
+++ src/branch.c
@@ -157,13 +157,13 @@
157157
fossil_panic("unable to install new manifest");
158158
}
159159
assert( blob_is_reset(&branch) );
160160
content_deltify(rootid, brid, 0);
161161
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
162
- printf("New branch: %s\n", zUuid);
162
+ fossil_print("New branch: %s\n", zUuid);
163163
if( g.argc==3 ){
164
- printf(
164
+ fossil_print(
165165
"\n"
166166
"Note: the local check-out has not been updated to the new\n"
167167
" branch. To begin working on the new branch, do this:\n"
168168
"\n"
169169
" %s update %s\n",
@@ -234,11 +234,11 @@
234234
TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
235235
);
236236
while( db_step(&q)==SQLITE_ROW ){
237237
const char *zBr = db_column_text(&q, 0);
238238
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
239
- printf("%s%s\n", (isCur ? "* " : " "), zBr);
239
+ fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
240240
}
241241
db_finalize(&q);
242242
}else{
243243
fossil_panic("branch subcommand should be one of: "
244244
"new list ls");
@@ -281,18 +281,32 @@
281281
@ reopened)</li>
282282
@ </ol>
283283
style_sidebox_end();
284284
285285
cnt = 0;
286
- db_prepare(&q,
287
- "SELECT DISTINCT value FROM tagxref"
288
- " WHERE tagid=%d AND value NOT NULL"
289
- " AND rid IN leaf"
290
- " AND %s %z"
291
- " ORDER BY value /*sort*/",
292
- TAG_BRANCH, showClosed ? "" : "NOT", leaf_is_closed_sql("tagxref.rid")
293
- );
286
+ if( showClosed ){
287
+ db_prepare(&q,
288
+ "SELECT value FROM tagxref"
289
+ " WHERE tagid=%d AND value NOT NULL "
290
+ "EXCEPT "
291
+ "SELECT value FROM tagxref"
292
+ " WHERE tagid=%d"
293
+ " AND rid IN leaf"
294
+ " AND NOT %z"
295
+ " ORDER BY value /*sort*/",
296
+ TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
297
+ );
298
+ }else{
299
+ db_prepare(&q,
300
+ "SELECT DISTINCT value FROM tagxref"
301
+ " WHERE tagid=%d AND value NOT NULL"
302
+ " AND rid IN leaf"
303
+ " AND NOT %z"
304
+ " ORDER BY value /*sort*/",
305
+ TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
306
+ );
307
+ }
294308
while( db_step(&q)==SQLITE_ROW ){
295309
const char *zBr = db_column_text(&q, 0);
296310
if( cnt==0 ){
297311
if( showClosed ){
298312
@ <h2>Closed Branches:</h2>
299313
--- src/branch.c
+++ src/branch.c
@@ -157,13 +157,13 @@
157 fossil_panic("unable to install new manifest");
158 }
159 assert( blob_is_reset(&branch) );
160 content_deltify(rootid, brid, 0);
161 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
162 printf("New branch: %s\n", zUuid);
163 if( g.argc==3 ){
164 printf(
165 "\n"
166 "Note: the local check-out has not been updated to the new\n"
167 " branch. To begin working on the new branch, do this:\n"
168 "\n"
169 " %s update %s\n",
@@ -234,11 +234,11 @@
234 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
235 );
236 while( db_step(&q)==SQLITE_ROW ){
237 const char *zBr = db_column_text(&q, 0);
238 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
239 printf("%s%s\n", (isCur ? "* " : " "), zBr);
240 }
241 db_finalize(&q);
242 }else{
243 fossil_panic("branch subcommand should be one of: "
244 "new list ls");
@@ -281,18 +281,32 @@
281 @ reopened)</li>
282 @ </ol>
283 style_sidebox_end();
284
285 cnt = 0;
286 db_prepare(&q,
287 "SELECT DISTINCT value FROM tagxref"
288 " WHERE tagid=%d AND value NOT NULL"
289 " AND rid IN leaf"
290 " AND %s %z"
291 " ORDER BY value /*sort*/",
292 TAG_BRANCH, showClosed ? "" : "NOT", leaf_is_closed_sql("tagxref.rid")
293 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294 while( db_step(&q)==SQLITE_ROW ){
295 const char *zBr = db_column_text(&q, 0);
296 if( cnt==0 ){
297 if( showClosed ){
298 @ <h2>Closed Branches:</h2>
299
--- src/branch.c
+++ src/branch.c
@@ -157,13 +157,13 @@
157 fossil_panic("unable to install new manifest");
158 }
159 assert( blob_is_reset(&branch) );
160 content_deltify(rootid, brid, 0);
161 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
162 fossil_print("New branch: %s\n", zUuid);
163 if( g.argc==3 ){
164 fossil_print(
165 "\n"
166 "Note: the local check-out has not been updated to the new\n"
167 " branch. To begin working on the new branch, do this:\n"
168 "\n"
169 " %s update %s\n",
@@ -234,11 +234,11 @@
234 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
235 );
236 while( db_step(&q)==SQLITE_ROW ){
237 const char *zBr = db_column_text(&q, 0);
238 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
239 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
240 }
241 db_finalize(&q);
242 }else{
243 fossil_panic("branch subcommand should be one of: "
244 "new list ls");
@@ -281,18 +281,32 @@
281 @ reopened)</li>
282 @ </ol>
283 style_sidebox_end();
284
285 cnt = 0;
286 if( showClosed ){
287 db_prepare(&q,
288 "SELECT value FROM tagxref"
289 " WHERE tagid=%d AND value NOT NULL "
290 "EXCEPT "
291 "SELECT value FROM tagxref"
292 " WHERE tagid=%d"
293 " AND rid IN leaf"
294 " AND NOT %z"
295 " ORDER BY value /*sort*/",
296 TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
297 );
298 }else{
299 db_prepare(&q,
300 "SELECT DISTINCT value FROM tagxref"
301 " WHERE tagid=%d AND value NOT NULL"
302 " AND rid IN leaf"
303 " AND NOT %z"
304 " ORDER BY value /*sort*/",
305 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
306 );
307 }
308 while( db_step(&q)==SQLITE_ROW ){
309 const char *zBr = db_column_text(&q, 0);
310 if( cnt==0 ){
311 if( showClosed ){
312 @ <h2>Closed Branches:</h2>
313
+1 -1
--- src/captcha.c
+++ src/captcha.c
@@ -392,11 +392,11 @@
392392
for(i=2; i<g.argc; i++){
393393
char zHex[30];
394394
v = (unsigned int)atoi(g.argv[i]);
395395
sqlite3_snprintf(sizeof(zHex), zHex, "%x", v);
396396
z = captcha_render(zHex);
397
- printf("%s:\n%s", zHex, z);
397
+ fossil_print("%s:\n%s", zHex, z);
398398
free(z);
399399
}
400400
}
401401
402402
/*
403403
--- src/captcha.c
+++ src/captcha.c
@@ -392,11 +392,11 @@
392 for(i=2; i<g.argc; i++){
393 char zHex[30];
394 v = (unsigned int)atoi(g.argv[i]);
395 sqlite3_snprintf(sizeof(zHex), zHex, "%x", v);
396 z = captcha_render(zHex);
397 printf("%s:\n%s", zHex, z);
398 free(z);
399 }
400 }
401
402 /*
403
--- src/captcha.c
+++ src/captcha.c
@@ -392,11 +392,11 @@
392 for(i=2; i<g.argc; i++){
393 char zHex[30];
394 v = (unsigned int)atoi(g.argv[i]);
395 sqlite3_snprintf(sizeof(zHex), zHex, "%x", v);
396 z = captcha_render(zHex);
397 fossil_print("%s:\n%s", zHex, z);
398 free(z);
399 }
400 }
401
402 /*
403
+29 -8
--- src/cgi.c
+++ src/cgi.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2006 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -55,12 +55,12 @@
5555
** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y")
5656
** does the same except "y" is returned in place of NULL if there is not match.
5757
*/
5858
#define P(x) cgi_parameter((x),0)
5959
#define PD(x,y) cgi_parameter((x),(y))
60
-#define QP(x) quotable_string(cgi_parameter((x),0))
61
-#define QPD(x,y) quotable_string(cgi_parameter((x),(y)))
60
+#define PT(x) cgi_parameter_trimmed((x),0)
61
+#define PDT(x,y) cgi_parameter_trimmed((x),(y))
6262
6363
6464
/*
6565
** Destinations for output text.
6666
*/
@@ -191,20 +191,24 @@
191191
const char *zName, /* Name of the cookie */
192192
const char *zValue, /* Value of the cookie. Automatically escaped */
193193
const char *zPath, /* Path cookie applies to. NULL means "/" */
194194
int lifetime /* Expiration of the cookie in seconds from now */
195195
){
196
+ char *zSecure = "";
196197
if( zPath==0 ) zPath = g.zTop;
198
+ if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){
199
+ zSecure = " secure;";
200
+ }
197201
if( lifetime>0 ){
198202
lifetime += (int)time(0);
199203
blob_appendf(&extraHeader,
200
- "Set-Cookie: %s=%t; Path=%s; expires=%z; Version=1\r\n",
201
- zName, zValue, zPath, cgi_rfc822_datestamp(lifetime));
204
+ "Set-Cookie: %s=%t; Path=%s; expires=%z; HttpOnly;%s Version=1\r\n",
205
+ zName, zValue, zPath, cgi_rfc822_datestamp(lifetime), zSecure);
202206
}else{
203207
blob_appendf(&extraHeader,
204
- "Set-Cookie: %s=%t; Path=%s; Version=1\r\n",
205
- zName, zValue, zPath);
208
+ "Set-Cookie: %s=%t; Path=%s; HttpOnly;%s Version=1\r\n",
209
+ zName, zValue, zPath, zSecure);
206210
}
207211
}
208212
209213
#if 0
210214
/*
@@ -787,10 +791,27 @@
787791
}
788792
}
789793
CGIDEBUG(("no-match [%s]\n", zName));
790794
return zDefault;
791795
}
796
+
797
+/*
798
+** Return the value of a CGI parameter with leading and trailing
799
+** spaces removed.
800
+*/
801
+char *cgi_parameter_trimmed(const char *zName, const char *zDefault){
802
+ const char *zIn;
803
+ char *zOut;
804
+ int i;
805
+ zIn = cgi_parameter(zName, 0);
806
+ if( zIn==0 ) zIn = zDefault;
807
+ while( fossil_isspace(zIn[0]) ) zIn++;
808
+ zOut = fossil_strdup(zIn);
809
+ for(i=0; zOut[i]; i++){}
810
+ while( i>0 && fossil_isspace(zOut[i-1]) ) zOut[--i] = 0;
811
+ return zOut;
812
+}
792813
793814
/*
794815
** Return the name of the i-th CGI parameter. Return NULL if there
795816
** are fewer than i registered CGI parmaeters.
796817
*/
@@ -1099,11 +1120,11 @@
10991120
}
11001121
}
11011122
if( iPort>mxPort ) return 1;
11021123
listen(listener,10);
11031124
if( iPort>mnPort ){
1104
- printf("Listening for HTTP requests on TCP port %d\n", iPort);
1125
+ fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
11051126
fflush(stdout);
11061127
}
11071128
if( zBrowser ){
11081129
zBrowser = mprintf(zBrowser, iPort);
11091130
system(zBrowser);
11101131
--- src/cgi.c
+++ src/cgi.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -55,12 +55,12 @@
55 ** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y")
56 ** does the same except "y" is returned in place of NULL if there is not match.
57 */
58 #define P(x) cgi_parameter((x),0)
59 #define PD(x,y) cgi_parameter((x),(y))
60 #define QP(x) quotable_string(cgi_parameter((x),0))
61 #define QPD(x,y) quotable_string(cgi_parameter((x),(y)))
62
63
64 /*
65 ** Destinations for output text.
66 */
@@ -191,20 +191,24 @@
191 const char *zName, /* Name of the cookie */
192 const char *zValue, /* Value of the cookie. Automatically escaped */
193 const char *zPath, /* Path cookie applies to. NULL means "/" */
194 int lifetime /* Expiration of the cookie in seconds from now */
195 ){
 
196 if( zPath==0 ) zPath = g.zTop;
 
 
 
197 if( lifetime>0 ){
198 lifetime += (int)time(0);
199 blob_appendf(&extraHeader,
200 "Set-Cookie: %s=%t; Path=%s; expires=%z; Version=1\r\n",
201 zName, zValue, zPath, cgi_rfc822_datestamp(lifetime));
202 }else{
203 blob_appendf(&extraHeader,
204 "Set-Cookie: %s=%t; Path=%s; Version=1\r\n",
205 zName, zValue, zPath);
206 }
207 }
208
209 #if 0
210 /*
@@ -787,10 +791,27 @@
787 }
788 }
789 CGIDEBUG(("no-match [%s]\n", zName));
790 return zDefault;
791 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
792
793 /*
794 ** Return the name of the i-th CGI parameter. Return NULL if there
795 ** are fewer than i registered CGI parmaeters.
796 */
@@ -1099,11 +1120,11 @@
1099 }
1100 }
1101 if( iPort>mxPort ) return 1;
1102 listen(listener,10);
1103 if( iPort>mnPort ){
1104 printf("Listening for HTTP requests on TCP port %d\n", iPort);
1105 fflush(stdout);
1106 }
1107 if( zBrowser ){
1108 zBrowser = mprintf(zBrowser, iPort);
1109 system(zBrowser);
1110
--- src/cgi.c
+++ src/cgi.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2006 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -55,12 +55,12 @@
55 ** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y")
56 ** does the same except "y" is returned in place of NULL if there is not match.
57 */
58 #define P(x) cgi_parameter((x),0)
59 #define PD(x,y) cgi_parameter((x),(y))
60 #define PT(x) cgi_parameter_trimmed((x),0)
61 #define PDT(x,y) cgi_parameter_trimmed((x),(y))
62
63
64 /*
65 ** Destinations for output text.
66 */
@@ -191,20 +191,24 @@
191 const char *zName, /* Name of the cookie */
192 const char *zValue, /* Value of the cookie. Automatically escaped */
193 const char *zPath, /* Path cookie applies to. NULL means "/" */
194 int lifetime /* Expiration of the cookie in seconds from now */
195 ){
196 char *zSecure = "";
197 if( zPath==0 ) zPath = g.zTop;
198 if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){
199 zSecure = " secure;";
200 }
201 if( lifetime>0 ){
202 lifetime += (int)time(0);
203 blob_appendf(&extraHeader,
204 "Set-Cookie: %s=%t; Path=%s; expires=%z; HttpOnly;%s Version=1\r\n",
205 zName, zValue, zPath, cgi_rfc822_datestamp(lifetime), zSecure);
206 }else{
207 blob_appendf(&extraHeader,
208 "Set-Cookie: %s=%t; Path=%s; HttpOnly;%s Version=1\r\n",
209 zName, zValue, zPath, zSecure);
210 }
211 }
212
213 #if 0
214 /*
@@ -787,10 +791,27 @@
791 }
792 }
793 CGIDEBUG(("no-match [%s]\n", zName));
794 return zDefault;
795 }
796
797 /*
798 ** Return the value of a CGI parameter with leading and trailing
799 ** spaces removed.
800 */
801 char *cgi_parameter_trimmed(const char *zName, const char *zDefault){
802 const char *zIn;
803 char *zOut;
804 int i;
805 zIn = cgi_parameter(zName, 0);
806 if( zIn==0 ) zIn = zDefault;
807 while( fossil_isspace(zIn[0]) ) zIn++;
808 zOut = fossil_strdup(zIn);
809 for(i=0; zOut[i]; i++){}
810 while( i>0 && fossil_isspace(zOut[i-1]) ) zOut[--i] = 0;
811 return zOut;
812 }
813
814 /*
815 ** Return the name of the i-th CGI parameter. Return NULL if there
816 ** are fewer than i registered CGI parmaeters.
817 */
@@ -1099,11 +1120,11 @@
1120 }
1121 }
1122 if( iPort>mxPort ) return 1;
1123 listen(listener,10);
1124 if( iPort>mnPort ){
1125 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
1126 fflush(stdout);
1127 }
1128 if( zBrowser ){
1129 zBrowser = mprintf(zBrowser, iPort);
1130 system(zBrowser);
1131
+41 -102
--- src/checkin.c
+++ src/checkin.c
@@ -54,11 +54,11 @@
5454
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
5555
blob_append(report, zPrefix, nPrefix);
5656
if( isDeleted ){
5757
blob_appendf(report, "DELETED %s\n", zPathname);
5858
}else if( !file_isfile(zFullName) ){
59
- if( access(zFullName, 0)==0 ){
59
+ if( file_access(zFullName, 0)==0 ){
6060
blob_appendf(report, "NOT_A_FILE %s\n", zPathname);
6161
if( missingIsFatal ){
6262
fossil_warning("not a file: %s", zPathname);
6363
nErr++;
6464
}
@@ -142,13 +142,13 @@
142142
*/
143143
void status_cmd(void){
144144
int vid;
145145
db_must_be_within_tree();
146146
/* 012345678901234 */
147
- printf("repository: %s\n", db_lget("repository",""));
148
- printf("local-root: %s\n", g.zLocalRoot);
149
- printf("server-code: %s\n", db_get("server-code", ""));
147
+ fossil_print("repository: %s\n", db_lget("repository",""));
148
+ fossil_print("local-root: %s\n", g.zLocalRoot);
149
+ fossil_print("server-code: %s\n", db_get("server-code", ""));
150150
vid = db_lget_int("checkout", 0);
151151
if( vid ){
152152
show_common_info(vid, "checkout:", 1, 1);
153153
}
154154
changes_cmd();
@@ -185,87 +185,33 @@
185185
int isNew = db_column_int(&q,2)==0;
186186
int chnged = db_column_int(&q,3);
187187
int renamed = db_column_int(&q,4);
188188
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
189189
if( isBrief ){
190
- printf("%s\n", zPathname);
190
+ fossil_print("%s\n", zPathname);
191191
}else if( isNew ){
192
- printf("ADDED %s\n", zPathname);
192
+ fossil_print("ADDED %s\n", zPathname);
193193
}else if( isDeleted ){
194
- printf("DELETED %s\n", zPathname);
194
+ fossil_print("DELETED %s\n", zPathname);
195195
}else if( !file_isfile(zFullName) ){
196
- if( access(zFullName, 0)==0 ){
197
- printf("NOT_A_FILE %s\n", zPathname);
196
+ if( file_access(zFullName, 0)==0 ){
197
+ fossil_print("NOT_A_FILE %s\n", zPathname);
198198
}else{
199
- printf("MISSING %s\n", zPathname);
199
+ fossil_print("MISSING %s\n", zPathname);
200200
}
201201
}else if( chnged ){
202
- printf("EDITED %s\n", zPathname);
202
+ fossil_print("EDITED %s\n", zPathname);
203203
}else if( renamed ){
204
- printf("RENAMED %s\n", zPathname);
204
+ fossil_print("RENAMED %s\n", zPathname);
205205
}else{
206
- printf("UNCHANGED %s\n", zPathname);
206
+ fossil_print("UNCHANGED %s\n", zPathname);
207207
}
208208
free(zFullName);
209209
}
210210
db_finalize(&q);
211211
}
212212
213
-/*
214
-** Construct and return a string which is an SQL expression that will
215
-** be TRUE if value zVal matches any of the GLOB expressions in the list
216
-** zGlobList. For example:
217
-**
218
-** zVal: "x"
219
-** zGlobList: "*.o,*.obj"
220
-**
221
-** Result: "(x GLOB '*.o' OR x GLOB '*.obj')"
222
-**
223
-** Each element of the GLOB list may optionally be enclosed in either '...'
224
-** or "...". This allows commas in the expression. Whitespace at the
225
-** beginning and end of each GLOB pattern is ignored, except when enclosed
226
-** within '...' or "...".
227
-**
228
-** This routine makes no effort to free the memory space it uses.
229
-*/
230
-char *glob_expr(const char *zVal, const char *zGlobList){
231
- Blob expr;
232
- char *zSep = "(";
233
- int nTerm = 0;
234
- int i;
235
- int cTerm;
236
-
237
- if( zGlobList==0 || zGlobList[0]==0 ) return "0";
238
- blob_zero(&expr);
239
- while( zGlobList[0] ){
240
- while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ) zGlobList++;
241
- if( zGlobList[0]==0 ) break;
242
- if( zGlobList[0]=='\'' || zGlobList[0]=='"' ){
243
- cTerm = zGlobList[0];
244
- zGlobList++;
245
- }else{
246
- cTerm = ',';
247
- }
248
- for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){}
249
- if( cTerm==',' ){
250
- while( i>0 && fossil_isspace(zGlobList[i-1]) ){ i--; }
251
- }
252
- blob_appendf(&expr, "%s%s GLOB '%.*q'", zSep, zVal, i, zGlobList);
253
- zSep = " OR ";
254
- if( cTerm!=',' && zGlobList[i] ) i++;
255
- zGlobList += i;
256
- if( zGlobList[0] ) zGlobList++;
257
- nTerm++;
258
- }
259
- if( nTerm ){
260
- blob_appendf(&expr, ")");
261
- return blob_str(&expr);
262
- }else{
263
- return "0";
264
- }
265
-}
266
-
267213
/*
268214
** COMMAND: extras
269215
** Usage: %fossil extras ?--dotfiles? ?--ignore GLOBPATTERN?
270216
**
271217
** Print a list of all files in the source tree that are NOT part of
@@ -288,33 +234,34 @@
288234
Stmt q;
289235
int n;
290236
const char *zIgnoreFlag = find_option("ignore",0,1);
291237
int allFlag = find_option("dotfiles",0,0)!=0;
292238
int outputManifest;
239
+ Glob *pIgnore;
293240
294241
db_must_be_within_tree();
295242
outputManifest = db_get_boolean("manifest",0);
296243
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
297244
n = strlen(g.zLocalRoot);
298245
blob_init(&path, g.zLocalRoot, n-1);
299246
if( zIgnoreFlag==0 ){
300247
zIgnoreFlag = db_get("ignore-glob", 0);
301248
}
302
- vfile_scan(0, &path, blob_size(&path), allFlag);
249
+ pIgnore = glob_create(zIgnoreFlag);
250
+ vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
251
+ glob_free(pIgnore);
303252
db_prepare(&q,
304253
"SELECT x FROM sfile"
305254
" WHERE x NOT IN (%s)"
306
- " AND NOT %s"
307255
" ORDER BY 1",
308
- fossil_all_reserved_names(),
309
- glob_expr("x", zIgnoreFlag)
256
+ fossil_all_reserved_names()
310257
);
311258
if( file_tree_name(g.zRepositoryName, &repo, 0) ){
312259
db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
313260
}
314261
while( db_step(&q)==SQLITE_ROW ){
315
- printf("%s\n", db_column_text(&q, 0));
262
+ fossil_print("%s\n", db_column_text(&q, 0));
316263
}
317264
db_finalize(&q);
318265
}
319266
320267
/*
@@ -348,10 +295,12 @@
348295
int dotfilesFlag;
349296
const char *zIgnoreFlag;
350297
Blob path, repo;
351298
Stmt q;
352299
int n;
300
+ Glob *pIgnore;
301
+
353302
allFlag = find_option("force","f",0)!=0;
354303
dotfilesFlag = find_option("dotfiles",0,0)!=0;
355304
zIgnoreFlag = find_option("ignore",0,1);
356305
db_must_be_within_tree();
357306
if( zIgnoreFlag==0 ){
@@ -358,31 +307,33 @@
358307
zIgnoreFlag = db_get("ignore-glob", 0);
359308
}
360309
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
361310
n = strlen(g.zLocalRoot);
362311
blob_init(&path, g.zLocalRoot, n-1);
363
- vfile_scan(0, &path, blob_size(&path), dotfilesFlag);
312
+ pIgnore = glob_create(zIgnoreFlag);
313
+ vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
314
+ glob_free(pIgnore);
364315
db_prepare(&q,
365316
"SELECT %Q || x FROM sfile"
366
- " WHERE x NOT IN (%s) AND NOT %s"
317
+ " WHERE x NOT IN (%s)"
367318
" ORDER BY 1",
368
- g.zLocalRoot, fossil_all_reserved_names(), glob_expr("x",zIgnoreFlag)
319
+ g.zLocalRoot, fossil_all_reserved_names()
369320
);
370321
if( file_tree_name(g.zRepositoryName, &repo, 0) ){
371322
db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
372323
}
373324
while( db_step(&q)==SQLITE_ROW ){
374325
if( allFlag ){
375
- unlink(db_column_text(&q, 0));
326
+ file_delete(db_column_text(&q, 0));
376327
}else{
377328
Blob ans;
378329
char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ",
379330
db_column_text(&q, 0));
380331
blob_zero(&ans);
381332
prompt_user(prompt, &ans);
382333
if( blob_str(&ans)[0]=='y' ){
383
- unlink(db_column_text(&q, 0));
334
+ file_delete(db_column_text(&q, 0));
384335
}
385336
}
386337
}
387338
db_finalize(&q);
388339
}
@@ -463,26 +414,31 @@
463414
blob_add_cr(&text);
464415
#endif
465416
blob_write_to_file(&text, zFile);
466417
if( zEditor ){
467418
zCmd = mprintf("%s \"%s\"", zEditor, zFile);
468
- printf("%s\n", zCmd);
419
+ fossil_print("%s\n", zCmd);
469420
if( fossil_system(zCmd) ){
470421
fossil_panic("editor aborted");
471422
}
472423
blob_reset(&text);
473424
blob_read_from_file(&text, zFile);
474425
}else{
475426
char zIn[300];
476427
blob_reset(&text);
477428
while( fgets(zIn, sizeof(zIn), stdin)!=0 ){
478
- if( zIn[0]=='.' && (zIn[1]==0 || zIn[1]=='\r' || zIn[1]=='\n') ) break;
429
+ char *zUtf8 = fossil_mbcs_to_utf8(zIn);
430
+ if( zUtf8[0]=='.' && (zUtf8[1]==0 || zUtf8[1]=='\r' || zUtf8[1]=='\n') ){
431
+ fossil_mbcs_free(zUtf8);
432
+ break;
433
+ }
479434
blob_append(&text, zIn, -1);
435
+ fossil_mbcs_free(zUtf8);
480436
}
481437
}
482438
blob_remove_cr(&text);
483
- unlink(zFile);
439
+ file_delete(zFile);
484440
free(zFile);
485441
blob_zero(pComment);
486442
while( blob_line(&text, &line) ){
487443
int i, n;
488444
char *z;
@@ -534,28 +490,10 @@
534490
}
535491
g.aCommitFile[ii-2] = 0;
536492
}
537493
}
538494
539
-/*
540
-** Return true if the check-in with RID=rid is a leaf.
541
-** A leaf has no children in the same branch.
542
-*/
543
-int is_a_leaf(int rid){
544
- int rc;
545
- static const char zSql[] =
546
- @ SELECT 1 FROM plink
547
- @ WHERE pid=%d
548
- @ AND coalesce((SELECT value FROM tagxref
549
- @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
550
- @ =coalesce((SELECT value FROM tagxref
551
- @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
552
- ;
553
- rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH);
554
- return rc==0;
555
-}
556
-
557495
/*
558496
** Make sure the current check-in with timestamp zDate is younger than its
559497
** ancestor identified rid and zUuid. Throw a fatal error if not.
560498
*/
561499
static void checkin_verify_younger(
@@ -795,12 +733,13 @@
795733
}
796734
if( nCrNl ){
797735
char c;
798736
file_relative_name(zFilename, &fname);
799737
blob_zero(&ans);
800
- zMsg = mprintf("%s contains CR/NL line endings; commit anyhow (y/N/a)?",
801
- blob_str(&fname));
738
+ zMsg = mprintf(
739
+ "%s contains CR/NL line endings; commit anyhow (yes/no/all)?",
740
+ blob_str(&fname));
802741
prompt_user(zMsg, &ans);
803742
fossil_free(zMsg);
804743
c = blob_str(&ans)[0];
805744
if( c=='a' ){
806745
allOk = 1;
@@ -1179,11 +1118,11 @@
11791118
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
11801119
manifest_crosslink(nvid, &manifest);
11811120
assert( blob_is_reset(&manifest) );
11821121
content_deltify(vid, nvid, 0);
11831122
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
1184
- printf("New_Version: %s\n", zUuid);
1123
+ fossil_print("New_Version: %s\n", zUuid);
11851124
if( outputManifest ){
11861125
zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
11871126
blob_zero(&muuid);
11881127
blob_appendf(&muuid, "%s\n", zUuid);
11891128
blob_write_to_file(&muuid, zManifestFile);
@@ -1248,8 +1187,8 @@
12481187
12491188
if( !g.markPrivate ){
12501189
autosync(AUTOSYNC_PUSH);
12511190
}
12521191
if( count_nonbranch_children(vid)>1 ){
1253
- printf("**** warning: a fork has occurred *****\n");
1192
+ fossil_print("**** warning: a fork has occurred *****\n");
12541193
}
12551194
}
12561195
--- src/checkin.c
+++ src/checkin.c
@@ -54,11 +54,11 @@
54 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
55 blob_append(report, zPrefix, nPrefix);
56 if( isDeleted ){
57 blob_appendf(report, "DELETED %s\n", zPathname);
58 }else if( !file_isfile(zFullName) ){
59 if( access(zFullName, 0)==0 ){
60 blob_appendf(report, "NOT_A_FILE %s\n", zPathname);
61 if( missingIsFatal ){
62 fossil_warning("not a file: %s", zPathname);
63 nErr++;
64 }
@@ -142,13 +142,13 @@
142 */
143 void status_cmd(void){
144 int vid;
145 db_must_be_within_tree();
146 /* 012345678901234 */
147 printf("repository: %s\n", db_lget("repository",""));
148 printf("local-root: %s\n", g.zLocalRoot);
149 printf("server-code: %s\n", db_get("server-code", ""));
150 vid = db_lget_int("checkout", 0);
151 if( vid ){
152 show_common_info(vid, "checkout:", 1, 1);
153 }
154 changes_cmd();
@@ -185,87 +185,33 @@
185 int isNew = db_column_int(&q,2)==0;
186 int chnged = db_column_int(&q,3);
187 int renamed = db_column_int(&q,4);
188 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
189 if( isBrief ){
190 printf("%s\n", zPathname);
191 }else if( isNew ){
192 printf("ADDED %s\n", zPathname);
193 }else if( isDeleted ){
194 printf("DELETED %s\n", zPathname);
195 }else if( !file_isfile(zFullName) ){
196 if( access(zFullName, 0)==0 ){
197 printf("NOT_A_FILE %s\n", zPathname);
198 }else{
199 printf("MISSING %s\n", zPathname);
200 }
201 }else if( chnged ){
202 printf("EDITED %s\n", zPathname);
203 }else if( renamed ){
204 printf("RENAMED %s\n", zPathname);
205 }else{
206 printf("UNCHANGED %s\n", zPathname);
207 }
208 free(zFullName);
209 }
210 db_finalize(&q);
211 }
212
213 /*
214 ** Construct and return a string which is an SQL expression that will
215 ** be TRUE if value zVal matches any of the GLOB expressions in the list
216 ** zGlobList. For example:
217 **
218 ** zVal: "x"
219 ** zGlobList: "*.o,*.obj"
220 **
221 ** Result: "(x GLOB '*.o' OR x GLOB '*.obj')"
222 **
223 ** Each element of the GLOB list may optionally be enclosed in either '...'
224 ** or "...". This allows commas in the expression. Whitespace at the
225 ** beginning and end of each GLOB pattern is ignored, except when enclosed
226 ** within '...' or "...".
227 **
228 ** This routine makes no effort to free the memory space it uses.
229 */
230 char *glob_expr(const char *zVal, const char *zGlobList){
231 Blob expr;
232 char *zSep = "(";
233 int nTerm = 0;
234 int i;
235 int cTerm;
236
237 if( zGlobList==0 || zGlobList[0]==0 ) return "0";
238 blob_zero(&expr);
239 while( zGlobList[0] ){
240 while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ) zGlobList++;
241 if( zGlobList[0]==0 ) break;
242 if( zGlobList[0]=='\'' || zGlobList[0]=='"' ){
243 cTerm = zGlobList[0];
244 zGlobList++;
245 }else{
246 cTerm = ',';
247 }
248 for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){}
249 if( cTerm==',' ){
250 while( i>0 && fossil_isspace(zGlobList[i-1]) ){ i--; }
251 }
252 blob_appendf(&expr, "%s%s GLOB '%.*q'", zSep, zVal, i, zGlobList);
253 zSep = " OR ";
254 if( cTerm!=',' && zGlobList[i] ) i++;
255 zGlobList += i;
256 if( zGlobList[0] ) zGlobList++;
257 nTerm++;
258 }
259 if( nTerm ){
260 blob_appendf(&expr, ")");
261 return blob_str(&expr);
262 }else{
263 return "0";
264 }
265 }
266
267 /*
268 ** COMMAND: extras
269 ** Usage: %fossil extras ?--dotfiles? ?--ignore GLOBPATTERN?
270 **
271 ** Print a list of all files in the source tree that are NOT part of
@@ -288,33 +234,34 @@
288 Stmt q;
289 int n;
290 const char *zIgnoreFlag = find_option("ignore",0,1);
291 int allFlag = find_option("dotfiles",0,0)!=0;
292 int outputManifest;
 
293
294 db_must_be_within_tree();
295 outputManifest = db_get_boolean("manifest",0);
296 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
297 n = strlen(g.zLocalRoot);
298 blob_init(&path, g.zLocalRoot, n-1);
299 if( zIgnoreFlag==0 ){
300 zIgnoreFlag = db_get("ignore-glob", 0);
301 }
302 vfile_scan(0, &path, blob_size(&path), allFlag);
 
 
303 db_prepare(&q,
304 "SELECT x FROM sfile"
305 " WHERE x NOT IN (%s)"
306 " AND NOT %s"
307 " ORDER BY 1",
308 fossil_all_reserved_names(),
309 glob_expr("x", zIgnoreFlag)
310 );
311 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
312 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
313 }
314 while( db_step(&q)==SQLITE_ROW ){
315 printf("%s\n", db_column_text(&q, 0));
316 }
317 db_finalize(&q);
318 }
319
320 /*
@@ -348,10 +295,12 @@
348 int dotfilesFlag;
349 const char *zIgnoreFlag;
350 Blob path, repo;
351 Stmt q;
352 int n;
 
 
353 allFlag = find_option("force","f",0)!=0;
354 dotfilesFlag = find_option("dotfiles",0,0)!=0;
355 zIgnoreFlag = find_option("ignore",0,1);
356 db_must_be_within_tree();
357 if( zIgnoreFlag==0 ){
@@ -358,31 +307,33 @@
358 zIgnoreFlag = db_get("ignore-glob", 0);
359 }
360 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
361 n = strlen(g.zLocalRoot);
362 blob_init(&path, g.zLocalRoot, n-1);
363 vfile_scan(0, &path, blob_size(&path), dotfilesFlag);
 
 
364 db_prepare(&q,
365 "SELECT %Q || x FROM sfile"
366 " WHERE x NOT IN (%s) AND NOT %s"
367 " ORDER BY 1",
368 g.zLocalRoot, fossil_all_reserved_names(), glob_expr("x",zIgnoreFlag)
369 );
370 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
371 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
372 }
373 while( db_step(&q)==SQLITE_ROW ){
374 if( allFlag ){
375 unlink(db_column_text(&q, 0));
376 }else{
377 Blob ans;
378 char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ",
379 db_column_text(&q, 0));
380 blob_zero(&ans);
381 prompt_user(prompt, &ans);
382 if( blob_str(&ans)[0]=='y' ){
383 unlink(db_column_text(&q, 0));
384 }
385 }
386 }
387 db_finalize(&q);
388 }
@@ -463,26 +414,31 @@
463 blob_add_cr(&text);
464 #endif
465 blob_write_to_file(&text, zFile);
466 if( zEditor ){
467 zCmd = mprintf("%s \"%s\"", zEditor, zFile);
468 printf("%s\n", zCmd);
469 if( fossil_system(zCmd) ){
470 fossil_panic("editor aborted");
471 }
472 blob_reset(&text);
473 blob_read_from_file(&text, zFile);
474 }else{
475 char zIn[300];
476 blob_reset(&text);
477 while( fgets(zIn, sizeof(zIn), stdin)!=0 ){
478 if( zIn[0]=='.' && (zIn[1]==0 || zIn[1]=='\r' || zIn[1]=='\n') ) break;
 
 
 
 
479 blob_append(&text, zIn, -1);
 
480 }
481 }
482 blob_remove_cr(&text);
483 unlink(zFile);
484 free(zFile);
485 blob_zero(pComment);
486 while( blob_line(&text, &line) ){
487 int i, n;
488 char *z;
@@ -534,28 +490,10 @@
534 }
535 g.aCommitFile[ii-2] = 0;
536 }
537 }
538
539 /*
540 ** Return true if the check-in with RID=rid is a leaf.
541 ** A leaf has no children in the same branch.
542 */
543 int is_a_leaf(int rid){
544 int rc;
545 static const char zSql[] =
546 @ SELECT 1 FROM plink
547 @ WHERE pid=%d
548 @ AND coalesce((SELECT value FROM tagxref
549 @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
550 @ =coalesce((SELECT value FROM tagxref
551 @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
552 ;
553 rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH);
554 return rc==0;
555 }
556
557 /*
558 ** Make sure the current check-in with timestamp zDate is younger than its
559 ** ancestor identified rid and zUuid. Throw a fatal error if not.
560 */
561 static void checkin_verify_younger(
@@ -795,12 +733,13 @@
795 }
796 if( nCrNl ){
797 char c;
798 file_relative_name(zFilename, &fname);
799 blob_zero(&ans);
800 zMsg = mprintf("%s contains CR/NL line endings; commit anyhow (y/N/a)?",
801 blob_str(&fname));
 
802 prompt_user(zMsg, &ans);
803 fossil_free(zMsg);
804 c = blob_str(&ans)[0];
805 if( c=='a' ){
806 allOk = 1;
@@ -1179,11 +1118,11 @@
1179 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
1180 manifest_crosslink(nvid, &manifest);
1181 assert( blob_is_reset(&manifest) );
1182 content_deltify(vid, nvid, 0);
1183 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
1184 printf("New_Version: %s\n", zUuid);
1185 if( outputManifest ){
1186 zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
1187 blob_zero(&muuid);
1188 blob_appendf(&muuid, "%s\n", zUuid);
1189 blob_write_to_file(&muuid, zManifestFile);
@@ -1248,8 +1187,8 @@
1248
1249 if( !g.markPrivate ){
1250 autosync(AUTOSYNC_PUSH);
1251 }
1252 if( count_nonbranch_children(vid)>1 ){
1253 printf("**** warning: a fork has occurred *****\n");
1254 }
1255 }
1256
--- src/checkin.c
+++ src/checkin.c
@@ -54,11 +54,11 @@
54 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
55 blob_append(report, zPrefix, nPrefix);
56 if( isDeleted ){
57 blob_appendf(report, "DELETED %s\n", zPathname);
58 }else if( !file_isfile(zFullName) ){
59 if( file_access(zFullName, 0)==0 ){
60 blob_appendf(report, "NOT_A_FILE %s\n", zPathname);
61 if( missingIsFatal ){
62 fossil_warning("not a file: %s", zPathname);
63 nErr++;
64 }
@@ -142,13 +142,13 @@
142 */
143 void status_cmd(void){
144 int vid;
145 db_must_be_within_tree();
146 /* 012345678901234 */
147 fossil_print("repository: %s\n", db_lget("repository",""));
148 fossil_print("local-root: %s\n", g.zLocalRoot);
149 fossil_print("server-code: %s\n", db_get("server-code", ""));
150 vid = db_lget_int("checkout", 0);
151 if( vid ){
152 show_common_info(vid, "checkout:", 1, 1);
153 }
154 changes_cmd();
@@ -185,87 +185,33 @@
185 int isNew = db_column_int(&q,2)==0;
186 int chnged = db_column_int(&q,3);
187 int renamed = db_column_int(&q,4);
188 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
189 if( isBrief ){
190 fossil_print("%s\n", zPathname);
191 }else if( isNew ){
192 fossil_print("ADDED %s\n", zPathname);
193 }else if( isDeleted ){
194 fossil_print("DELETED %s\n", zPathname);
195 }else if( !file_isfile(zFullName) ){
196 if( file_access(zFullName, 0)==0 ){
197 fossil_print("NOT_A_FILE %s\n", zPathname);
198 }else{
199 fossil_print("MISSING %s\n", zPathname);
200 }
201 }else if( chnged ){
202 fossil_print("EDITED %s\n", zPathname);
203 }else if( renamed ){
204 fossil_print("RENAMED %s\n", zPathname);
205 }else{
206 fossil_print("UNCHANGED %s\n", zPathname);
207 }
208 free(zFullName);
209 }
210 db_finalize(&q);
211 }
212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213 /*
214 ** COMMAND: extras
215 ** Usage: %fossil extras ?--dotfiles? ?--ignore GLOBPATTERN?
216 **
217 ** Print a list of all files in the source tree that are NOT part of
@@ -288,33 +234,34 @@
234 Stmt q;
235 int n;
236 const char *zIgnoreFlag = find_option("ignore",0,1);
237 int allFlag = find_option("dotfiles",0,0)!=0;
238 int outputManifest;
239 Glob *pIgnore;
240
241 db_must_be_within_tree();
242 outputManifest = db_get_boolean("manifest",0);
243 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
244 n = strlen(g.zLocalRoot);
245 blob_init(&path, g.zLocalRoot, n-1);
246 if( zIgnoreFlag==0 ){
247 zIgnoreFlag = db_get("ignore-glob", 0);
248 }
249 pIgnore = glob_create(zIgnoreFlag);
250 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
251 glob_free(pIgnore);
252 db_prepare(&q,
253 "SELECT x FROM sfile"
254 " WHERE x NOT IN (%s)"
 
255 " ORDER BY 1",
256 fossil_all_reserved_names()
 
257 );
258 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
259 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
260 }
261 while( db_step(&q)==SQLITE_ROW ){
262 fossil_print("%s\n", db_column_text(&q, 0));
263 }
264 db_finalize(&q);
265 }
266
267 /*
@@ -348,10 +295,12 @@
295 int dotfilesFlag;
296 const char *zIgnoreFlag;
297 Blob path, repo;
298 Stmt q;
299 int n;
300 Glob *pIgnore;
301
302 allFlag = find_option("force","f",0)!=0;
303 dotfilesFlag = find_option("dotfiles",0,0)!=0;
304 zIgnoreFlag = find_option("ignore",0,1);
305 db_must_be_within_tree();
306 if( zIgnoreFlag==0 ){
@@ -358,31 +307,33 @@
307 zIgnoreFlag = db_get("ignore-glob", 0);
308 }
309 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
310 n = strlen(g.zLocalRoot);
311 blob_init(&path, g.zLocalRoot, n-1);
312 pIgnore = glob_create(zIgnoreFlag);
313 vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
314 glob_free(pIgnore);
315 db_prepare(&q,
316 "SELECT %Q || x FROM sfile"
317 " WHERE x NOT IN (%s)"
318 " ORDER BY 1",
319 g.zLocalRoot, fossil_all_reserved_names()
320 );
321 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
322 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
323 }
324 while( db_step(&q)==SQLITE_ROW ){
325 if( allFlag ){
326 file_delete(db_column_text(&q, 0));
327 }else{
328 Blob ans;
329 char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ",
330 db_column_text(&q, 0));
331 blob_zero(&ans);
332 prompt_user(prompt, &ans);
333 if( blob_str(&ans)[0]=='y' ){
334 file_delete(db_column_text(&q, 0));
335 }
336 }
337 }
338 db_finalize(&q);
339 }
@@ -463,26 +414,31 @@
414 blob_add_cr(&text);
415 #endif
416 blob_write_to_file(&text, zFile);
417 if( zEditor ){
418 zCmd = mprintf("%s \"%s\"", zEditor, zFile);
419 fossil_print("%s\n", zCmd);
420 if( fossil_system(zCmd) ){
421 fossil_panic("editor aborted");
422 }
423 blob_reset(&text);
424 blob_read_from_file(&text, zFile);
425 }else{
426 char zIn[300];
427 blob_reset(&text);
428 while( fgets(zIn, sizeof(zIn), stdin)!=0 ){
429 char *zUtf8 = fossil_mbcs_to_utf8(zIn);
430 if( zUtf8[0]=='.' && (zUtf8[1]==0 || zUtf8[1]=='\r' || zUtf8[1]=='\n') ){
431 fossil_mbcs_free(zUtf8);
432 break;
433 }
434 blob_append(&text, zIn, -1);
435 fossil_mbcs_free(zUtf8);
436 }
437 }
438 blob_remove_cr(&text);
439 file_delete(zFile);
440 free(zFile);
441 blob_zero(pComment);
442 while( blob_line(&text, &line) ){
443 int i, n;
444 char *z;
@@ -534,28 +490,10 @@
490 }
491 g.aCommitFile[ii-2] = 0;
492 }
493 }
494
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495 /*
496 ** Make sure the current check-in with timestamp zDate is younger than its
497 ** ancestor identified rid and zUuid. Throw a fatal error if not.
498 */
499 static void checkin_verify_younger(
@@ -795,12 +733,13 @@
733 }
734 if( nCrNl ){
735 char c;
736 file_relative_name(zFilename, &fname);
737 blob_zero(&ans);
738 zMsg = mprintf(
739 "%s contains CR/NL line endings; commit anyhow (yes/no/all)?",
740 blob_str(&fname));
741 prompt_user(zMsg, &ans);
742 fossil_free(zMsg);
743 c = blob_str(&ans)[0];
744 if( c=='a' ){
745 allOk = 1;
@@ -1179,11 +1118,11 @@
1118 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
1119 manifest_crosslink(nvid, &manifest);
1120 assert( blob_is_reset(&manifest) );
1121 content_deltify(vid, nvid, 0);
1122 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
1123 fossil_print("New_Version: %s\n", zUuid);
1124 if( outputManifest ){
1125 zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
1126 blob_zero(&muuid);
1127 blob_appendf(&muuid, "%s\n", zUuid);
1128 blob_write_to_file(&muuid, zManifestFile);
@@ -1248,8 +1187,8 @@
1187
1188 if( !g.markPrivate ){
1189 autosync(AUTOSYNC_PUSH);
1190 }
1191 if( count_nonbranch_children(vid)>1 ){
1192 fossil_print("**** warning: a fork has occurred *****\n");
1193 }
1194 }
1195
+41 -102
--- src/checkin.c
+++ src/checkin.c
@@ -54,11 +54,11 @@
5454
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
5555
blob_append(report, zPrefix, nPrefix);
5656
if( isDeleted ){
5757
blob_appendf(report, "DELETED %s\n", zPathname);
5858
}else if( !file_isfile(zFullName) ){
59
- if( access(zFullName, 0)==0 ){
59
+ if( file_access(zFullName, 0)==0 ){
6060
blob_appendf(report, "NOT_A_FILE %s\n", zPathname);
6161
if( missingIsFatal ){
6262
fossil_warning("not a file: %s", zPathname);
6363
nErr++;
6464
}
@@ -142,13 +142,13 @@
142142
*/
143143
void status_cmd(void){
144144
int vid;
145145
db_must_be_within_tree();
146146
/* 012345678901234 */
147
- printf("repository: %s\n", db_lget("repository",""));
148
- printf("local-root: %s\n", g.zLocalRoot);
149
- printf("server-code: %s\n", db_get("server-code", ""));
147
+ fossil_print("repository: %s\n", db_lget("repository",""));
148
+ fossil_print("local-root: %s\n", g.zLocalRoot);
149
+ fossil_print("server-code: %s\n", db_get("server-code", ""));
150150
vid = db_lget_int("checkout", 0);
151151
if( vid ){
152152
show_common_info(vid, "checkout:", 1, 1);
153153
}
154154
changes_cmd();
@@ -185,87 +185,33 @@
185185
int isNew = db_column_int(&q,2)==0;
186186
int chnged = db_column_int(&q,3);
187187
int renamed = db_column_int(&q,4);
188188
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
189189
if( isBrief ){
190
- printf("%s\n", zPathname);
190
+ fossil_print("%s\n", zPathname);
191191
}else if( isNew ){
192
- printf("ADDED %s\n", zPathname);
192
+ fossil_print("ADDED %s\n", zPathname);
193193
}else if( isDeleted ){
194
- printf("DELETED %s\n", zPathname);
194
+ fossil_print("DELETED %s\n", zPathname);
195195
}else if( !file_isfile(zFullName) ){
196
- if( access(zFullName, 0)==0 ){
197
- printf("NOT_A_FILE %s\n", zPathname);
196
+ if( file_access(zFullName, 0)==0 ){
197
+ fossil_print("NOT_A_FILE %s\n", zPathname);
198198
}else{
199
- printf("MISSING %s\n", zPathname);
199
+ fossil_print("MISSING %s\n", zPathname);
200200
}
201201
}else if( chnged ){
202
- printf("EDITED %s\n", zPathname);
202
+ fossil_print("EDITED %s\n", zPathname);
203203
}else if( renamed ){
204
- printf("RENAMED %s\n", zPathname);
204
+ fossil_print("RENAMED %s\n", zPathname);
205205
}else{
206
- printf("UNCHANGED %s\n", zPathname);
206
+ fossil_print("UNCHANGED %s\n", zPathname);
207207
}
208208
free(zFullName);
209209
}
210210
db_finalize(&q);
211211
}
212212
213
-/*
214
-** Construct and return a string which is an SQL expression that will
215
-** be TRUE if value zVal matches any of the GLOB expressions in the list
216
-** zGlobList. For example:
217
-**
218
-** zVal: "x"
219
-** zGlobList: "*.o,*.obj"
220
-**
221
-** Result: "(x GLOB '*.o' OR x GLOB '*.obj')"
222
-**
223
-** Each element of the GLOB list may optionally be enclosed in either '...'
224
-** or "...". This allows commas in the expression. Whitespace at the
225
-** beginning and end of each GLOB pattern is ignored, except when enclosed
226
-** within '...' or "...".
227
-**
228
-** This routine makes no effort to free the memory space it uses.
229
-*/
230
-char *glob_expr(const char *zVal, const char *zGlobList){
231
- Blob expr;
232
- char *zSep = "(";
233
- int nTerm = 0;
234
- int i;
235
- int cTerm;
236
-
237
- if( zGlobList==0 || zGlobList[0]==0 ) return "0";
238
- blob_zero(&expr);
239
- while( zGlobList[0] ){
240
- while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ) zGlobList++;
241
- if( zGlobList[0]==0 ) break;
242
- if( zGlobList[0]=='\'' || zGlobList[0]=='"' ){
243
- cTerm = zGlobList[0];
244
- zGlobList++;
245
- }else{
246
- cTerm = ',';
247
- }
248
- for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){}
249
- if( cTerm==',' ){
250
- while( i>0 && fossil_isspace(zGlobList[i-1]) ){ i--; }
251
- }
252
- blob_appendf(&expr, "%s%s GLOB '%.*q'", zSep, zVal, i, zGlobList);
253
- zSep = " OR ";
254
- if( cTerm!=',' && zGlobList[i] ) i++;
255
- zGlobList += i;
256
- if( zGlobList[0] ) zGlobList++;
257
- nTerm++;
258
- }
259
- if( nTerm ){
260
- blob_appendf(&expr, ")");
261
- return blob_str(&expr);
262
- }else{
263
- return "0";
264
- }
265
-}
266
-
267213
/*
268214
** COMMAND: extras
269215
** Usage: %fossil extras ?--dotfiles? ?--ignore GLOBPATTERN?
270216
**
271217
** Print a list of all files in the source tree that are NOT part of
@@ -288,33 +234,34 @@
288234
Stmt q;
289235
int n;
290236
const char *zIgnoreFlag = find_option("ignore",0,1);
291237
int allFlag = find_option("dotfiles",0,0)!=0;
292238
int outputManifest;
239
+ Glob *pIgnore;
293240
294241
db_must_be_within_tree();
295242
outputManifest = db_get_boolean("manifest",0);
296243
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
297244
n = strlen(g.zLocalRoot);
298245
blob_init(&path, g.zLocalRoot, n-1);
299246
if( zIgnoreFlag==0 ){
300247
zIgnoreFlag = db_get("ignore-glob", 0);
301248
}
302
- vfile_scan(0, &path, blob_size(&path), allFlag);
249
+ pIgnore = glob_create(zIgnoreFlag);
250
+ vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
251
+ glob_free(pIgnore);
303252
db_prepare(&q,
304253
"SELECT x FROM sfile"
305254
" WHERE x NOT IN (%s)"
306
- " AND NOT %s"
307255
" ORDER BY 1",
308
- fossil_all_reserved_names(),
309
- glob_expr("x", zIgnoreFlag)
256
+ fossil_all_reserved_names()
310257
);
311258
if( file_tree_name(g.zRepositoryName, &repo, 0) ){
312259
db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
313260
}
314261
while( db_step(&q)==SQLITE_ROW ){
315
- printf("%s\n", db_column_text(&q, 0));
262
+ fossil_print("%s\n", db_column_text(&q, 0));
316263
}
317264
db_finalize(&q);
318265
}
319266
320267
/*
@@ -348,10 +295,12 @@
348295
int dotfilesFlag;
349296
const char *zIgnoreFlag;
350297
Blob path, repo;
351298
Stmt q;
352299
int n;
300
+ Glob *pIgnore;
301
+
353302
allFlag = find_option("force","f",0)!=0;
354303
dotfilesFlag = find_option("dotfiles",0,0)!=0;
355304
zIgnoreFlag = find_option("ignore",0,1);
356305
db_must_be_within_tree();
357306
if( zIgnoreFlag==0 ){
@@ -358,31 +307,33 @@
358307
zIgnoreFlag = db_get("ignore-glob", 0);
359308
}
360309
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
361310
n = strlen(g.zLocalRoot);
362311
blob_init(&path, g.zLocalRoot, n-1);
363
- vfile_scan(0, &path, blob_size(&path), dotfilesFlag);
312
+ pIgnore = glob_create(zIgnoreFlag);
313
+ vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
314
+ glob_free(pIgnore);
364315
db_prepare(&q,
365316
"SELECT %Q || x FROM sfile"
366
- " WHERE x NOT IN (%s) AND NOT %s"
317
+ " WHERE x NOT IN (%s)"
367318
" ORDER BY 1",
368
- g.zLocalRoot, fossil_all_reserved_names(), glob_expr("x",zIgnoreFlag)
319
+ g.zLocalRoot, fossil_all_reserved_names()
369320
);
370321
if( file_tree_name(g.zRepositoryName, &repo, 0) ){
371322
db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
372323
}
373324
while( db_step(&q)==SQLITE_ROW ){
374325
if( allFlag ){
375
- unlink(db_column_text(&q, 0));
326
+ file_delete(db_column_text(&q, 0));
376327
}else{
377328
Blob ans;
378329
char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ",
379330
db_column_text(&q, 0));
380331
blob_zero(&ans);
381332
prompt_user(prompt, &ans);
382333
if( blob_str(&ans)[0]=='y' ){
383
- unlink(db_column_text(&q, 0));
334
+ file_delete(db_column_text(&q, 0));
384335
}
385336
}
386337
}
387338
db_finalize(&q);
388339
}
@@ -463,26 +414,31 @@
463414
blob_add_cr(&text);
464415
#endif
465416
blob_write_to_file(&text, zFile);
466417
if( zEditor ){
467418
zCmd = mprintf("%s \"%s\"", zEditor, zFile);
468
- printf("%s\n", zCmd);
419
+ fossil_print("%s\n", zCmd);
469420
if( fossil_system(zCmd) ){
470421
fossil_panic("editor aborted");
471422
}
472423
blob_reset(&text);
473424
blob_read_from_file(&text, zFile);
474425
}else{
475426
char zIn[300];
476427
blob_reset(&text);
477428
while( fgets(zIn, sizeof(zIn), stdin)!=0 ){
478
- if( zIn[0]=='.' && (zIn[1]==0 || zIn[1]=='\r' || zIn[1]=='\n') ) break;
429
+ char *zUtf8 = fossil_mbcs_to_utf8(zIn);
430
+ if( zUtf8[0]=='.' && (zUtf8[1]==0 || zUtf8[1]=='\r' || zUtf8[1]=='\n') ){
431
+ fossil_mbcs_free(zUtf8);
432
+ break;
433
+ }
479434
blob_append(&text, zIn, -1);
435
+ fossil_mbcs_free(zUtf8);
480436
}
481437
}
482438
blob_remove_cr(&text);
483
- unlink(zFile);
439
+ file_delete(zFile);
484440
free(zFile);
485441
blob_zero(pComment);
486442
while( blob_line(&text, &line) ){
487443
int i, n;
488444
char *z;
@@ -534,28 +490,10 @@
534490
}
535491
g.aCommitFile[ii-2] = 0;
536492
}
537493
}
538494
539
-/*
540
-** Return true if the check-in with RID=rid is a leaf.
541
-** A leaf has no children in the same branch.
542
-*/
543
-int is_a_leaf(int rid){
544
- int rc;
545
- static const char zSql[] =
546
- @ SELECT 1 FROM plink
547
- @ WHERE pid=%d
548
- @ AND coalesce((SELECT value FROM tagxref
549
- @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
550
- @ =coalesce((SELECT value FROM tagxref
551
- @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
552
- ;
553
- rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH);
554
- return rc==0;
555
-}
556
-
557495
/*
558496
** Make sure the current check-in with timestamp zDate is younger than its
559497
** ancestor identified rid and zUuid. Throw a fatal error if not.
560498
*/
561499
static void checkin_verify_younger(
@@ -795,12 +733,13 @@
795733
}
796734
if( nCrNl ){
797735
char c;
798736
file_relative_name(zFilename, &fname);
799737
blob_zero(&ans);
800
- zMsg = mprintf("%s contains CR/NL line endings; commit anyhow (y/N/a)?",
801
- blob_str(&fname));
738
+ zMsg = mprintf(
739
+ "%s contains CR/NL line endings; commit anyhow (yes/no/all)?",
740
+ blob_str(&fname));
802741
prompt_user(zMsg, &ans);
803742
fossil_free(zMsg);
804743
c = blob_str(&ans)[0];
805744
if( c=='a' ){
806745
allOk = 1;
@@ -1179,11 +1118,11 @@
11791118
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
11801119
manifest_crosslink(nvid, &manifest);
11811120
assert( blob_is_reset(&manifest) );
11821121
content_deltify(vid, nvid, 0);
11831122
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
1184
- printf("New_Version: %s\n", zUuid);
1123
+ fossil_print("New_Version: %s\n", zUuid);
11851124
if( outputManifest ){
11861125
zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
11871126
blob_zero(&muuid);
11881127
blob_appendf(&muuid, "%s\n", zUuid);
11891128
blob_write_to_file(&muuid, zManifestFile);
@@ -1248,8 +1187,8 @@
12481187
12491188
if( !g.markPrivate ){
12501189
autosync(AUTOSYNC_PUSH);
12511190
}
12521191
if( count_nonbranch_children(vid)>1 ){
1253
- printf("**** warning: a fork has occurred *****\n");
1192
+ fossil_print("**** warning: a fork has occurred *****\n");
12541193
}
12551194
}
12561195
--- src/checkin.c
+++ src/checkin.c
@@ -54,11 +54,11 @@
54 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
55 blob_append(report, zPrefix, nPrefix);
56 if( isDeleted ){
57 blob_appendf(report, "DELETED %s\n", zPathname);
58 }else if( !file_isfile(zFullName) ){
59 if( access(zFullName, 0)==0 ){
60 blob_appendf(report, "NOT_A_FILE %s\n", zPathname);
61 if( missingIsFatal ){
62 fossil_warning("not a file: %s", zPathname);
63 nErr++;
64 }
@@ -142,13 +142,13 @@
142 */
143 void status_cmd(void){
144 int vid;
145 db_must_be_within_tree();
146 /* 012345678901234 */
147 printf("repository: %s\n", db_lget("repository",""));
148 printf("local-root: %s\n", g.zLocalRoot);
149 printf("server-code: %s\n", db_get("server-code", ""));
150 vid = db_lget_int("checkout", 0);
151 if( vid ){
152 show_common_info(vid, "checkout:", 1, 1);
153 }
154 changes_cmd();
@@ -185,87 +185,33 @@
185 int isNew = db_column_int(&q,2)==0;
186 int chnged = db_column_int(&q,3);
187 int renamed = db_column_int(&q,4);
188 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
189 if( isBrief ){
190 printf("%s\n", zPathname);
191 }else if( isNew ){
192 printf("ADDED %s\n", zPathname);
193 }else if( isDeleted ){
194 printf("DELETED %s\n", zPathname);
195 }else if( !file_isfile(zFullName) ){
196 if( access(zFullName, 0)==0 ){
197 printf("NOT_A_FILE %s\n", zPathname);
198 }else{
199 printf("MISSING %s\n", zPathname);
200 }
201 }else if( chnged ){
202 printf("EDITED %s\n", zPathname);
203 }else if( renamed ){
204 printf("RENAMED %s\n", zPathname);
205 }else{
206 printf("UNCHANGED %s\n", zPathname);
207 }
208 free(zFullName);
209 }
210 db_finalize(&q);
211 }
212
213 /*
214 ** Construct and return a string which is an SQL expression that will
215 ** be TRUE if value zVal matches any of the GLOB expressions in the list
216 ** zGlobList. For example:
217 **
218 ** zVal: "x"
219 ** zGlobList: "*.o,*.obj"
220 **
221 ** Result: "(x GLOB '*.o' OR x GLOB '*.obj')"
222 **
223 ** Each element of the GLOB list may optionally be enclosed in either '...'
224 ** or "...". This allows commas in the expression. Whitespace at the
225 ** beginning and end of each GLOB pattern is ignored, except when enclosed
226 ** within '...' or "...".
227 **
228 ** This routine makes no effort to free the memory space it uses.
229 */
230 char *glob_expr(const char *zVal, const char *zGlobList){
231 Blob expr;
232 char *zSep = "(";
233 int nTerm = 0;
234 int i;
235 int cTerm;
236
237 if( zGlobList==0 || zGlobList[0]==0 ) return "0";
238 blob_zero(&expr);
239 while( zGlobList[0] ){
240 while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ) zGlobList++;
241 if( zGlobList[0]==0 ) break;
242 if( zGlobList[0]=='\'' || zGlobList[0]=='"' ){
243 cTerm = zGlobList[0];
244 zGlobList++;
245 }else{
246 cTerm = ',';
247 }
248 for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){}
249 if( cTerm==',' ){
250 while( i>0 && fossil_isspace(zGlobList[i-1]) ){ i--; }
251 }
252 blob_appendf(&expr, "%s%s GLOB '%.*q'", zSep, zVal, i, zGlobList);
253 zSep = " OR ";
254 if( cTerm!=',' && zGlobList[i] ) i++;
255 zGlobList += i;
256 if( zGlobList[0] ) zGlobList++;
257 nTerm++;
258 }
259 if( nTerm ){
260 blob_appendf(&expr, ")");
261 return blob_str(&expr);
262 }else{
263 return "0";
264 }
265 }
266
267 /*
268 ** COMMAND: extras
269 ** Usage: %fossil extras ?--dotfiles? ?--ignore GLOBPATTERN?
270 **
271 ** Print a list of all files in the source tree that are NOT part of
@@ -288,33 +234,34 @@
288 Stmt q;
289 int n;
290 const char *zIgnoreFlag = find_option("ignore",0,1);
291 int allFlag = find_option("dotfiles",0,0)!=0;
292 int outputManifest;
 
293
294 db_must_be_within_tree();
295 outputManifest = db_get_boolean("manifest",0);
296 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
297 n = strlen(g.zLocalRoot);
298 blob_init(&path, g.zLocalRoot, n-1);
299 if( zIgnoreFlag==0 ){
300 zIgnoreFlag = db_get("ignore-glob", 0);
301 }
302 vfile_scan(0, &path, blob_size(&path), allFlag);
 
 
303 db_prepare(&q,
304 "SELECT x FROM sfile"
305 " WHERE x NOT IN (%s)"
306 " AND NOT %s"
307 " ORDER BY 1",
308 fossil_all_reserved_names(),
309 glob_expr("x", zIgnoreFlag)
310 );
311 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
312 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
313 }
314 while( db_step(&q)==SQLITE_ROW ){
315 printf("%s\n", db_column_text(&q, 0));
316 }
317 db_finalize(&q);
318 }
319
320 /*
@@ -348,10 +295,12 @@
348 int dotfilesFlag;
349 const char *zIgnoreFlag;
350 Blob path, repo;
351 Stmt q;
352 int n;
 
 
353 allFlag = find_option("force","f",0)!=0;
354 dotfilesFlag = find_option("dotfiles",0,0)!=0;
355 zIgnoreFlag = find_option("ignore",0,1);
356 db_must_be_within_tree();
357 if( zIgnoreFlag==0 ){
@@ -358,31 +307,33 @@
358 zIgnoreFlag = db_get("ignore-glob", 0);
359 }
360 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
361 n = strlen(g.zLocalRoot);
362 blob_init(&path, g.zLocalRoot, n-1);
363 vfile_scan(0, &path, blob_size(&path), dotfilesFlag);
 
 
364 db_prepare(&q,
365 "SELECT %Q || x FROM sfile"
366 " WHERE x NOT IN (%s) AND NOT %s"
367 " ORDER BY 1",
368 g.zLocalRoot, fossil_all_reserved_names(), glob_expr("x",zIgnoreFlag)
369 );
370 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
371 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
372 }
373 while( db_step(&q)==SQLITE_ROW ){
374 if( allFlag ){
375 unlink(db_column_text(&q, 0));
376 }else{
377 Blob ans;
378 char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ",
379 db_column_text(&q, 0));
380 blob_zero(&ans);
381 prompt_user(prompt, &ans);
382 if( blob_str(&ans)[0]=='y' ){
383 unlink(db_column_text(&q, 0));
384 }
385 }
386 }
387 db_finalize(&q);
388 }
@@ -463,26 +414,31 @@
463 blob_add_cr(&text);
464 #endif
465 blob_write_to_file(&text, zFile);
466 if( zEditor ){
467 zCmd = mprintf("%s \"%s\"", zEditor, zFile);
468 printf("%s\n", zCmd);
469 if( fossil_system(zCmd) ){
470 fossil_panic("editor aborted");
471 }
472 blob_reset(&text);
473 blob_read_from_file(&text, zFile);
474 }else{
475 char zIn[300];
476 blob_reset(&text);
477 while( fgets(zIn, sizeof(zIn), stdin)!=0 ){
478 if( zIn[0]=='.' && (zIn[1]==0 || zIn[1]=='\r' || zIn[1]=='\n') ) break;
 
 
 
 
479 blob_append(&text, zIn, -1);
 
480 }
481 }
482 blob_remove_cr(&text);
483 unlink(zFile);
484 free(zFile);
485 blob_zero(pComment);
486 while( blob_line(&text, &line) ){
487 int i, n;
488 char *z;
@@ -534,28 +490,10 @@
534 }
535 g.aCommitFile[ii-2] = 0;
536 }
537 }
538
539 /*
540 ** Return true if the check-in with RID=rid is a leaf.
541 ** A leaf has no children in the same branch.
542 */
543 int is_a_leaf(int rid){
544 int rc;
545 static const char zSql[] =
546 @ SELECT 1 FROM plink
547 @ WHERE pid=%d
548 @ AND coalesce((SELECT value FROM tagxref
549 @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
550 @ =coalesce((SELECT value FROM tagxref
551 @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
552 ;
553 rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH);
554 return rc==0;
555 }
556
557 /*
558 ** Make sure the current check-in with timestamp zDate is younger than its
559 ** ancestor identified rid and zUuid. Throw a fatal error if not.
560 */
561 static void checkin_verify_younger(
@@ -795,12 +733,13 @@
795 }
796 if( nCrNl ){
797 char c;
798 file_relative_name(zFilename, &fname);
799 blob_zero(&ans);
800 zMsg = mprintf("%s contains CR/NL line endings; commit anyhow (y/N/a)?",
801 blob_str(&fname));
 
802 prompt_user(zMsg, &ans);
803 fossil_free(zMsg);
804 c = blob_str(&ans)[0];
805 if( c=='a' ){
806 allOk = 1;
@@ -1179,11 +1118,11 @@
1179 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
1180 manifest_crosslink(nvid, &manifest);
1181 assert( blob_is_reset(&manifest) );
1182 content_deltify(vid, nvid, 0);
1183 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
1184 printf("New_Version: %s\n", zUuid);
1185 if( outputManifest ){
1186 zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
1187 blob_zero(&muuid);
1188 blob_appendf(&muuid, "%s\n", zUuid);
1189 blob_write_to_file(&muuid, zManifestFile);
@@ -1248,8 +1187,8 @@
1248
1249 if( !g.markPrivate ){
1250 autosync(AUTOSYNC_PUSH);
1251 }
1252 if( count_nonbranch_children(vid)>1 ){
1253 printf("**** warning: a fork has occurred *****\n");
1254 }
1255 }
1256
--- src/checkin.c
+++ src/checkin.c
@@ -54,11 +54,11 @@
54 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
55 blob_append(report, zPrefix, nPrefix);
56 if( isDeleted ){
57 blob_appendf(report, "DELETED %s\n", zPathname);
58 }else if( !file_isfile(zFullName) ){
59 if( file_access(zFullName, 0)==0 ){
60 blob_appendf(report, "NOT_A_FILE %s\n", zPathname);
61 if( missingIsFatal ){
62 fossil_warning("not a file: %s", zPathname);
63 nErr++;
64 }
@@ -142,13 +142,13 @@
142 */
143 void status_cmd(void){
144 int vid;
145 db_must_be_within_tree();
146 /* 012345678901234 */
147 fossil_print("repository: %s\n", db_lget("repository",""));
148 fossil_print("local-root: %s\n", g.zLocalRoot);
149 fossil_print("server-code: %s\n", db_get("server-code", ""));
150 vid = db_lget_int("checkout", 0);
151 if( vid ){
152 show_common_info(vid, "checkout:", 1, 1);
153 }
154 changes_cmd();
@@ -185,87 +185,33 @@
185 int isNew = db_column_int(&q,2)==0;
186 int chnged = db_column_int(&q,3);
187 int renamed = db_column_int(&q,4);
188 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
189 if( isBrief ){
190 fossil_print("%s\n", zPathname);
191 }else if( isNew ){
192 fossil_print("ADDED %s\n", zPathname);
193 }else if( isDeleted ){
194 fossil_print("DELETED %s\n", zPathname);
195 }else if( !file_isfile(zFullName) ){
196 if( file_access(zFullName, 0)==0 ){
197 fossil_print("NOT_A_FILE %s\n", zPathname);
198 }else{
199 fossil_print("MISSING %s\n", zPathname);
200 }
201 }else if( chnged ){
202 fossil_print("EDITED %s\n", zPathname);
203 }else if( renamed ){
204 fossil_print("RENAMED %s\n", zPathname);
205 }else{
206 fossil_print("UNCHANGED %s\n", zPathname);
207 }
208 free(zFullName);
209 }
210 db_finalize(&q);
211 }
212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213 /*
214 ** COMMAND: extras
215 ** Usage: %fossil extras ?--dotfiles? ?--ignore GLOBPATTERN?
216 **
217 ** Print a list of all files in the source tree that are NOT part of
@@ -288,33 +234,34 @@
234 Stmt q;
235 int n;
236 const char *zIgnoreFlag = find_option("ignore",0,1);
237 int allFlag = find_option("dotfiles",0,0)!=0;
238 int outputManifest;
239 Glob *pIgnore;
240
241 db_must_be_within_tree();
242 outputManifest = db_get_boolean("manifest",0);
243 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
244 n = strlen(g.zLocalRoot);
245 blob_init(&path, g.zLocalRoot, n-1);
246 if( zIgnoreFlag==0 ){
247 zIgnoreFlag = db_get("ignore-glob", 0);
248 }
249 pIgnore = glob_create(zIgnoreFlag);
250 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
251 glob_free(pIgnore);
252 db_prepare(&q,
253 "SELECT x FROM sfile"
254 " WHERE x NOT IN (%s)"
 
255 " ORDER BY 1",
256 fossil_all_reserved_names()
 
257 );
258 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
259 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
260 }
261 while( db_step(&q)==SQLITE_ROW ){
262 fossil_print("%s\n", db_column_text(&q, 0));
263 }
264 db_finalize(&q);
265 }
266
267 /*
@@ -348,10 +295,12 @@
295 int dotfilesFlag;
296 const char *zIgnoreFlag;
297 Blob path, repo;
298 Stmt q;
299 int n;
300 Glob *pIgnore;
301
302 allFlag = find_option("force","f",0)!=0;
303 dotfilesFlag = find_option("dotfiles",0,0)!=0;
304 zIgnoreFlag = find_option("ignore",0,1);
305 db_must_be_within_tree();
306 if( zIgnoreFlag==0 ){
@@ -358,31 +307,33 @@
307 zIgnoreFlag = db_get("ignore-glob", 0);
308 }
309 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
310 n = strlen(g.zLocalRoot);
311 blob_init(&path, g.zLocalRoot, n-1);
312 pIgnore = glob_create(zIgnoreFlag);
313 vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
314 glob_free(pIgnore);
315 db_prepare(&q,
316 "SELECT %Q || x FROM sfile"
317 " WHERE x NOT IN (%s)"
318 " ORDER BY 1",
319 g.zLocalRoot, fossil_all_reserved_names()
320 );
321 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
322 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
323 }
324 while( db_step(&q)==SQLITE_ROW ){
325 if( allFlag ){
326 file_delete(db_column_text(&q, 0));
327 }else{
328 Blob ans;
329 char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ",
330 db_column_text(&q, 0));
331 blob_zero(&ans);
332 prompt_user(prompt, &ans);
333 if( blob_str(&ans)[0]=='y' ){
334 file_delete(db_column_text(&q, 0));
335 }
336 }
337 }
338 db_finalize(&q);
339 }
@@ -463,26 +414,31 @@
414 blob_add_cr(&text);
415 #endif
416 blob_write_to_file(&text, zFile);
417 if( zEditor ){
418 zCmd = mprintf("%s \"%s\"", zEditor, zFile);
419 fossil_print("%s\n", zCmd);
420 if( fossil_system(zCmd) ){
421 fossil_panic("editor aborted");
422 }
423 blob_reset(&text);
424 blob_read_from_file(&text, zFile);
425 }else{
426 char zIn[300];
427 blob_reset(&text);
428 while( fgets(zIn, sizeof(zIn), stdin)!=0 ){
429 char *zUtf8 = fossil_mbcs_to_utf8(zIn);
430 if( zUtf8[0]=='.' && (zUtf8[1]==0 || zUtf8[1]=='\r' || zUtf8[1]=='\n') ){
431 fossil_mbcs_free(zUtf8);
432 break;
433 }
434 blob_append(&text, zIn, -1);
435 fossil_mbcs_free(zUtf8);
436 }
437 }
438 blob_remove_cr(&text);
439 file_delete(zFile);
440 free(zFile);
441 blob_zero(pComment);
442 while( blob_line(&text, &line) ){
443 int i, n;
444 char *z;
@@ -534,28 +490,10 @@
490 }
491 g.aCommitFile[ii-2] = 0;
492 }
493 }
494
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495 /*
496 ** Make sure the current check-in with timestamp zDate is younger than its
497 ** ancestor identified rid and zUuid. Throw a fatal error if not.
498 */
499 static void checkin_verify_younger(
@@ -795,12 +733,13 @@
733 }
734 if( nCrNl ){
735 char c;
736 file_relative_name(zFilename, &fname);
737 blob_zero(&ans);
738 zMsg = mprintf(
739 "%s contains CR/NL line endings; commit anyhow (yes/no/all)?",
740 blob_str(&fname));
741 prompt_user(zMsg, &ans);
742 fossil_free(zMsg);
743 c = blob_str(&ans)[0];
744 if( c=='a' ){
745 allOk = 1;
@@ -1179,11 +1118,11 @@
1118 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
1119 manifest_crosslink(nvid, &manifest);
1120 assert( blob_is_reset(&manifest) );
1121 content_deltify(vid, nvid, 0);
1122 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
1123 fossil_print("New_Version: %s\n", zUuid);
1124 if( outputManifest ){
1125 zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
1126 blob_zero(&muuid);
1127 blob_appendf(&muuid, "%s\n", zUuid);
1128 blob_write_to_file(&muuid, zManifestFile);
@@ -1248,8 +1187,8 @@
1187
1188 if( !g.markPrivate ){
1189 autosync(AUTOSYNC_PUSH);
1190 }
1191 if( count_nonbranch_children(vid)>1 ){
1192 fossil_print("**** warning: a fork has occurred *****\n");
1193 }
1194 }
1195
+6 -6
--- src/checkout.c
+++ src/checkout.c
@@ -157,16 +157,16 @@
157157
free(zManFile);
158158
blob_reset(&hash);
159159
}else{
160160
if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
161161
zManFile = mprintf("%smanifest", g.zLocalRoot);
162
- unlink(zManFile);
162
+ file_delete(zManFile);
163163
free(zManFile);
164164
}
165165
if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
166166
zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
167
- unlink(zManFile);
167
+ file_delete(zManFile);
168168
free(zManFile);
169169
}
170170
}
171171
172172
}
@@ -203,11 +203,11 @@
203203
db_must_be_within_tree();
204204
db_begin_transaction();
205205
forceFlag = find_option("force","f",0)!=0;
206206
keepFlag = find_option("keep",0,0)!=0;
207207
latestFlag = find_option("latest",0,0)!=0;
208
- promptFlag = find_option("prompt",0,0)!=0; /* Prompt user before overwrite */
208
+ promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;
209209
if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
210210
usage("VERSION|--latest ?--force? ?--keep?");
211211
}
212212
if( !forceFlag && unsaved_changes()==1 ){
213213
fossil_fatal("there are unsaved changes in the current checkout");
@@ -252,14 +252,14 @@
252252
db_multi_exec("DELETE FROM vmerge");
253253
if( !keepFlag && db_get_boolean("repo-cksum",1) ){
254254
vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
255255
vfile_aggregate_checksum_disk(vid, &cksum2);
256256
if( blob_compare(&cksum1, &cksum2) ){
257
- printf("WARNING: manifest checksum does not agree with disk\n");
257
+ fossil_print("WARNING: manifest checksum does not agree with disk\n");
258258
}
259259
if( blob_size(&cksum1b) && blob_compare(&cksum1, &cksum1b) ){
260
- printf("WARNING: manifest checksum does not agree with manifest\n");
260
+ fossil_print("WARNING: manifest checksum does not agree with manifest\n");
261261
}
262262
}
263263
db_end_transaction(0);
264264
}
265265
@@ -271,11 +271,11 @@
271271
int i;
272272
for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
273273
if( manifestOnly==0 || zReserved[0]=='m' ){
274274
char *z;
275275
z = mprintf("%s%s", g.zLocalRoot, zReserved);
276
- unlink(z);
276
+ file_delete(z);
277277
free(z);
278278
}
279279
}
280280
}
281281
282282
--- src/checkout.c
+++ src/checkout.c
@@ -157,16 +157,16 @@
157 free(zManFile);
158 blob_reset(&hash);
159 }else{
160 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
161 zManFile = mprintf("%smanifest", g.zLocalRoot);
162 unlink(zManFile);
163 free(zManFile);
164 }
165 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
166 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
167 unlink(zManFile);
168 free(zManFile);
169 }
170 }
171
172 }
@@ -203,11 +203,11 @@
203 db_must_be_within_tree();
204 db_begin_transaction();
205 forceFlag = find_option("force","f",0)!=0;
206 keepFlag = find_option("keep",0,0)!=0;
207 latestFlag = find_option("latest",0,0)!=0;
208 promptFlag = find_option("prompt",0,0)!=0; /* Prompt user before overwrite */
209 if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
210 usage("VERSION|--latest ?--force? ?--keep?");
211 }
212 if( !forceFlag && unsaved_changes()==1 ){
213 fossil_fatal("there are unsaved changes in the current checkout");
@@ -252,14 +252,14 @@
252 db_multi_exec("DELETE FROM vmerge");
253 if( !keepFlag && db_get_boolean("repo-cksum",1) ){
254 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
255 vfile_aggregate_checksum_disk(vid, &cksum2);
256 if( blob_compare(&cksum1, &cksum2) ){
257 printf("WARNING: manifest checksum does not agree with disk\n");
258 }
259 if( blob_size(&cksum1b) && blob_compare(&cksum1, &cksum1b) ){
260 printf("WARNING: manifest checksum does not agree with manifest\n");
261 }
262 }
263 db_end_transaction(0);
264 }
265
@@ -271,11 +271,11 @@
271 int i;
272 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
273 if( manifestOnly==0 || zReserved[0]=='m' ){
274 char *z;
275 z = mprintf("%s%s", g.zLocalRoot, zReserved);
276 unlink(z);
277 free(z);
278 }
279 }
280 }
281
282
--- src/checkout.c
+++ src/checkout.c
@@ -157,16 +157,16 @@
157 free(zManFile);
158 blob_reset(&hash);
159 }else{
160 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
161 zManFile = mprintf("%smanifest", g.zLocalRoot);
162 file_delete(zManFile);
163 free(zManFile);
164 }
165 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
166 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
167 file_delete(zManFile);
168 free(zManFile);
169 }
170 }
171
172 }
@@ -203,11 +203,11 @@
203 db_must_be_within_tree();
204 db_begin_transaction();
205 forceFlag = find_option("force","f",0)!=0;
206 keepFlag = find_option("keep",0,0)!=0;
207 latestFlag = find_option("latest",0,0)!=0;
208 promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;
209 if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
210 usage("VERSION|--latest ?--force? ?--keep?");
211 }
212 if( !forceFlag && unsaved_changes()==1 ){
213 fossil_fatal("there are unsaved changes in the current checkout");
@@ -252,14 +252,14 @@
252 db_multi_exec("DELETE FROM vmerge");
253 if( !keepFlag && db_get_boolean("repo-cksum",1) ){
254 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
255 vfile_aggregate_checksum_disk(vid, &cksum2);
256 if( blob_compare(&cksum1, &cksum2) ){
257 fossil_print("WARNING: manifest checksum does not agree with disk\n");
258 }
259 if( blob_size(&cksum1b) && blob_compare(&cksum1, &cksum1b) ){
260 fossil_print("WARNING: manifest checksum does not agree with manifest\n");
261 }
262 }
263 db_end_transaction(0);
264 }
265
@@ -271,11 +271,11 @@
271 int i;
272 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
273 if( manifestOnly==0 || zReserved[0]=='m' ){
274 char *z;
275 z = mprintf("%s%s", g.zLocalRoot, zReserved);
276 file_delete(z);
277 free(z);
278 }
279 }
280 }
281
282
+6 -6
--- src/checkout.c
+++ src/checkout.c
@@ -157,16 +157,16 @@
157157
free(zManFile);
158158
blob_reset(&hash);
159159
}else{
160160
if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
161161
zManFile = mprintf("%smanifest", g.zLocalRoot);
162
- unlink(zManFile);
162
+ file_delete(zManFile);
163163
free(zManFile);
164164
}
165165
if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
166166
zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
167
- unlink(zManFile);
167
+ file_delete(zManFile);
168168
free(zManFile);
169169
}
170170
}
171171
172172
}
@@ -203,11 +203,11 @@
203203
db_must_be_within_tree();
204204
db_begin_transaction();
205205
forceFlag = find_option("force","f",0)!=0;
206206
keepFlag = find_option("keep",0,0)!=0;
207207
latestFlag = find_option("latest",0,0)!=0;
208
- promptFlag = find_option("prompt",0,0)!=0; /* Prompt user before overwrite */
208
+ promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;
209209
if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
210210
usage("VERSION|--latest ?--force? ?--keep?");
211211
}
212212
if( !forceFlag && unsaved_changes()==1 ){
213213
fossil_fatal("there are unsaved changes in the current checkout");
@@ -252,14 +252,14 @@
252252
db_multi_exec("DELETE FROM vmerge");
253253
if( !keepFlag && db_get_boolean("repo-cksum",1) ){
254254
vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
255255
vfile_aggregate_checksum_disk(vid, &cksum2);
256256
if( blob_compare(&cksum1, &cksum2) ){
257
- printf("WARNING: manifest checksum does not agree with disk\n");
257
+ fossil_print("WARNING: manifest checksum does not agree with disk\n");
258258
}
259259
if( blob_size(&cksum1b) && blob_compare(&cksum1, &cksum1b) ){
260
- printf("WARNING: manifest checksum does not agree with manifest\n");
260
+ fossil_print("WARNING: manifest checksum does not agree with manifest\n");
261261
}
262262
}
263263
db_end_transaction(0);
264264
}
265265
@@ -271,11 +271,11 @@
271271
int i;
272272
for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
273273
if( manifestOnly==0 || zReserved[0]=='m' ){
274274
char *z;
275275
z = mprintf("%s%s", g.zLocalRoot, zReserved);
276
- unlink(z);
276
+ file_delete(z);
277277
free(z);
278278
}
279279
}
280280
}
281281
282282
--- src/checkout.c
+++ src/checkout.c
@@ -157,16 +157,16 @@
157 free(zManFile);
158 blob_reset(&hash);
159 }else{
160 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
161 zManFile = mprintf("%smanifest", g.zLocalRoot);
162 unlink(zManFile);
163 free(zManFile);
164 }
165 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
166 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
167 unlink(zManFile);
168 free(zManFile);
169 }
170 }
171
172 }
@@ -203,11 +203,11 @@
203 db_must_be_within_tree();
204 db_begin_transaction();
205 forceFlag = find_option("force","f",0)!=0;
206 keepFlag = find_option("keep",0,0)!=0;
207 latestFlag = find_option("latest",0,0)!=0;
208 promptFlag = find_option("prompt",0,0)!=0; /* Prompt user before overwrite */
209 if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
210 usage("VERSION|--latest ?--force? ?--keep?");
211 }
212 if( !forceFlag && unsaved_changes()==1 ){
213 fossil_fatal("there are unsaved changes in the current checkout");
@@ -252,14 +252,14 @@
252 db_multi_exec("DELETE FROM vmerge");
253 if( !keepFlag && db_get_boolean("repo-cksum",1) ){
254 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
255 vfile_aggregate_checksum_disk(vid, &cksum2);
256 if( blob_compare(&cksum1, &cksum2) ){
257 printf("WARNING: manifest checksum does not agree with disk\n");
258 }
259 if( blob_size(&cksum1b) && blob_compare(&cksum1, &cksum1b) ){
260 printf("WARNING: manifest checksum does not agree with manifest\n");
261 }
262 }
263 db_end_transaction(0);
264 }
265
@@ -271,11 +271,11 @@
271 int i;
272 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
273 if( manifestOnly==0 || zReserved[0]=='m' ){
274 char *z;
275 z = mprintf("%s%s", g.zLocalRoot, zReserved);
276 unlink(z);
277 free(z);
278 }
279 }
280 }
281
282
--- src/checkout.c
+++ src/checkout.c
@@ -157,16 +157,16 @@
157 free(zManFile);
158 blob_reset(&hash);
159 }else{
160 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){
161 zManFile = mprintf("%smanifest", g.zLocalRoot);
162 file_delete(zManFile);
163 free(zManFile);
164 }
165 if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){
166 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
167 file_delete(zManFile);
168 free(zManFile);
169 }
170 }
171
172 }
@@ -203,11 +203,11 @@
203 db_must_be_within_tree();
204 db_begin_transaction();
205 forceFlag = find_option("force","f",0)!=0;
206 keepFlag = find_option("keep",0,0)!=0;
207 latestFlag = find_option("latest",0,0)!=0;
208 promptFlag = find_option("prompt",0,0)!=0 || forceFlag==0;
209 if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
210 usage("VERSION|--latest ?--force? ?--keep?");
211 }
212 if( !forceFlag && unsaved_changes()==1 ){
213 fossil_fatal("there are unsaved changes in the current checkout");
@@ -252,14 +252,14 @@
252 db_multi_exec("DELETE FROM vmerge");
253 if( !keepFlag && db_get_boolean("repo-cksum",1) ){
254 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
255 vfile_aggregate_checksum_disk(vid, &cksum2);
256 if( blob_compare(&cksum1, &cksum2) ){
257 fossil_print("WARNING: manifest checksum does not agree with disk\n");
258 }
259 if( blob_size(&cksum1b) && blob_compare(&cksum1, &cksum1b) ){
260 fossil_print("WARNING: manifest checksum does not agree with manifest\n");
261 }
262 }
263 db_end_transaction(0);
264 }
265
@@ -271,11 +271,11 @@
271 int i;
272 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
273 if( manifestOnly==0 || zReserved[0]=='m' ){
274 char *z;
275 z = mprintf("%s%s", g.zLocalRoot, zReserved);
276 file_delete(z);
277 free(z);
278 }
279 }
280 }
281
282
+2 -2
--- src/clearsign.c
+++ src/clearsign.c
@@ -52,11 +52,11 @@
5252
}else{
5353
if( pOut!=pIn ){
5454
blob_copy(pOut, pIn);
5555
}
5656
}
57
- unlink(zOut);
58
- unlink(zIn);
57
+ file_delete(zOut);
58
+ file_delete(zIn);
5959
free(zOut);
6060
free(zIn);
6161
return rc;
6262
}
6363
--- src/clearsign.c
+++ src/clearsign.c
@@ -52,11 +52,11 @@
52 }else{
53 if( pOut!=pIn ){
54 blob_copy(pOut, pIn);
55 }
56 }
57 unlink(zOut);
58 unlink(zIn);
59 free(zOut);
60 free(zIn);
61 return rc;
62 }
63
--- src/clearsign.c
+++ src/clearsign.c
@@ -52,11 +52,11 @@
52 }else{
53 if( pOut!=pIn ){
54 blob_copy(pOut, pIn);
55 }
56 }
57 file_delete(zOut);
58 file_delete(zIn);
59 free(zOut);
60 free(zIn);
61 return rc;
62 }
63
+12 -12
--- src/clone.c
+++ src/clone.c
@@ -64,14 +64,14 @@
6464
file_copy(g.urlName, g.argv[3]);
6565
db_close(1);
6666
db_open_repository(g.argv[3]);
6767
db_record_repository_filename(g.argv[3]);
6868
db_multi_exec(
69
- "REPLACE INTO config(name,value)"
70
- " VALUES('server-code', lower(hex(randomblob(20))));"
71
- "REPLACE INTO config(name,value)"
72
- " VALUES('last-sync-url', '%q');",
69
+ "REPLACE INTO config(name,value,mtime)"
70
+ " VALUES('server-code', lower(hex(randomblob(20))),now());"
71
+ "REPLACE INTO config(name,value,mtime)"
72
+ " VALUES('last-sync-url', '%q',now());",
7373
g.urlCanonical
7474
);
7575
db_multi_exec(
7676
"DELETE FROM blob WHERE rid IN private;"
7777
"DELETE FROM delta wHERE rid IN private;"
@@ -80,11 +80,11 @@
8080
shun_artifacts();
8181
g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
8282
if( g.zLogin==0 ){
8383
db_create_default_users(1,zDefaultUser);
8484
}
85
- printf("Repository cloned into %s\n", g.argv[3]);
85
+ fossil_print("Repository cloned into %s\n", g.argv[3]);
8686
}else{
8787
db_create_repository(g.argv[3]);
8888
db_open_repository(g.argv[3]);
8989
db_begin_transaction();
9090
db_record_repository_filename(g.argv[3]);
@@ -92,12 +92,12 @@
9292
user_select();
9393
db_set("content-schema", CONTENT_SCHEMA, 0);
9494
db_set("aux-schema", AUX_SCHEMA, 0);
9595
db_set("last-sync-url", g.argv[2], 0);
9696
db_multi_exec(
97
- "REPLACE INTO config(name,value)"
98
- " VALUES('server-code', lower(hex(randomblob(20))));"
97
+ "REPLACE INTO config(name,value,mtime)"
98
+ " VALUES('server-code', lower(hex(randomblob(20))), now());"
9999
);
100100
url_enable_proxy(0);
101101
url_get_password_if_needed();
102102
g.xlinkClusterOnly = 1;
103103
nErr = client_sync(0,0,1,bPrivate,CONFIGSET_ALL,0);
@@ -104,19 +104,19 @@
104104
g.xlinkClusterOnly = 0;
105105
verify_cancel();
106106
db_end_transaction(0);
107107
db_close(1);
108108
if( nErr ){
109
- unlink(g.argv[3]);
109
+ file_delete(g.argv[3]);
110110
fossil_fatal("server returned an error - clone aborted");
111111
}
112112
db_open_repository(g.argv[3]);
113113
}
114114
db_begin_transaction();
115
- printf("Rebuilding repository meta-data...\n");
115
+ fossil_print("Rebuilding repository meta-data...\n");
116116
rebuild_db(0, 1, 0);
117
- printf("project-id: %s\n", db_get("project-code", 0));
118
- printf("server-id: %s\n", db_get("server-code", 0));
117
+ fossil_print("project-id: %s\n", db_get("project-code", 0));
118
+ fossil_print("server-id: %s\n", db_get("server-code", 0));
119119
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
120
- printf("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
120
+ fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
121121
db_end_transaction(0);
122122
}
123123
--- src/clone.c
+++ src/clone.c
@@ -64,14 +64,14 @@
64 file_copy(g.urlName, g.argv[3]);
65 db_close(1);
66 db_open_repository(g.argv[3]);
67 db_record_repository_filename(g.argv[3]);
68 db_multi_exec(
69 "REPLACE INTO config(name,value)"
70 " VALUES('server-code', lower(hex(randomblob(20))));"
71 "REPLACE INTO config(name,value)"
72 " VALUES('last-sync-url', '%q');",
73 g.urlCanonical
74 );
75 db_multi_exec(
76 "DELETE FROM blob WHERE rid IN private;"
77 "DELETE FROM delta wHERE rid IN private;"
@@ -80,11 +80,11 @@
80 shun_artifacts();
81 g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
82 if( g.zLogin==0 ){
83 db_create_default_users(1,zDefaultUser);
84 }
85 printf("Repository cloned into %s\n", g.argv[3]);
86 }else{
87 db_create_repository(g.argv[3]);
88 db_open_repository(g.argv[3]);
89 db_begin_transaction();
90 db_record_repository_filename(g.argv[3]);
@@ -92,12 +92,12 @@
92 user_select();
93 db_set("content-schema", CONTENT_SCHEMA, 0);
94 db_set("aux-schema", AUX_SCHEMA, 0);
95 db_set("last-sync-url", g.argv[2], 0);
96 db_multi_exec(
97 "REPLACE INTO config(name,value)"
98 " VALUES('server-code', lower(hex(randomblob(20))));"
99 );
100 url_enable_proxy(0);
101 url_get_password_if_needed();
102 g.xlinkClusterOnly = 1;
103 nErr = client_sync(0,0,1,bPrivate,CONFIGSET_ALL,0);
@@ -104,19 +104,19 @@
104 g.xlinkClusterOnly = 0;
105 verify_cancel();
106 db_end_transaction(0);
107 db_close(1);
108 if( nErr ){
109 unlink(g.argv[3]);
110 fossil_fatal("server returned an error - clone aborted");
111 }
112 db_open_repository(g.argv[3]);
113 }
114 db_begin_transaction();
115 printf("Rebuilding repository meta-data...\n");
116 rebuild_db(0, 1, 0);
117 printf("project-id: %s\n", db_get("project-code", 0));
118 printf("server-id: %s\n", db_get("server-code", 0));
119 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
120 printf("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
121 db_end_transaction(0);
122 }
123
--- src/clone.c
+++ src/clone.c
@@ -64,14 +64,14 @@
64 file_copy(g.urlName, g.argv[3]);
65 db_close(1);
66 db_open_repository(g.argv[3]);
67 db_record_repository_filename(g.argv[3]);
68 db_multi_exec(
69 "REPLACE INTO config(name,value,mtime)"
70 " VALUES('server-code', lower(hex(randomblob(20))),now());"
71 "REPLACE INTO config(name,value,mtime)"
72 " VALUES('last-sync-url', '%q',now());",
73 g.urlCanonical
74 );
75 db_multi_exec(
76 "DELETE FROM blob WHERE rid IN private;"
77 "DELETE FROM delta wHERE rid IN private;"
@@ -80,11 +80,11 @@
80 shun_artifacts();
81 g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
82 if( g.zLogin==0 ){
83 db_create_default_users(1,zDefaultUser);
84 }
85 fossil_print("Repository cloned into %s\n", g.argv[3]);
86 }else{
87 db_create_repository(g.argv[3]);
88 db_open_repository(g.argv[3]);
89 db_begin_transaction();
90 db_record_repository_filename(g.argv[3]);
@@ -92,12 +92,12 @@
92 user_select();
93 db_set("content-schema", CONTENT_SCHEMA, 0);
94 db_set("aux-schema", AUX_SCHEMA, 0);
95 db_set("last-sync-url", g.argv[2], 0);
96 db_multi_exec(
97 "REPLACE INTO config(name,value,mtime)"
98 " VALUES('server-code', lower(hex(randomblob(20))), now());"
99 );
100 url_enable_proxy(0);
101 url_get_password_if_needed();
102 g.xlinkClusterOnly = 1;
103 nErr = client_sync(0,0,1,bPrivate,CONFIGSET_ALL,0);
@@ -104,19 +104,19 @@
104 g.xlinkClusterOnly = 0;
105 verify_cancel();
106 db_end_transaction(0);
107 db_close(1);
108 if( nErr ){
109 file_delete(g.argv[3]);
110 fossil_fatal("server returned an error - clone aborted");
111 }
112 db_open_repository(g.argv[3]);
113 }
114 db_begin_transaction();
115 fossil_print("Rebuilding repository meta-data...\n");
116 rebuild_db(0, 1, 0);
117 fossil_print("project-id: %s\n", db_get("project-code", 0));
118 fossil_print("server-id: %s\n", db_get("server-code", 0));
119 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
120 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
121 db_end_transaction(0);
122 }
123
+12 -12
--- src/clone.c
+++ src/clone.c
@@ -64,14 +64,14 @@
6464
file_copy(g.urlName, g.argv[3]);
6565
db_close(1);
6666
db_open_repository(g.argv[3]);
6767
db_record_repository_filename(g.argv[3]);
6868
db_multi_exec(
69
- "REPLACE INTO config(name,value)"
70
- " VALUES('server-code', lower(hex(randomblob(20))));"
71
- "REPLACE INTO config(name,value)"
72
- " VALUES('last-sync-url', '%q');",
69
+ "REPLACE INTO config(name,value,mtime)"
70
+ " VALUES('server-code', lower(hex(randomblob(20))),now());"
71
+ "REPLACE INTO config(name,value,mtime)"
72
+ " VALUES('last-sync-url', '%q',now());",
7373
g.urlCanonical
7474
);
7575
db_multi_exec(
7676
"DELETE FROM blob WHERE rid IN private;"
7777
"DELETE FROM delta wHERE rid IN private;"
@@ -80,11 +80,11 @@
8080
shun_artifacts();
8181
g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
8282
if( g.zLogin==0 ){
8383
db_create_default_users(1,zDefaultUser);
8484
}
85
- printf("Repository cloned into %s\n", g.argv[3]);
85
+ fossil_print("Repository cloned into %s\n", g.argv[3]);
8686
}else{
8787
db_create_repository(g.argv[3]);
8888
db_open_repository(g.argv[3]);
8989
db_begin_transaction();
9090
db_record_repository_filename(g.argv[3]);
@@ -92,12 +92,12 @@
9292
user_select();
9393
db_set("content-schema", CONTENT_SCHEMA, 0);
9494
db_set("aux-schema", AUX_SCHEMA, 0);
9595
db_set("last-sync-url", g.argv[2], 0);
9696
db_multi_exec(
97
- "REPLACE INTO config(name,value)"
98
- " VALUES('server-code', lower(hex(randomblob(20))));"
97
+ "REPLACE INTO config(name,value,mtime)"
98
+ " VALUES('server-code', lower(hex(randomblob(20))), now());"
9999
);
100100
url_enable_proxy(0);
101101
url_get_password_if_needed();
102102
g.xlinkClusterOnly = 1;
103103
nErr = client_sync(0,0,1,bPrivate,CONFIGSET_ALL,0);
@@ -104,19 +104,19 @@
104104
g.xlinkClusterOnly = 0;
105105
verify_cancel();
106106
db_end_transaction(0);
107107
db_close(1);
108108
if( nErr ){
109
- unlink(g.argv[3]);
109
+ file_delete(g.argv[3]);
110110
fossil_fatal("server returned an error - clone aborted");
111111
}
112112
db_open_repository(g.argv[3]);
113113
}
114114
db_begin_transaction();
115
- printf("Rebuilding repository meta-data...\n");
115
+ fossil_print("Rebuilding repository meta-data...\n");
116116
rebuild_db(0, 1, 0);
117
- printf("project-id: %s\n", db_get("project-code", 0));
118
- printf("server-id: %s\n", db_get("server-code", 0));
117
+ fossil_print("project-id: %s\n", db_get("project-code", 0));
118
+ fossil_print("server-id: %s\n", db_get("server-code", 0));
119119
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
120
- printf("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
120
+ fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
121121
db_end_transaction(0);
122122
}
123123
--- src/clone.c
+++ src/clone.c
@@ -64,14 +64,14 @@
64 file_copy(g.urlName, g.argv[3]);
65 db_close(1);
66 db_open_repository(g.argv[3]);
67 db_record_repository_filename(g.argv[3]);
68 db_multi_exec(
69 "REPLACE INTO config(name,value)"
70 " VALUES('server-code', lower(hex(randomblob(20))));"
71 "REPLACE INTO config(name,value)"
72 " VALUES('last-sync-url', '%q');",
73 g.urlCanonical
74 );
75 db_multi_exec(
76 "DELETE FROM blob WHERE rid IN private;"
77 "DELETE FROM delta wHERE rid IN private;"
@@ -80,11 +80,11 @@
80 shun_artifacts();
81 g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
82 if( g.zLogin==0 ){
83 db_create_default_users(1,zDefaultUser);
84 }
85 printf("Repository cloned into %s\n", g.argv[3]);
86 }else{
87 db_create_repository(g.argv[3]);
88 db_open_repository(g.argv[3]);
89 db_begin_transaction();
90 db_record_repository_filename(g.argv[3]);
@@ -92,12 +92,12 @@
92 user_select();
93 db_set("content-schema", CONTENT_SCHEMA, 0);
94 db_set("aux-schema", AUX_SCHEMA, 0);
95 db_set("last-sync-url", g.argv[2], 0);
96 db_multi_exec(
97 "REPLACE INTO config(name,value)"
98 " VALUES('server-code', lower(hex(randomblob(20))));"
99 );
100 url_enable_proxy(0);
101 url_get_password_if_needed();
102 g.xlinkClusterOnly = 1;
103 nErr = client_sync(0,0,1,bPrivate,CONFIGSET_ALL,0);
@@ -104,19 +104,19 @@
104 g.xlinkClusterOnly = 0;
105 verify_cancel();
106 db_end_transaction(0);
107 db_close(1);
108 if( nErr ){
109 unlink(g.argv[3]);
110 fossil_fatal("server returned an error - clone aborted");
111 }
112 db_open_repository(g.argv[3]);
113 }
114 db_begin_transaction();
115 printf("Rebuilding repository meta-data...\n");
116 rebuild_db(0, 1, 0);
117 printf("project-id: %s\n", db_get("project-code", 0));
118 printf("server-id: %s\n", db_get("server-code", 0));
119 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
120 printf("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
121 db_end_transaction(0);
122 }
123
--- src/clone.c
+++ src/clone.c
@@ -64,14 +64,14 @@
64 file_copy(g.urlName, g.argv[3]);
65 db_close(1);
66 db_open_repository(g.argv[3]);
67 db_record_repository_filename(g.argv[3]);
68 db_multi_exec(
69 "REPLACE INTO config(name,value,mtime)"
70 " VALUES('server-code', lower(hex(randomblob(20))),now());"
71 "REPLACE INTO config(name,value,mtime)"
72 " VALUES('last-sync-url', '%q',now());",
73 g.urlCanonical
74 );
75 db_multi_exec(
76 "DELETE FROM blob WHERE rid IN private;"
77 "DELETE FROM delta wHERE rid IN private;"
@@ -80,11 +80,11 @@
80 shun_artifacts();
81 g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'");
82 if( g.zLogin==0 ){
83 db_create_default_users(1,zDefaultUser);
84 }
85 fossil_print("Repository cloned into %s\n", g.argv[3]);
86 }else{
87 db_create_repository(g.argv[3]);
88 db_open_repository(g.argv[3]);
89 db_begin_transaction();
90 db_record_repository_filename(g.argv[3]);
@@ -92,12 +92,12 @@
92 user_select();
93 db_set("content-schema", CONTENT_SCHEMA, 0);
94 db_set("aux-schema", AUX_SCHEMA, 0);
95 db_set("last-sync-url", g.argv[2], 0);
96 db_multi_exec(
97 "REPLACE INTO config(name,value,mtime)"
98 " VALUES('server-code', lower(hex(randomblob(20))), now());"
99 );
100 url_enable_proxy(0);
101 url_get_password_if_needed();
102 g.xlinkClusterOnly = 1;
103 nErr = client_sync(0,0,1,bPrivate,CONFIGSET_ALL,0);
@@ -104,19 +104,19 @@
104 g.xlinkClusterOnly = 0;
105 verify_cancel();
106 db_end_transaction(0);
107 db_close(1);
108 if( nErr ){
109 file_delete(g.argv[3]);
110 fossil_fatal("server returned an error - clone aborted");
111 }
112 db_open_repository(g.argv[3]);
113 }
114 db_begin_transaction();
115 fossil_print("Rebuilding repository meta-data...\n");
116 rebuild_db(0, 1, 0);
117 fossil_print("project-id: %s\n", db_get("project-code", 0));
118 fossil_print("server-id: %s\n", db_get("server-code", 0));
119 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
120 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
121 db_end_transaction(0);
122 }
123
+6 -6
--- src/comformat.c
+++ src/comformat.c
@@ -41,11 +41,11 @@
4141
4242
for(;;){
4343
while( fossil_isspace(zText[0]) ){ zText++; }
4444
if( zText[0]==0 ){
4545
if( doIndent==0 ){
46
- printf("\n");
46
+ fossil_print("\n");
4747
lineCnt = 1;
4848
}
4949
return lineCnt;
5050
}
5151
for(sk=si=i=k=0; zText[i] && k<tlen; i++){
@@ -64,23 +64,23 @@
6464
}
6565
k++;
6666
}
6767
}
6868
if( doIndent ){
69
- printf("%*s", indent, "");
69
+ fossil_print("%*s", indent, "");
7070
}
7171
doIndent = 1;
7272
if( sk>0 && zText[i] ){
7373
zText += si;
7474
zBuf[sk++] = '\n';
7575
zBuf[sk] = 0;
76
- printf("%s", zBuf);
76
+ fossil_print("%s", zBuf);
7777
}else{
7878
zText += i;
7979
zBuf[k++] = '\n';
8080
zBuf[k] = 0;
81
- printf("%s", zBuf);
81
+ fossil_print("%s", zBuf);
8282
}
8383
lineCnt++;
8484
}
8585
}
8686
@@ -93,8 +93,8 @@
9393
int indent;
9494
if( g.argc!=4 ){
9595
usage("PREFIX TEXT");
9696
}
9797
indent = strlen(g.argv[2]) + 1;
98
- printf("%s ", g.argv[2]);
99
- printf("(%d lines output)\n", comment_print(g.argv[3], indent, 79));
98
+ fossil_print("%s ", g.argv[2]);
99
+ fossil_print("(%d lines output)\n", comment_print(g.argv[3], indent, 79));
100100
}
101101
--- src/comformat.c
+++ src/comformat.c
@@ -41,11 +41,11 @@
41
42 for(;;){
43 while( fossil_isspace(zText[0]) ){ zText++; }
44 if( zText[0]==0 ){
45 if( doIndent==0 ){
46 printf("\n");
47 lineCnt = 1;
48 }
49 return lineCnt;
50 }
51 for(sk=si=i=k=0; zText[i] && k<tlen; i++){
@@ -64,23 +64,23 @@
64 }
65 k++;
66 }
67 }
68 if( doIndent ){
69 printf("%*s", indent, "");
70 }
71 doIndent = 1;
72 if( sk>0 && zText[i] ){
73 zText += si;
74 zBuf[sk++] = '\n';
75 zBuf[sk] = 0;
76 printf("%s", zBuf);
77 }else{
78 zText += i;
79 zBuf[k++] = '\n';
80 zBuf[k] = 0;
81 printf("%s", zBuf);
82 }
83 lineCnt++;
84 }
85 }
86
@@ -93,8 +93,8 @@
93 int indent;
94 if( g.argc!=4 ){
95 usage("PREFIX TEXT");
96 }
97 indent = strlen(g.argv[2]) + 1;
98 printf("%s ", g.argv[2]);
99 printf("(%d lines output)\n", comment_print(g.argv[3], indent, 79));
100 }
101
--- src/comformat.c
+++ src/comformat.c
@@ -41,11 +41,11 @@
41
42 for(;;){
43 while( fossil_isspace(zText[0]) ){ zText++; }
44 if( zText[0]==0 ){
45 if( doIndent==0 ){
46 fossil_print("\n");
47 lineCnt = 1;
48 }
49 return lineCnt;
50 }
51 for(sk=si=i=k=0; zText[i] && k<tlen; i++){
@@ -64,23 +64,23 @@
64 }
65 k++;
66 }
67 }
68 if( doIndent ){
69 fossil_print("%*s", indent, "");
70 }
71 doIndent = 1;
72 if( sk>0 && zText[i] ){
73 zText += si;
74 zBuf[sk++] = '\n';
75 zBuf[sk] = 0;
76 fossil_print("%s", zBuf);
77 }else{
78 zText += i;
79 zBuf[k++] = '\n';
80 zBuf[k] = 0;
81 fossil_print("%s", zBuf);
82 }
83 lineCnt++;
84 }
85 }
86
@@ -93,8 +93,8 @@
93 int indent;
94 if( g.argc!=4 ){
95 usage("PREFIX TEXT");
96 }
97 indent = strlen(g.argv[2]) + 1;
98 fossil_print("%s ", g.argv[2]);
99 fossil_print("(%d lines output)\n", comment_print(g.argv[3], indent, 79));
100 }
101
+7 -15
--- src/config.h
+++ src/config.h
@@ -82,10 +82,17 @@
8282
8383
#ifndef _RC_COMPILE_
8484
8585
#include "sqlite3.h"
8686
87
+/*
88
+** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
89
+*/
90
+#if defined(__sun__) || defined(sun)
91
+ #define getpass getpassphrase
92
+#endif
93
+
8794
/*
8895
** Typedef for a 64-bit integer
8996
*/
9097
typedef sqlite3_int64 i64;
9198
typedef sqlite3_uint64 u64;
@@ -123,21 +130,6 @@
123130
#else /* Generates a warning - but it always works */
124131
# define FOSSIL_INT_TO_PTR(X) ((void*)(X))
125132
# define FOSSIL_PTR_TO_INT(X) ((int)(X))
126133
#endif
127134
128
-
129
-/* Unset the following to disable internationalization code. */
130
-#ifndef FOSSIL_I18N
131
-# define FOSSIL_I18N 1
132
-#endif
133
-
134
-#if FOSSIL_I18N
135
-# include <locale.h>
136
-# include <langinfo.h>
137
-#endif
138
-#ifndef CODESET
139
-# undef FOSSIL_I18N
140
-# define FOSSIL_I18N 0
141
-#endif
142
-
143135
#endif /* _RC_COMPILE_ */
144136
--- src/config.h
+++ src/config.h
@@ -82,10 +82,17 @@
82
83 #ifndef _RC_COMPILE_
84
85 #include "sqlite3.h"
86
 
 
 
 
 
 
 
87 /*
88 ** Typedef for a 64-bit integer
89 */
90 typedef sqlite3_int64 i64;
91 typedef sqlite3_uint64 u64;
@@ -123,21 +130,6 @@
123 #else /* Generates a warning - but it always works */
124 # define FOSSIL_INT_TO_PTR(X) ((void*)(X))
125 # define FOSSIL_PTR_TO_INT(X) ((int)(X))
126 #endif
127
128
129 /* Unset the following to disable internationalization code. */
130 #ifndef FOSSIL_I18N
131 # define FOSSIL_I18N 1
132 #endif
133
134 #if FOSSIL_I18N
135 # include <locale.h>
136 # include <langinfo.h>
137 #endif
138 #ifndef CODESET
139 # undef FOSSIL_I18N
140 # define FOSSIL_I18N 0
141 #endif
142
143 #endif /* _RC_COMPILE_ */
144
--- src/config.h
+++ src/config.h
@@ -82,10 +82,17 @@
82
83 #ifndef _RC_COMPILE_
84
85 #include "sqlite3.h"
86
87 /*
88 ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
89 */
90 #if defined(__sun__) || defined(sun)
91 #define getpass getpassphrase
92 #endif
93
94 /*
95 ** Typedef for a 64-bit integer
96 */
97 typedef sqlite3_int64 i64;
98 typedef sqlite3_uint64 u64;
@@ -123,21 +130,6 @@
130 #else /* Generates a warning - but it always works */
131 # define FOSSIL_INT_TO_PTR(X) ((void*)(X))
132 # define FOSSIL_PTR_TO_INT(X) ((int)(X))
133 #endif
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135 #endif /* _RC_COMPILE_ */
136
+479 -91
--- src/configure.c
+++ src/configure.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2008 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -14,10 +14,11 @@
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
1818
** This file contains code used to manage repository configurations.
19
+**
1920
** By "responsitory configure" we mean the local state of a repository
2021
** distinct from the versioned files.
2122
*/
2223
#include "config.h"
2324
#include "configure.h"
@@ -26,18 +27,21 @@
2627
#if INTERFACE
2728
/*
2829
** Configuration transfers occur in groups. These are the allowed
2930
** groupings:
3031
*/
31
-#define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
32
-#define CONFIGSET_TKT 0x000002 /* Ticket configuration */
33
-#define CONFIGSET_PROJ 0x000004 /* Project name */
34
-#define CONFIGSET_SHUN 0x000008 /* Shun settings */
35
-#define CONFIGSET_USER 0x000010 /* The USER table */
36
-#define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
37
-
38
-#define CONFIGSET_ALL 0xffffff /* Everything */
32
+#define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
33
+#define CONFIGSET_TKT 0x000002 /* Ticket configuration */
34
+#define CONFIGSET_PROJ 0x000004 /* Project name */
35
+#define CONFIGSET_SHUN 0x000008 /* Shun settings */
36
+#define CONFIGSET_USER 0x000010 /* The USER table */
37
+#define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
38
+
39
+#define CONFIGSET_ALL 0x0000ff /* Everything */
40
+
41
+#define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
42
+#define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
3943
4044
#endif /* INTERFACE */
4145
4246
/*
4347
** Names of the configuration sets
@@ -45,17 +49,17 @@
4549
static struct {
4650
const char *zName; /* Name of the configuration set */
4751
int groupMask; /* Mask for that configuration set */
4852
const char *zHelp; /* What it does */
4953
} aGroupName[] = {
50
- { "email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
51
- { "project", CONFIGSET_PROJ, "Project name and description" },
52
- { "skin", CONFIGSET_SKIN, "Web interface apparance settings" },
53
- { "shun", CONFIGSET_SHUN, "List of shunned artifacts" },
54
- { "ticket", CONFIGSET_TKT, "Ticket setup", },
55
- { "user", CONFIGSET_USER, "Users and privilege settings" },
56
- { "all", CONFIGSET_ALL, "All of the above" },
54
+ { "/email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
55
+ { "/project", CONFIGSET_PROJ, "Project name and description" },
56
+ { "/skin", CONFIGSET_SKIN, "Web interface apparance settings" },
57
+ { "/shun", CONFIGSET_SHUN, "List of shunned artifacts" },
58
+ { "/ticket", CONFIGSET_TKT, "Ticket setup", },
59
+ { "/user", CONFIGSET_USER, "Users and privilege settings" },
60
+ { "/all", CONFIGSET_ALL, "All of the above" },
5761
};
5862
5963
6064
/*
6165
** The following is a list of settings that we are willing to
@@ -105,28 +109,52 @@
105109
const char *configure_first_name(int iMask){
106110
iConfig = 0;
107111
return configure_next_name(iMask);
108112
}
109113
const char *configure_next_name(int iMask){
110
- while( iConfig<count(aConfig) ){
111
- if( aConfig[iConfig].groupMask & iMask ){
112
- return aConfig[iConfig++].zName;
113
- }else{
114
- iConfig++;
114
+ if( iMask & CONFIGSET_OLDFORMAT ){
115
+ while( iConfig<count(aConfig) ){
116
+ if( aConfig[iConfig].groupMask & iMask ){
117
+ return aConfig[iConfig++].zName;
118
+ }else{
119
+ iConfig++;
120
+ }
121
+ }
122
+ }else{
123
+ if( iConfig==0 && (iMask & CONFIGSET_ALL)==CONFIGSET_ALL ){
124
+ iConfig = count(aGroupName);
125
+ return "/all";
126
+ }
127
+ while( iConfig<count(aGroupName)-1 ){
128
+ if( aGroupName[iConfig].groupMask & iMask ){
129
+ return aGroupName[iConfig++].zName;
130
+ }else{
131
+ iConfig++;
132
+ }
115133
}
116134
}
117135
return 0;
118136
}
119137
120138
/*
121139
** Return the mask for the named configuration parameter if it can be
122140
** safely exported. Return 0 if the parameter is not safe to export.
141
+**
142
+** "Safe" in the previous paragraph means the permission is created to
143
+** export the property. In other words, the requesting side has presented
144
+** login credentials and has sufficient capabilities to access the requested
145
+** information.
123146
*/
124147
int configure_is_exportable(const char *zName){
125148
int i;
149
+ int n = strlen(zName);
150
+ if( n>2 && zName[0]=='\'' && zName[n-1]=='\'' ){
151
+ zName++;
152
+ n -= 2;
153
+ }
126154
for(i=0; i<count(aConfig); i++){
127
- if( fossil_strcmp(zName, aConfig[i].zName)==0 ){
155
+ if( memcmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
128156
int m = aConfig[i].groupMask;
129157
if( !g.okAdmin ){
130158
m &= ~CONFIGSET_USER;
131159
}
132160
if( !g.okRdAddr ){
@@ -194,38 +222,39 @@
194222
}
195223
196224
/*
197225
** Two SQL functions:
198226
**
199
-** flag_test(int)
200
-** flag_clear(int)
227
+** config_is_reset(int)
228
+** config_reset(int)
201229
**
202
-** The flag_test() function takes the integer valued argument and
203
-** ANDs it against the static variable "flag_value" below. The
204
-** function returns TRUE or false depending on the result. The
205
-** flag_clear() function masks off the bits from "flag_value" that
230
+** The config_is_reset() function takes the integer valued argument and
231
+** ANDs it against the static variable "configHasBeenReset" below. The
232
+** function returns TRUE or FALSE depending on the result depending on
233
+** whether or not the corresponding configuration table has been reset. The
234
+** config_reset() function adds the bits to "configHasBeenReset" that
206235
** are given in the argument.
207236
**
208237
** These functions are used below in the WHEN clause of a trigger to
209238
** get the trigger to fire exactly once.
210239
*/
211
-static int flag_value = 0xffff;
212
-static void flag_test_function(
240
+static int configHasBeenReset = 0;
241
+static void config_is_reset_function(
213242
sqlite3_context *context,
214243
int argc,
215244
sqlite3_value **argv
216245
){
217246
int m = sqlite3_value_int(argv[0]);
218
- sqlite3_result_int(context, (flag_value&m)!=0 );
247
+ sqlite3_result_int(context, (configHasBeenReset&m)!=0 );
219248
}
220
-static void flag_clear_function(
249
+static void config_reset_function(
221250
sqlite3_context *context,
222251
int argc,
223252
sqlite3_value **argv
224253
){
225254
int m = sqlite3_value_int(argv[0]);
226
- flag_value &= ~m;
255
+ configHasBeenReset |= m;
227256
}
228257
229258
/*
230259
** Create the temporary _xfer_reportfmt and _xfer_user tables that are
231260
** necessary in order to evalute the SQL text generated by the
@@ -255,12 +284,14 @@
255284
@ ipaddr TEXT, -- IP address for which cookie is valid
256285
@ cexpire DATETIME, -- Time when cookie expires
257286
@ info TEXT, -- contact information
258287
@ photo BLOB -- JPEG image of this user
259288
@ );
260
- @ INSERT INTO _xfer_reportfmt SELECT * FROM reportfmt;
261
- @ INSERT INTO _xfer_user SELECT * FROM user;
289
+ @ INSERT INTO _xfer_reportfmt
290
+ @ SELECT rn,owner,title,cols,sqlcode FROM reportfmt;
291
+ @ INSERT INTO _xfer_user
292
+ @ SELECT uid,login,pw,cap,cookie,ipaddr,cexpire,info,photo FROM user;
262293
;
263294
db_multi_exec(zSQL1);
264295
265296
/* When the replace flag is set, add triggers that run the first time
266297
** that new data is seen. The triggers run only once and delete all the
@@ -267,30 +298,30 @@
267298
** existing data.
268299
*/
269300
if( replaceFlag ){
270301
static const char zSQL2[] =
271302
@ CREATE TRIGGER _xfer_r1 BEFORE INSERT ON _xfer_reportfmt
272
- @ WHEN flag_test(1) BEGIN
303
+ @ WHEN NOT config_is_reset(2) BEGIN
273304
@ DELETE FROM _xfer_reportfmt;
274
- @ SELECT flag_clear(1);
305
+ @ SELECT config_reset(2);
275306
@ END;
276307
@ CREATE TRIGGER _xfer_r2 BEFORE INSERT ON _xfer_user
277
- @ WHEN flag_test(2) BEGIN
308
+ @ WHEN NOT config_is_reset(16) BEGIN
278309
@ DELETE FROM _xfer_user;
279
- @ SELECT flag_clear(2);
310
+ @ SELECT config_reset(16);
280311
@ END;
281312
@ CREATE TEMP TRIGGER _xfer_r3 BEFORE INSERT ON shun
282
- @ WHEN flag_test(4) BEGIN
313
+ @ WHEN NOT config_is_reset(8) BEGIN
283314
@ DELETE FROM shun;
284
- @ SELECT flag_clear(4);
315
+ @ SELECT config_reset(8);
285316
@ END;
286317
;
287
- sqlite3_create_function(g.db, "flag_test", 1, SQLITE_UTF8, 0,
288
- flag_test_function, 0, 0);
289
- sqlite3_create_function(g.db, "flag_clear", 1, SQLITE_UTF8, 0,
290
- flag_clear_function, 0, 0);
291
- flag_value = 0xffff;
318
+ sqlite3_create_function(g.db, "config_is_reset", 1, SQLITE_UTF8, 0,
319
+ config_is_reset_function, 0, 0);
320
+ sqlite3_create_function(g.db, "config_reset", 1, SQLITE_UTF8, 0,
321
+ config_reset_function, 0, 0);
322
+ configHasBeenReset = 0;
292323
db_multi_exec(zSQL2);
293324
}
294325
}
295326
296327
/*
@@ -306,66 +337,390 @@
306337
@ DROP TABLE _xfer_user;
307338
@ DROP TABLE _xfer_reportfmt;
308339
;
309340
db_multi_exec(zSQL);
310341
}
342
+
343
+/*
344
+** Return true if z[] is not a "safe" SQL token. A safe token is one of:
345
+**
346
+** * A string literal
347
+** * A blob literal
348
+** * An integer literal (no floating point)
349
+** * NULL
350
+*/
351
+static int safeSql(const char *z){
352
+ int i;
353
+ if( z==0 || z[0]==0 ) return 0;
354
+ if( (z[0]=='x' || z[0]=='X') && z[1]=='\'' ) z++;
355
+ if( z[0]=='\'' ){
356
+ for(i=1; z[i]; i++){
357
+ if( z[i]=='\'' ){
358
+ i++;
359
+ if( z[i]=='\'' ){ continue; }
360
+ return z[i]==0;
361
+ }
362
+ }
363
+ return 0;
364
+ }else{
365
+ char c;
366
+ for(i=0; (c = z[i])!=0; i++){
367
+ if( !fossil_isalnum(c) ) return 0;
368
+ }
369
+ }
370
+ return 1;
371
+}
372
+
373
+/*
374
+** Return true if z[] consists of nothing but digits
375
+*/
376
+static int safeInt(const char *z){
377
+ int i;
378
+ if( z==0 || z[0]==0 ) return 0;
379
+ for(i=0; fossil_isdigit(z[i]); i++){}
380
+ return z[i]==0;
381
+}
382
+
383
+/*
384
+** Process a single "config" card received from the other side of a
385
+** sync session.
386
+**
387
+** Mask consists of one or more CONFIGSET_* values ORed together, to
388
+** designate what types of configuration we are allowed to receive.
389
+**
390
+** NEW FORMAT:
391
+**
392
+** zName is one of "/config", "/user", "/shun", "/reportfmt", or "/concealed".
393
+** zName indicates the table that holds the configuration information being
394
+** transferred. pContent is a string that consist of alternating Fossil
395
+** and SQL tokens. The First token is a timestamp in seconds since 1970.
396
+** The second token is a primary key for the table identified by zName. If
397
+** The entry with the corresponding primary key exists and has a more recent
398
+** mtime, then nothing happens. If the entry does not exist or if it has
399
+** an older mtime, then the content described by subsequent token pairs is
400
+** inserted. The first element of each token pair is a column name and
401
+** the second is its value.
402
+**
403
+** In overview, we have:
404
+**
405
+** NAME CONTENT
406
+** ------- -----------------------------------------------------------
407
+** /config $MTIME $NAME value $VALUE
408
+** /user $MTIME $LOGIN pw $VALUE cap $VALUE info $VALUE photo $VALUE
409
+** /shun $MTIME $UUID scom $VALUE
410
+** /reportfmt $MTIME $TITLE owner $VALUE cols $VALUE sqlcode $VALUE
411
+** /concealed $MTIME $HASH content $VALUE
412
+**
413
+** OLD FORMAT:
414
+**
415
+** The old format is retained for backwards compatiblity, but is deprecated.
416
+** The cutover from old format to new was on 2011-04-25. After sufficient
417
+** time has passed, support for the old format will be removed.
418
+**
419
+** zName is either the NAME of an element of the CONFIG table, or else
420
+** one of the special names "@shun", "@reportfmt", "@user", or "@concealed".
421
+** If zName is a CONFIG table name, then CONTENT replaces (overwrites) the
422
+** element in the CONFIG table. For one of the @-labels, CONTENT is raw
423
+** SQL that is evaluated. Note that the raw SQL in CONTENT might not
424
+** insert directly into the target table but might instead use a proxy
425
+** table like _fer_reportfmt or _xfer_user. Such tables must be created
426
+** ahead of time using configure_prepare_to_receive(). Then after multiple
427
+** calls to this routine, configure_finalize_receive() to transfer the
428
+** information received into the true target table.
429
+*/
430
+void configure_receive(const char *zName, Blob *pContent, int groupMask){
431
+ if( zName[0]=='/' ){
432
+ /* The new format */
433
+ char *azToken[12];
434
+ int nToken = 0;
435
+ int ii, jj;
436
+ int thisMask;
437
+ Blob name, value, sql;
438
+ static const struct receiveType {
439
+ const char *zName;
440
+ const char *zPrimKey;
441
+ int nField;
442
+ const char *azField[4];
443
+ } aType[] = {
444
+ { "/config", "name", 1, { "value", 0, 0, 0 } },
445
+ { "@user", "login", 4, { "pw", "cap", "info", "photo" } },
446
+ { "@shun", "uuid", 1, { "scom", 0, 0, 0 } },
447
+ { "@reportfmt", "title", 3, { "owner", "cols", "sqlcode", 0 } },
448
+ { "@concealed", "hash", 1, { "content", 0, 0, 0 } },
449
+ };
450
+ for(ii=0; ii<count(aType); ii++){
451
+ if( fossil_strcmp(&aType[ii].zName[1],&zName[1])==0 ) break;
452
+ }
453
+ if( ii>=count(aType) ) return;
454
+ while( blob_token(pContent, &name) && blob_sqltoken(pContent, &value) ){
455
+ char *z = blob_terminate(&name);
456
+ if( !safeSql(z) ) return;
457
+ if( nToken>0 ){
458
+ for(jj=0; jj<aType[ii].nField; jj++){
459
+ if( fossil_strcmp(aType[ii].azField[jj], z)==0 ) break;
460
+ }
461
+ if( jj>=aType[ii].nField ) continue;
462
+ }else{
463
+ if( !safeInt(z) ) return;
464
+ }
465
+ azToken[nToken++] = z;
466
+ azToken[nToken++] = z = blob_terminate(&value);
467
+ if( !safeSql(z) ) return;
468
+ if( nToken>=count(azToken) ) break;
469
+ }
470
+ if( nToken<2 ) return;
471
+ if( aType[ii].zName[0]=='/' ){
472
+ thisMask = configure_is_exportable(azToken[1]);
473
+ }else{
474
+ thisMask = configure_is_exportable(aType[ii].zName);
475
+ }
476
+ if( (thisMask & groupMask)==0 ) return;
477
+
478
+ blob_zero(&sql);
479
+ if( groupMask & CONFIGSET_OVERWRITE ){
480
+ if( (thisMask & configHasBeenReset)==0 && aType[ii].zName[0]!='/' ){
481
+ db_multi_exec("DELETE FROM %s", &aType[ii].zName[1]);
482
+ configHasBeenReset |= thisMask;
483
+ }
484
+ blob_append(&sql, "REPLACE INTO ", -1);
485
+ }else{
486
+ blob_append(&sql, "INSERT OR IGNORE INTO ", -1);
487
+ }
488
+ blob_appendf(&sql, "%s(%s, mtime", &zName[1], aType[ii].zPrimKey);
489
+ for(jj=2; jj<nToken; jj+=2){
490
+ blob_appendf(&sql, ",%s", azToken[jj]);
491
+ }
492
+ blob_appendf(&sql,") VALUES(%s,%s", azToken[1], azToken[0]);
493
+ for(jj=2; jj<nToken; jj+=2){
494
+ blob_appendf(&sql, ",%s", azToken[jj+1]);
495
+ }
496
+ db_multi_exec("%s)", blob_str(&sql));
497
+ if( db_changes()==0 ){
498
+ blob_reset(&sql);
499
+ blob_appendf(&sql, "UPDATE %s SET mtime=%s", &zName[1], azToken[0]);
500
+ for(jj=2; jj<nToken; jj+=2){
501
+ blob_appendf(&sql, ", %s=%s", azToken[jj], azToken[jj+1]);
502
+ }
503
+ blob_appendf(&sql, " WHERE %s=%s AND mtime<%s",
504
+ aType[ii].zPrimKey, azToken[1], azToken[0]);
505
+ db_multi_exec("%s", blob_str(&sql));
506
+ }
507
+ blob_reset(&sql);
508
+ }else{
509
+ /* Otherwise, the old format */
510
+ if( (configure_is_exportable(zName) & groupMask)==0 ) return;
511
+ if( strcmp(zName, "logo-image")==0 ){
512
+ Stmt ins;
513
+ db_prepare(&ins,
514
+ "REPLACE INTO config(name, value, mtime) VALUES(:name, :value, now())"
515
+ );
516
+ db_bind_text(&ins, ":name", zName);
517
+ db_bind_blob(&ins, ":value", pContent);
518
+ db_step(&ins);
519
+ db_finalize(&ins);
520
+ }else if( zName[0]=='@' ){
521
+ /* Notice that we are evaluating arbitrary SQL received from the
522
+ ** client. But this can only happen if the client has authenticated
523
+ ** as an administrator, so presumably we trust the client at this
524
+ ** point.
525
+ */
526
+ db_multi_exec("%s", blob_str(pContent));
527
+ }else{
528
+ db_multi_exec(
529
+ "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
530
+ zName, blob_str(pContent)
531
+ );
532
+ }
533
+ }
534
+}
535
+
536
+/*
537
+** Process a file full of "config" cards.
538
+*/
539
+void configure_receive_all(Blob *pIn, int groupMask){
540
+ Blob line;
541
+ int nToken;
542
+ int size;
543
+ Blob aToken[4];
544
+
545
+ configHasBeenReset = 0;
546
+ while( blob_line(pIn, &line) ){
547
+ if( blob_buffer(&line)[0]=='#' ) continue;
548
+ nToken = blob_tokenize(&line, aToken, count(aToken));
549
+ if( blob_eq(&aToken[0],"config")
550
+ && nToken==3
551
+ && blob_is_int(&aToken[2], &size)
552
+ ){
553
+ const char *zName = blob_str(&aToken[1]);
554
+ Blob content;
555
+ blob_zero(&content);
556
+ blob_extract(pIn, size, &content);
557
+ g.okAdmin = g.okRdAddr = 1;
558
+ configure_receive(zName, &content, groupMask);
559
+ blob_reset(&content);
560
+ blob_seek(pIn, 1, BLOB_SEEK_CUR);
561
+ }
562
+ }
563
+}
564
+
565
+
566
+/*
567
+** Send "config" cards using the new format for all elements of a group
568
+** that have recently changed.
569
+**
570
+** Output goes into pOut. The groupMask identifies the group(s) to be sent.
571
+** Send only entries whose timestamp is later than or equal to iStart.
572
+**
573
+** Return the number of cards sent.
574
+*/
575
+int configure_send_group(
576
+ Blob *pOut, /* Write output here */
577
+ int groupMask, /* Mask of groups to be send */
578
+ sqlite3_int64 iStart /* Only write values changed since this time */
579
+){
580
+ Stmt q;
581
+ Blob rec;
582
+ int ii;
583
+ int nCard = 0;
584
+
585
+ blob_zero(&rec);
586
+ if( groupMask & CONFIGSET_SHUN ){
587
+ db_prepare(&q, "SELECT mtime, quote(uuid), quote(scom) FROM shun"
588
+ " WHERE mtime>=%lld", iStart);
589
+ while( db_step(&q)==SQLITE_ROW ){
590
+ blob_appendf(&rec,"%s %s scom %s",
591
+ db_column_text(&q, 0),
592
+ db_column_text(&q, 1),
593
+ db_column_text(&q, 2)
594
+ );
595
+ blob_appendf(pOut, "config /shun %d\n%s\n",
596
+ blob_size(&rec), blob_str(&rec));
597
+ nCard++;
598
+ blob_reset(&rec);
599
+ }
600
+ db_finalize(&q);
601
+ }
602
+ if( groupMask & CONFIGSET_USER ){
603
+ db_prepare(&q, "SELECT mtime, quote(login), quote(pw), quote(cap),"
604
+ " quote(info), quote(photo) FROM user"
605
+ " WHERE mtime>=%lld", iStart);
606
+ while( db_step(&q)==SQLITE_ROW ){
607
+ blob_appendf(&rec,"%s %s pw %s cap %s info %s photo %s",
608
+ db_column_text(&q, 0),
609
+ db_column_text(&q, 1),
610
+ db_column_text(&q, 2),
611
+ db_column_text(&q, 3),
612
+ db_column_text(&q, 4),
613
+ db_column_text(&q, 5)
614
+ );
615
+ blob_appendf(pOut, "config /user %d\n%s\n",
616
+ blob_size(&rec), blob_str(&rec));
617
+ nCard++;
618
+ blob_reset(&rec);
619
+ }
620
+ db_finalize(&q);
621
+ }
622
+ if( groupMask & CONFIGSET_TKT ){
623
+ db_prepare(&q, "SELECT mtime, quote(title), quote(owner), quote(cols),"
624
+ " quote(sqlcode) FROM reportfmt"
625
+ " WHERE mtime>=%lld", iStart);
626
+ while( db_step(&q)==SQLITE_ROW ){
627
+ blob_appendf(&rec,"%s %s owner %s cols %s sqlcode %s",
628
+ db_column_text(&q, 0),
629
+ db_column_text(&q, 1),
630
+ db_column_text(&q, 2),
631
+ db_column_text(&q, 3),
632
+ db_column_text(&q, 4)
633
+ );
634
+ blob_appendf(pOut, "config /reportfmt %d\n%s\n",
635
+ blob_size(&rec), blob_str(&rec));
636
+ nCard++;
637
+ blob_reset(&rec);
638
+ }
639
+ db_finalize(&q);
640
+ }
641
+ if( groupMask & CONFIGSET_ADDR ){
642
+ db_prepare(&q, "SELECT mtime, quote(hash), quote(content) FROM concealed"
643
+ " WHERE mtime>=%lld", iStart);
644
+ while( db_step(&q)==SQLITE_ROW ){
645
+ blob_appendf(&rec,"%s %s content %s",
646
+ db_column_text(&q, 0),
647
+ db_column_text(&q, 1),
648
+ db_column_text(&q, 2)
649
+ );
650
+ blob_appendf(pOut, "config /concealed %d\n%s\n",
651
+ blob_size(&rec), blob_str(&rec));
652
+ nCard++;
653
+ blob_reset(&rec);
654
+ }
655
+ db_finalize(&q);
656
+ }
657
+ db_prepare(&q, "SELECT mtime, quote(name), quote(value) FROM config"
658
+ " WHERE name=:name AND mtime>=%lld", iStart);
659
+ for(ii=0; ii<count(aConfig); ii++){
660
+ if( (aConfig[ii].groupMask & groupMask)!=0 && aConfig[ii].zName[0]!='@' ){
661
+ db_bind_text(&q, ":name", aConfig[ii].zName);
662
+ while( db_step(&q)==SQLITE_ROW ){
663
+ blob_appendf(&rec,"%s %s value %s",
664
+ db_column_text(&q, 0),
665
+ db_column_text(&q, 1),
666
+ db_column_text(&q, 2)
667
+ );
668
+ blob_appendf(pOut, "config /config %d\n%s\n",
669
+ blob_size(&rec), blob_str(&rec));
670
+ nCard++;
671
+ blob_reset(&rec);
672
+ }
673
+ db_reset(&q);
674
+ }
675
+ }
676
+ db_finalize(&q);
677
+ return nCard;
678
+}
311679
312680
/*
313681
** Identify a configuration group by name. Return its mask.
314682
** Throw an error if no match.
315683
*/
316
-static int find_area(const char *z){
684
+int configure_name_to_mask(const char *z, int notFoundIsFatal){
317685
int i;
318686
int n = strlen(z);
319687
for(i=0; i<count(aGroupName); i++){
320
- if( strncmp(z, aGroupName[i].zName, n)==0 ){
688
+ if( strncmp(z, &aGroupName[i].zName[1], n)==0 ){
321689
return aGroupName[i].groupMask;
322690
}
323691
}
324
- printf("Available configuration areas:\n");
325
- for(i=0; i<count(aGroupName); i++){
326
- printf(" %-10s %s\n", aGroupName[i].zName, aGroupName[i].zHelp);
692
+ if( notFoundIsFatal ){
693
+ fossil_print("Available configuration areas:\n");
694
+ for(i=0; i<count(aGroupName); i++){
695
+ fossil_print(" %-10s %s\n", &aGroupName[i].zName[1], aGroupName[i].zHelp);
696
+ }
697
+ fossil_fatal("no such configuration area: \"%s\"", z);
327698
}
328
- fossil_fatal("no such configuration area: \"%s\"", z);
329699
return 0;
330700
}
331701
332702
/*
333703
** Write SQL text into file zFilename that will restore the configuration
334704
** area identified by mask to its current state from any other state.
335705
*/
336706
static void export_config(
337
- int mask, /* Mask indicating which configuration to export */
707
+ int groupMask, /* Mask indicating which configuration to export */
338708
const char *zMask, /* Name of the configuration */
709
+ sqlite3_int64 iStart, /* Start date */
339710
const char *zFilename /* Write into this file */
340711
){
341
- int i;
342712
Blob out;
343713
blob_zero(&out);
344
- blob_appendf(&out,
345
- "-- The \"%s\" configuration exported from\n"
346
- "-- repository \"%s\"\n"
347
- "-- on %s\n",
714
+ blob_appendf(&out,
715
+ "# The \"%s\" configuration exported from\n"
716
+ "# repository \"%s\"\n"
717
+ "# on %s\n",
348718
zMask, g.zRepositoryName,
349719
db_text(0, "SELECT datetime('now')")
350720
);
351
- for(i=0; i<count(aConfig); i++){
352
- if( (aConfig[i].groupMask & mask)!=0 ){
353
- const char *zName = aConfig[i].zName;
354
- if( zName[0]!='@' ){
355
- char *zValue = db_text(0,
356
- "SELECT quote(value) FROM config WHERE name=%Q", zName);
357
- if( zValue ){
358
- blob_appendf(&out,"REPLACE INTO config VALUES(%Q,%s);\n",
359
- zName, zValue);
360
- }
361
- free(zValue);
362
- }else{
363
- configure_render_special_name(zName, &out);
364
- }
365
- }
366
- }
721
+ configure_send_group(&out, groupMask, iStart);
367722
blob_write_to_file(&out, zFilename);
368723
blob_reset(&out);
369724
}
370725
371726
@@ -395,25 +750,31 @@
395750
**
396751
** %fossil configuration pull AREA ?URL?
397752
**
398753
** Pull and install the configuration from a different server
399754
** identified by URL. If no URL is specified, then the default
400
-** server is used.
755
+** server is used. Use the --legacy option for the older protocol
756
+** (when talking to servers compiled prior to 2011-04-27.) Use
757
+** the --overwrite flag to completely replace local settings with
758
+** content received from URL.
401759
**
402760
** %fossil configuration push AREA ?URL?
403761
**
404762
** Push the local configuration into the remote server identified
405763
** by URL. Admin privilege is required on the remote server for
406
-** this to work.
764
+** this to work. When the same record exists both locally and on
765
+** the remote end, the one that was most recently changed wins.
766
+** Use the --legacy flag when talking to holder servers.
407767
**
408768
** %fossil configuration reset AREA
409769
**
410770
** Restore the configuration to the default. AREA as above.
411771
**
412
-** WARNING: Do not import, merge, or pull configurations from an untrusted
413
-** source. The inbound configuration is not checked for safety and can
414
-** introduce security vulnerabilities.
772
+** %fossil configuration sync AREA ?URL?
773
+**
774
+** Synchronize configuration changes in the local repository with
775
+** the remote repository at URL.
415776
**
416777
**
417778
** SUMMARY: fossil configure METHOD ... ?-R|--repository REPOSITORY?
418779
** Where: METHOD = export, import, merge, pull, push or reset
419780
**
@@ -438,36 +799,59 @@
438799
db_find_and_open_repository(0, 0);
439800
zMethod = g.argv[2];
440801
n = strlen(zMethod);
441802
if( strncmp(zMethod, "export", n)==0 ){
442803
int mask;
804
+ const char *zSince = find_option("since",0,1);
805
+ sqlite3_int64 iStart;
443806
if( g.argc!=5 ){
444807
usage("export AREA FILENAME");
445808
}
446
- mask = find_area(g.argv[3]);
447
- export_config(mask, g.argv[3], g.argv[4]);
809
+ mask = configure_name_to_mask(g.argv[3], 1);
810
+ if( zSince ){
811
+ iStart = db_multi_exec(
812
+ "SELECT coalesce(strftime('%%s',%Q),strftime('%%s','now',%Q))+0",
813
+ zSince, zSince
814
+ );
815
+ }else{
816
+ iStart = 0;
817
+ }
818
+ export_config(mask, g.argv[3], iStart, g.argv[4]);
448819
}else
449820
if( strncmp(zMethod, "import", n)==0
450821
|| strncmp(zMethod, "merge", n)==0 ){
451822
Blob in;
823
+ int groupMask;
452824
if( g.argc!=4 ) usage(mprintf("%s FILENAME",zMethod));
453825
blob_read_from_file(&in, g.argv[3]);
454826
db_begin_transaction();
455
- configure_prepare_to_receive(zMethod[0]=='i');
456
- db_multi_exec("%s", blob_str(&in));
457
- configure_finalize_receive();
827
+ if( zMethod[0]=='i' ){
828
+ groupMask = CONFIGSET_ALL | CONFIGSET_OVERWRITE;
829
+ }else{
830
+ groupMask = CONFIGSET_ALL;
831
+ }
832
+ configure_receive_all(&in, groupMask);
458833
db_end_transaction(0);
459834
}else
460
- if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
835
+ if( strncmp(zMethod, "pull", n)==0
836
+ || strncmp(zMethod, "push", n)==0
837
+ || strncmp(zMethod, "sync", n)==0
838
+ ){
461839
int mask;
462840
const char *zServer;
463841
const char *zPw;
842
+ int legacyFlag = 0;
843
+ int overwriteFlag = 0;
844
+ if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
845
+ if( strncmp(zMethod,"pull",n)==0 ){
846
+ overwriteFlag = find_option("overwrite",0,0)!=0;
847
+ }
464848
url_proxy_options();
465849
if( g.argc!=4 && g.argc!=5 ){
466850
usage("pull AREA ?URL?");
467851
}
468
- mask = find_area(g.argv[3]);
852
+ mask = configure_name_to_mask(g.argv[3], 1);
469853
if( g.argc==5 ){
470854
zServer = g.argv[4];
471855
zPw = 0;
472856
g.dontKeepUrl = 1;
473857
}else{
@@ -479,25 +863,29 @@
479863
}
480864
url_parse(zServer);
481865
if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
482866
user_select();
483867
url_enable_proxy("via proxy: ");
868
+ if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
869
+ if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
484870
if( strncmp(zMethod, "push", n)==0 ){
485871
client_sync(0,0,0,0,0,mask);
486
- }else{
872
+ }else if( strncmp(zMethod, "pull", n)==0 ){
487873
client_sync(0,0,0,0,mask,0);
874
+ }else{
875
+ client_sync(0,0,0,0,mask,mask);
488876
}
489877
}else
490878
if( strncmp(zMethod, "reset", n)==0 ){
491879
int mask, i;
492880
char *zBackup;
493881
if( g.argc!=4 ) usage("reset AREA");
494
- mask = find_area(g.argv[3]);
882
+ mask = configure_name_to_mask(g.argv[3], 1);
495883
zBackup = db_text(0,
496884
"SELECT strftime('config-backup-%%Y%%m%%d%%H%%M%%f','now')");
497885
db_begin_transaction();
498
- export_config(mask, g.argv[3], zBackup);
886
+ export_config(mask, g.argv[3], 0, zBackup);
499887
for(i=0; i<count(aConfig); i++){
500888
const char *zName = aConfig[i].zName;
501889
if( (aConfig[i].groupMask & mask)==0 ) continue;
502890
if( zName[0]!='@' ){
503891
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -511,14 +899,14 @@
511899
}else if( fossil_strcmp(zName,"@reportfmt")==0 ){
512900
db_multi_exec("DELETE FROM reportfmt");
513901
}
514902
}
515903
db_end_transaction(0);
516
- printf("Configuration reset to factory defaults.\n");
517
- printf("To recover, use: %s %s import %s\n",
904
+ fossil_print("Configuration reset to factory defaults.\n");
905
+ fossil_print("To recover, use: %s %s import %s\n",
518906
fossil_nameofexe(), g.argv[1], zBackup);
519907
}else
520908
{
521909
fossil_fatal("METHOD should be one of:"
522910
" export import merge pull push reset");
523911
}
524912
}
525913
--- src/configure.c
+++ src/configure.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2008 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -14,10 +14,11 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to manage repository configurations.
 
19 ** By "responsitory configure" we mean the local state of a repository
20 ** distinct from the versioned files.
21 */
22 #include "config.h"
23 #include "configure.h"
@@ -26,18 +27,21 @@
26 #if INTERFACE
27 /*
28 ** Configuration transfers occur in groups. These are the allowed
29 ** groupings:
30 */
31 #define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
32 #define CONFIGSET_TKT 0x000002 /* Ticket configuration */
33 #define CONFIGSET_PROJ 0x000004 /* Project name */
34 #define CONFIGSET_SHUN 0x000008 /* Shun settings */
35 #define CONFIGSET_USER 0x000010 /* The USER table */
36 #define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
37
38 #define CONFIGSET_ALL 0xffffff /* Everything */
 
 
 
39
40 #endif /* INTERFACE */
41
42 /*
43 ** Names of the configuration sets
@@ -45,17 +49,17 @@
45 static struct {
46 const char *zName; /* Name of the configuration set */
47 int groupMask; /* Mask for that configuration set */
48 const char *zHelp; /* What it does */
49 } aGroupName[] = {
50 { "email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
51 { "project", CONFIGSET_PROJ, "Project name and description" },
52 { "skin", CONFIGSET_SKIN, "Web interface apparance settings" },
53 { "shun", CONFIGSET_SHUN, "List of shunned artifacts" },
54 { "ticket", CONFIGSET_TKT, "Ticket setup", },
55 { "user", CONFIGSET_USER, "Users and privilege settings" },
56 { "all", CONFIGSET_ALL, "All of the above" },
57 };
58
59
60 /*
61 ** The following is a list of settings that we are willing to
@@ -105,28 +109,52 @@
105 const char *configure_first_name(int iMask){
106 iConfig = 0;
107 return configure_next_name(iMask);
108 }
109 const char *configure_next_name(int iMask){
110 while( iConfig<count(aConfig) ){
111 if( aConfig[iConfig].groupMask & iMask ){
112 return aConfig[iConfig++].zName;
113 }else{
114 iConfig++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115 }
116 }
117 return 0;
118 }
119
120 /*
121 ** Return the mask for the named configuration parameter if it can be
122 ** safely exported. Return 0 if the parameter is not safe to export.
 
 
 
 
 
123 */
124 int configure_is_exportable(const char *zName){
125 int i;
 
 
 
 
 
126 for(i=0; i<count(aConfig); i++){
127 if( fossil_strcmp(zName, aConfig[i].zName)==0 ){
128 int m = aConfig[i].groupMask;
129 if( !g.okAdmin ){
130 m &= ~CONFIGSET_USER;
131 }
132 if( !g.okRdAddr ){
@@ -194,38 +222,39 @@
194 }
195
196 /*
197 ** Two SQL functions:
198 **
199 ** flag_test(int)
200 ** flag_clear(int)
201 **
202 ** The flag_test() function takes the integer valued argument and
203 ** ANDs it against the static variable "flag_value" below. The
204 ** function returns TRUE or false depending on the result. The
205 ** flag_clear() function masks off the bits from "flag_value" that
 
206 ** are given in the argument.
207 **
208 ** These functions are used below in the WHEN clause of a trigger to
209 ** get the trigger to fire exactly once.
210 */
211 static int flag_value = 0xffff;
212 static void flag_test_function(
213 sqlite3_context *context,
214 int argc,
215 sqlite3_value **argv
216 ){
217 int m = sqlite3_value_int(argv[0]);
218 sqlite3_result_int(context, (flag_value&m)!=0 );
219 }
220 static void flag_clear_function(
221 sqlite3_context *context,
222 int argc,
223 sqlite3_value **argv
224 ){
225 int m = sqlite3_value_int(argv[0]);
226 flag_value &= ~m;
227 }
228
229 /*
230 ** Create the temporary _xfer_reportfmt and _xfer_user tables that are
231 ** necessary in order to evalute the SQL text generated by the
@@ -255,12 +284,14 @@
255 @ ipaddr TEXT, -- IP address for which cookie is valid
256 @ cexpire DATETIME, -- Time when cookie expires
257 @ info TEXT, -- contact information
258 @ photo BLOB -- JPEG image of this user
259 @ );
260 @ INSERT INTO _xfer_reportfmt SELECT * FROM reportfmt;
261 @ INSERT INTO _xfer_user SELECT * FROM user;
 
 
262 ;
263 db_multi_exec(zSQL1);
264
265 /* When the replace flag is set, add triggers that run the first time
266 ** that new data is seen. The triggers run only once and delete all the
@@ -267,30 +298,30 @@
267 ** existing data.
268 */
269 if( replaceFlag ){
270 static const char zSQL2[] =
271 @ CREATE TRIGGER _xfer_r1 BEFORE INSERT ON _xfer_reportfmt
272 @ WHEN flag_test(1) BEGIN
273 @ DELETE FROM _xfer_reportfmt;
274 @ SELECT flag_clear(1);
275 @ END;
276 @ CREATE TRIGGER _xfer_r2 BEFORE INSERT ON _xfer_user
277 @ WHEN flag_test(2) BEGIN
278 @ DELETE FROM _xfer_user;
279 @ SELECT flag_clear(2);
280 @ END;
281 @ CREATE TEMP TRIGGER _xfer_r3 BEFORE INSERT ON shun
282 @ WHEN flag_test(4) BEGIN
283 @ DELETE FROM shun;
284 @ SELECT flag_clear(4);
285 @ END;
286 ;
287 sqlite3_create_function(g.db, "flag_test", 1, SQLITE_UTF8, 0,
288 flag_test_function, 0, 0);
289 sqlite3_create_function(g.db, "flag_clear", 1, SQLITE_UTF8, 0,
290 flag_clear_function, 0, 0);
291 flag_value = 0xffff;
292 db_multi_exec(zSQL2);
293 }
294 }
295
296 /*
@@ -306,66 +337,390 @@
306 @ DROP TABLE _xfer_user;
307 @ DROP TABLE _xfer_reportfmt;
308 ;
309 db_multi_exec(zSQL);
310 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
312 /*
313 ** Identify a configuration group by name. Return its mask.
314 ** Throw an error if no match.
315 */
316 static int find_area(const char *z){
317 int i;
318 int n = strlen(z);
319 for(i=0; i<count(aGroupName); i++){
320 if( strncmp(z, aGroupName[i].zName, n)==0 ){
321 return aGroupName[i].groupMask;
322 }
323 }
324 printf("Available configuration areas:\n");
325 for(i=0; i<count(aGroupName); i++){
326 printf(" %-10s %s\n", aGroupName[i].zName, aGroupName[i].zHelp);
 
 
 
327 }
328 fossil_fatal("no such configuration area: \"%s\"", z);
329 return 0;
330 }
331
332 /*
333 ** Write SQL text into file zFilename that will restore the configuration
334 ** area identified by mask to its current state from any other state.
335 */
336 static void export_config(
337 int mask, /* Mask indicating which configuration to export */
338 const char *zMask, /* Name of the configuration */
 
339 const char *zFilename /* Write into this file */
340 ){
341 int i;
342 Blob out;
343 blob_zero(&out);
344 blob_appendf(&out,
345 "-- The \"%s\" configuration exported from\n"
346 "-- repository \"%s\"\n"
347 "-- on %s\n",
348 zMask, g.zRepositoryName,
349 db_text(0, "SELECT datetime('now')")
350 );
351 for(i=0; i<count(aConfig); i++){
352 if( (aConfig[i].groupMask & mask)!=0 ){
353 const char *zName = aConfig[i].zName;
354 if( zName[0]!='@' ){
355 char *zValue = db_text(0,
356 "SELECT quote(value) FROM config WHERE name=%Q", zName);
357 if( zValue ){
358 blob_appendf(&out,"REPLACE INTO config VALUES(%Q,%s);\n",
359 zName, zValue);
360 }
361 free(zValue);
362 }else{
363 configure_render_special_name(zName, &out);
364 }
365 }
366 }
367 blob_write_to_file(&out, zFilename);
368 blob_reset(&out);
369 }
370
371
@@ -395,25 +750,31 @@
395 **
396 ** %fossil configuration pull AREA ?URL?
397 **
398 ** Pull and install the configuration from a different server
399 ** identified by URL. If no URL is specified, then the default
400 ** server is used.
 
 
 
401 **
402 ** %fossil configuration push AREA ?URL?
403 **
404 ** Push the local configuration into the remote server identified
405 ** by URL. Admin privilege is required on the remote server for
406 ** this to work.
 
 
407 **
408 ** %fossil configuration reset AREA
409 **
410 ** Restore the configuration to the default. AREA as above.
411 **
412 ** WARNING: Do not import, merge, or pull configurations from an untrusted
413 ** source. The inbound configuration is not checked for safety and can
414 ** introduce security vulnerabilities.
 
415 **
416 **
417 ** SUMMARY: fossil configure METHOD ... ?-R|--repository REPOSITORY?
418 ** Where: METHOD = export, import, merge, pull, push or reset
419 **
@@ -438,36 +799,59 @@
438 db_find_and_open_repository(0, 0);
439 zMethod = g.argv[2];
440 n = strlen(zMethod);
441 if( strncmp(zMethod, "export", n)==0 ){
442 int mask;
 
 
443 if( g.argc!=5 ){
444 usage("export AREA FILENAME");
445 }
446 mask = find_area(g.argv[3]);
447 export_config(mask, g.argv[3], g.argv[4]);
 
 
 
 
 
 
 
 
448 }else
449 if( strncmp(zMethod, "import", n)==0
450 || strncmp(zMethod, "merge", n)==0 ){
451 Blob in;
 
452 if( g.argc!=4 ) usage(mprintf("%s FILENAME",zMethod));
453 blob_read_from_file(&in, g.argv[3]);
454 db_begin_transaction();
455 configure_prepare_to_receive(zMethod[0]=='i');
456 db_multi_exec("%s", blob_str(&in));
457 configure_finalize_receive();
 
 
 
458 db_end_transaction(0);
459 }else
460 if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
 
 
 
461 int mask;
462 const char *zServer;
463 const char *zPw;
 
 
 
 
 
 
464 url_proxy_options();
465 if( g.argc!=4 && g.argc!=5 ){
466 usage("pull AREA ?URL?");
467 }
468 mask = find_area(g.argv[3]);
469 if( g.argc==5 ){
470 zServer = g.argv[4];
471 zPw = 0;
472 g.dontKeepUrl = 1;
473 }else{
@@ -479,25 +863,29 @@
479 }
480 url_parse(zServer);
481 if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
482 user_select();
483 url_enable_proxy("via proxy: ");
 
 
484 if( strncmp(zMethod, "push", n)==0 ){
485 client_sync(0,0,0,0,0,mask);
486 }else{
487 client_sync(0,0,0,0,mask,0);
 
 
488 }
489 }else
490 if( strncmp(zMethod, "reset", n)==0 ){
491 int mask, i;
492 char *zBackup;
493 if( g.argc!=4 ) usage("reset AREA");
494 mask = find_area(g.argv[3]);
495 zBackup = db_text(0,
496 "SELECT strftime('config-backup-%%Y%%m%%d%%H%%M%%f','now')");
497 db_begin_transaction();
498 export_config(mask, g.argv[3], zBackup);
499 for(i=0; i<count(aConfig); i++){
500 const char *zName = aConfig[i].zName;
501 if( (aConfig[i].groupMask & mask)==0 ) continue;
502 if( zName[0]!='@' ){
503 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -511,14 +899,14 @@
511 }else if( fossil_strcmp(zName,"@reportfmt")==0 ){
512 db_multi_exec("DELETE FROM reportfmt");
513 }
514 }
515 db_end_transaction(0);
516 printf("Configuration reset to factory defaults.\n");
517 printf("To recover, use: %s %s import %s\n",
518 fossil_nameofexe(), g.argv[1], zBackup);
519 }else
520 {
521 fossil_fatal("METHOD should be one of:"
522 " export import merge pull push reset");
523 }
524 }
525
--- src/configure.c
+++ src/configure.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2008 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -14,10 +14,11 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to manage repository configurations.
19 **
20 ** By "responsitory configure" we mean the local state of a repository
21 ** distinct from the versioned files.
22 */
23 #include "config.h"
24 #include "configure.h"
@@ -26,18 +27,21 @@
27 #if INTERFACE
28 /*
29 ** Configuration transfers occur in groups. These are the allowed
30 ** groupings:
31 */
32 #define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
33 #define CONFIGSET_TKT 0x000002 /* Ticket configuration */
34 #define CONFIGSET_PROJ 0x000004 /* Project name */
35 #define CONFIGSET_SHUN 0x000008 /* Shun settings */
36 #define CONFIGSET_USER 0x000010 /* The USER table */
37 #define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
38
39 #define CONFIGSET_ALL 0x0000ff /* Everything */
40
41 #define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
42 #define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
43
44 #endif /* INTERFACE */
45
46 /*
47 ** Names of the configuration sets
@@ -45,17 +49,17 @@
49 static struct {
50 const char *zName; /* Name of the configuration set */
51 int groupMask; /* Mask for that configuration set */
52 const char *zHelp; /* What it does */
53 } aGroupName[] = {
54 { "/email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
55 { "/project", CONFIGSET_PROJ, "Project name and description" },
56 { "/skin", CONFIGSET_SKIN, "Web interface apparance settings" },
57 { "/shun", CONFIGSET_SHUN, "List of shunned artifacts" },
58 { "/ticket", CONFIGSET_TKT, "Ticket setup", },
59 { "/user", CONFIGSET_USER, "Users and privilege settings" },
60 { "/all", CONFIGSET_ALL, "All of the above" },
61 };
62
63
64 /*
65 ** The following is a list of settings that we are willing to
@@ -105,28 +109,52 @@
109 const char *configure_first_name(int iMask){
110 iConfig = 0;
111 return configure_next_name(iMask);
112 }
113 const char *configure_next_name(int iMask){
114 if( iMask & CONFIGSET_OLDFORMAT ){
115 while( iConfig<count(aConfig) ){
116 if( aConfig[iConfig].groupMask & iMask ){
117 return aConfig[iConfig++].zName;
118 }else{
119 iConfig++;
120 }
121 }
122 }else{
123 if( iConfig==0 && (iMask & CONFIGSET_ALL)==CONFIGSET_ALL ){
124 iConfig = count(aGroupName);
125 return "/all";
126 }
127 while( iConfig<count(aGroupName)-1 ){
128 if( aGroupName[iConfig].groupMask & iMask ){
129 return aGroupName[iConfig++].zName;
130 }else{
131 iConfig++;
132 }
133 }
134 }
135 return 0;
136 }
137
138 /*
139 ** Return the mask for the named configuration parameter if it can be
140 ** safely exported. Return 0 if the parameter is not safe to export.
141 **
142 ** "Safe" in the previous paragraph means the permission is created to
143 ** export the property. In other words, the requesting side has presented
144 ** login credentials and has sufficient capabilities to access the requested
145 ** information.
146 */
147 int configure_is_exportable(const char *zName){
148 int i;
149 int n = strlen(zName);
150 if( n>2 && zName[0]=='\'' && zName[n-1]=='\'' ){
151 zName++;
152 n -= 2;
153 }
154 for(i=0; i<count(aConfig); i++){
155 if( memcmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
156 int m = aConfig[i].groupMask;
157 if( !g.okAdmin ){
158 m &= ~CONFIGSET_USER;
159 }
160 if( !g.okRdAddr ){
@@ -194,38 +222,39 @@
222 }
223
224 /*
225 ** Two SQL functions:
226 **
227 ** config_is_reset(int)
228 ** config_reset(int)
229 **
230 ** The config_is_reset() function takes the integer valued argument and
231 ** ANDs it against the static variable "configHasBeenReset" below. The
232 ** function returns TRUE or FALSE depending on the result depending on
233 ** whether or not the corresponding configuration table has been reset. The
234 ** config_reset() function adds the bits to "configHasBeenReset" that
235 ** are given in the argument.
236 **
237 ** These functions are used below in the WHEN clause of a trigger to
238 ** get the trigger to fire exactly once.
239 */
240 static int configHasBeenReset = 0;
241 static void config_is_reset_function(
242 sqlite3_context *context,
243 int argc,
244 sqlite3_value **argv
245 ){
246 int m = sqlite3_value_int(argv[0]);
247 sqlite3_result_int(context, (configHasBeenReset&m)!=0 );
248 }
249 static void config_reset_function(
250 sqlite3_context *context,
251 int argc,
252 sqlite3_value **argv
253 ){
254 int m = sqlite3_value_int(argv[0]);
255 configHasBeenReset |= m;
256 }
257
258 /*
259 ** Create the temporary _xfer_reportfmt and _xfer_user tables that are
260 ** necessary in order to evalute the SQL text generated by the
@@ -255,12 +284,14 @@
284 @ ipaddr TEXT, -- IP address for which cookie is valid
285 @ cexpire DATETIME, -- Time when cookie expires
286 @ info TEXT, -- contact information
287 @ photo BLOB -- JPEG image of this user
288 @ );
289 @ INSERT INTO _xfer_reportfmt
290 @ SELECT rn,owner,title,cols,sqlcode FROM reportfmt;
291 @ INSERT INTO _xfer_user
292 @ SELECT uid,login,pw,cap,cookie,ipaddr,cexpire,info,photo FROM user;
293 ;
294 db_multi_exec(zSQL1);
295
296 /* When the replace flag is set, add triggers that run the first time
297 ** that new data is seen. The triggers run only once and delete all the
@@ -267,30 +298,30 @@
298 ** existing data.
299 */
300 if( replaceFlag ){
301 static const char zSQL2[] =
302 @ CREATE TRIGGER _xfer_r1 BEFORE INSERT ON _xfer_reportfmt
303 @ WHEN NOT config_is_reset(2) BEGIN
304 @ DELETE FROM _xfer_reportfmt;
305 @ SELECT config_reset(2);
306 @ END;
307 @ CREATE TRIGGER _xfer_r2 BEFORE INSERT ON _xfer_user
308 @ WHEN NOT config_is_reset(16) BEGIN
309 @ DELETE FROM _xfer_user;
310 @ SELECT config_reset(16);
311 @ END;
312 @ CREATE TEMP TRIGGER _xfer_r3 BEFORE INSERT ON shun
313 @ WHEN NOT config_is_reset(8) BEGIN
314 @ DELETE FROM shun;
315 @ SELECT config_reset(8);
316 @ END;
317 ;
318 sqlite3_create_function(g.db, "config_is_reset", 1, SQLITE_UTF8, 0,
319 config_is_reset_function, 0, 0);
320 sqlite3_create_function(g.db, "config_reset", 1, SQLITE_UTF8, 0,
321 config_reset_function, 0, 0);
322 configHasBeenReset = 0;
323 db_multi_exec(zSQL2);
324 }
325 }
326
327 /*
@@ -306,66 +337,390 @@
337 @ DROP TABLE _xfer_user;
338 @ DROP TABLE _xfer_reportfmt;
339 ;
340 db_multi_exec(zSQL);
341 }
342
343 /*
344 ** Return true if z[] is not a "safe" SQL token. A safe token is one of:
345 **
346 ** * A string literal
347 ** * A blob literal
348 ** * An integer literal (no floating point)
349 ** * NULL
350 */
351 static int safeSql(const char *z){
352 int i;
353 if( z==0 || z[0]==0 ) return 0;
354 if( (z[0]=='x' || z[0]=='X') && z[1]=='\'' ) z++;
355 if( z[0]=='\'' ){
356 for(i=1; z[i]; i++){
357 if( z[i]=='\'' ){
358 i++;
359 if( z[i]=='\'' ){ continue; }
360 return z[i]==0;
361 }
362 }
363 return 0;
364 }else{
365 char c;
366 for(i=0; (c = z[i])!=0; i++){
367 if( !fossil_isalnum(c) ) return 0;
368 }
369 }
370 return 1;
371 }
372
373 /*
374 ** Return true if z[] consists of nothing but digits
375 */
376 static int safeInt(const char *z){
377 int i;
378 if( z==0 || z[0]==0 ) return 0;
379 for(i=0; fossil_isdigit(z[i]); i++){}
380 return z[i]==0;
381 }
382
383 /*
384 ** Process a single "config" card received from the other side of a
385 ** sync session.
386 **
387 ** Mask consists of one or more CONFIGSET_* values ORed together, to
388 ** designate what types of configuration we are allowed to receive.
389 **
390 ** NEW FORMAT:
391 **
392 ** zName is one of "/config", "/user", "/shun", "/reportfmt", or "/concealed".
393 ** zName indicates the table that holds the configuration information being
394 ** transferred. pContent is a string that consist of alternating Fossil
395 ** and SQL tokens. The First token is a timestamp in seconds since 1970.
396 ** The second token is a primary key for the table identified by zName. If
397 ** The entry with the corresponding primary key exists and has a more recent
398 ** mtime, then nothing happens. If the entry does not exist or if it has
399 ** an older mtime, then the content described by subsequent token pairs is
400 ** inserted. The first element of each token pair is a column name and
401 ** the second is its value.
402 **
403 ** In overview, we have:
404 **
405 ** NAME CONTENT
406 ** ------- -----------------------------------------------------------
407 ** /config $MTIME $NAME value $VALUE
408 ** /user $MTIME $LOGIN pw $VALUE cap $VALUE info $VALUE photo $VALUE
409 ** /shun $MTIME $UUID scom $VALUE
410 ** /reportfmt $MTIME $TITLE owner $VALUE cols $VALUE sqlcode $VALUE
411 ** /concealed $MTIME $HASH content $VALUE
412 **
413 ** OLD FORMAT:
414 **
415 ** The old format is retained for backwards compatiblity, but is deprecated.
416 ** The cutover from old format to new was on 2011-04-25. After sufficient
417 ** time has passed, support for the old format will be removed.
418 **
419 ** zName is either the NAME of an element of the CONFIG table, or else
420 ** one of the special names "@shun", "@reportfmt", "@user", or "@concealed".
421 ** If zName is a CONFIG table name, then CONTENT replaces (overwrites) the
422 ** element in the CONFIG table. For one of the @-labels, CONTENT is raw
423 ** SQL that is evaluated. Note that the raw SQL in CONTENT might not
424 ** insert directly into the target table but might instead use a proxy
425 ** table like _fer_reportfmt or _xfer_user. Such tables must be created
426 ** ahead of time using configure_prepare_to_receive(). Then after multiple
427 ** calls to this routine, configure_finalize_receive() to transfer the
428 ** information received into the true target table.
429 */
430 void configure_receive(const char *zName, Blob *pContent, int groupMask){
431 if( zName[0]=='/' ){
432 /* The new format */
433 char *azToken[12];
434 int nToken = 0;
435 int ii, jj;
436 int thisMask;
437 Blob name, value, sql;
438 static const struct receiveType {
439 const char *zName;
440 const char *zPrimKey;
441 int nField;
442 const char *azField[4];
443 } aType[] = {
444 { "/config", "name", 1, { "value", 0, 0, 0 } },
445 { "@user", "login", 4, { "pw", "cap", "info", "photo" } },
446 { "@shun", "uuid", 1, { "scom", 0, 0, 0 } },
447 { "@reportfmt", "title", 3, { "owner", "cols", "sqlcode", 0 } },
448 { "@concealed", "hash", 1, { "content", 0, 0, 0 } },
449 };
450 for(ii=0; ii<count(aType); ii++){
451 if( fossil_strcmp(&aType[ii].zName[1],&zName[1])==0 ) break;
452 }
453 if( ii>=count(aType) ) return;
454 while( blob_token(pContent, &name) && blob_sqltoken(pContent, &value) ){
455 char *z = blob_terminate(&name);
456 if( !safeSql(z) ) return;
457 if( nToken>0 ){
458 for(jj=0; jj<aType[ii].nField; jj++){
459 if( fossil_strcmp(aType[ii].azField[jj], z)==0 ) break;
460 }
461 if( jj>=aType[ii].nField ) continue;
462 }else{
463 if( !safeInt(z) ) return;
464 }
465 azToken[nToken++] = z;
466 azToken[nToken++] = z = blob_terminate(&value);
467 if( !safeSql(z) ) return;
468 if( nToken>=count(azToken) ) break;
469 }
470 if( nToken<2 ) return;
471 if( aType[ii].zName[0]=='/' ){
472 thisMask = configure_is_exportable(azToken[1]);
473 }else{
474 thisMask = configure_is_exportable(aType[ii].zName);
475 }
476 if( (thisMask & groupMask)==0 ) return;
477
478 blob_zero(&sql);
479 if( groupMask & CONFIGSET_OVERWRITE ){
480 if( (thisMask & configHasBeenReset)==0 && aType[ii].zName[0]!='/' ){
481 db_multi_exec("DELETE FROM %s", &aType[ii].zName[1]);
482 configHasBeenReset |= thisMask;
483 }
484 blob_append(&sql, "REPLACE INTO ", -1);
485 }else{
486 blob_append(&sql, "INSERT OR IGNORE INTO ", -1);
487 }
488 blob_appendf(&sql, "%s(%s, mtime", &zName[1], aType[ii].zPrimKey);
489 for(jj=2; jj<nToken; jj+=2){
490 blob_appendf(&sql, ",%s", azToken[jj]);
491 }
492 blob_appendf(&sql,") VALUES(%s,%s", azToken[1], azToken[0]);
493 for(jj=2; jj<nToken; jj+=2){
494 blob_appendf(&sql, ",%s", azToken[jj+1]);
495 }
496 db_multi_exec("%s)", blob_str(&sql));
497 if( db_changes()==0 ){
498 blob_reset(&sql);
499 blob_appendf(&sql, "UPDATE %s SET mtime=%s", &zName[1], azToken[0]);
500 for(jj=2; jj<nToken; jj+=2){
501 blob_appendf(&sql, ", %s=%s", azToken[jj], azToken[jj+1]);
502 }
503 blob_appendf(&sql, " WHERE %s=%s AND mtime<%s",
504 aType[ii].zPrimKey, azToken[1], azToken[0]);
505 db_multi_exec("%s", blob_str(&sql));
506 }
507 blob_reset(&sql);
508 }else{
509 /* Otherwise, the old format */
510 if( (configure_is_exportable(zName) & groupMask)==0 ) return;
511 if( strcmp(zName, "logo-image")==0 ){
512 Stmt ins;
513 db_prepare(&ins,
514 "REPLACE INTO config(name, value, mtime) VALUES(:name, :value, now())"
515 );
516 db_bind_text(&ins, ":name", zName);
517 db_bind_blob(&ins, ":value", pContent);
518 db_step(&ins);
519 db_finalize(&ins);
520 }else if( zName[0]=='@' ){
521 /* Notice that we are evaluating arbitrary SQL received from the
522 ** client. But this can only happen if the client has authenticated
523 ** as an administrator, so presumably we trust the client at this
524 ** point.
525 */
526 db_multi_exec("%s", blob_str(pContent));
527 }else{
528 db_multi_exec(
529 "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
530 zName, blob_str(pContent)
531 );
532 }
533 }
534 }
535
536 /*
537 ** Process a file full of "config" cards.
538 */
539 void configure_receive_all(Blob *pIn, int groupMask){
540 Blob line;
541 int nToken;
542 int size;
543 Blob aToken[4];
544
545 configHasBeenReset = 0;
546 while( blob_line(pIn, &line) ){
547 if( blob_buffer(&line)[0]=='#' ) continue;
548 nToken = blob_tokenize(&line, aToken, count(aToken));
549 if( blob_eq(&aToken[0],"config")
550 && nToken==3
551 && blob_is_int(&aToken[2], &size)
552 ){
553 const char *zName = blob_str(&aToken[1]);
554 Blob content;
555 blob_zero(&content);
556 blob_extract(pIn, size, &content);
557 g.okAdmin = g.okRdAddr = 1;
558 configure_receive(zName, &content, groupMask);
559 blob_reset(&content);
560 blob_seek(pIn, 1, BLOB_SEEK_CUR);
561 }
562 }
563 }
564
565
566 /*
567 ** Send "config" cards using the new format for all elements of a group
568 ** that have recently changed.
569 **
570 ** Output goes into pOut. The groupMask identifies the group(s) to be sent.
571 ** Send only entries whose timestamp is later than or equal to iStart.
572 **
573 ** Return the number of cards sent.
574 */
575 int configure_send_group(
576 Blob *pOut, /* Write output here */
577 int groupMask, /* Mask of groups to be send */
578 sqlite3_int64 iStart /* Only write values changed since this time */
579 ){
580 Stmt q;
581 Blob rec;
582 int ii;
583 int nCard = 0;
584
585 blob_zero(&rec);
586 if( groupMask & CONFIGSET_SHUN ){
587 db_prepare(&q, "SELECT mtime, quote(uuid), quote(scom) FROM shun"
588 " WHERE mtime>=%lld", iStart);
589 while( db_step(&q)==SQLITE_ROW ){
590 blob_appendf(&rec,"%s %s scom %s",
591 db_column_text(&q, 0),
592 db_column_text(&q, 1),
593 db_column_text(&q, 2)
594 );
595 blob_appendf(pOut, "config /shun %d\n%s\n",
596 blob_size(&rec), blob_str(&rec));
597 nCard++;
598 blob_reset(&rec);
599 }
600 db_finalize(&q);
601 }
602 if( groupMask & CONFIGSET_USER ){
603 db_prepare(&q, "SELECT mtime, quote(login), quote(pw), quote(cap),"
604 " quote(info), quote(photo) FROM user"
605 " WHERE mtime>=%lld", iStart);
606 while( db_step(&q)==SQLITE_ROW ){
607 blob_appendf(&rec,"%s %s pw %s cap %s info %s photo %s",
608 db_column_text(&q, 0),
609 db_column_text(&q, 1),
610 db_column_text(&q, 2),
611 db_column_text(&q, 3),
612 db_column_text(&q, 4),
613 db_column_text(&q, 5)
614 );
615 blob_appendf(pOut, "config /user %d\n%s\n",
616 blob_size(&rec), blob_str(&rec));
617 nCard++;
618 blob_reset(&rec);
619 }
620 db_finalize(&q);
621 }
622 if( groupMask & CONFIGSET_TKT ){
623 db_prepare(&q, "SELECT mtime, quote(title), quote(owner), quote(cols),"
624 " quote(sqlcode) FROM reportfmt"
625 " WHERE mtime>=%lld", iStart);
626 while( db_step(&q)==SQLITE_ROW ){
627 blob_appendf(&rec,"%s %s owner %s cols %s sqlcode %s",
628 db_column_text(&q, 0),
629 db_column_text(&q, 1),
630 db_column_text(&q, 2),
631 db_column_text(&q, 3),
632 db_column_text(&q, 4)
633 );
634 blob_appendf(pOut, "config /reportfmt %d\n%s\n",
635 blob_size(&rec), blob_str(&rec));
636 nCard++;
637 blob_reset(&rec);
638 }
639 db_finalize(&q);
640 }
641 if( groupMask & CONFIGSET_ADDR ){
642 db_prepare(&q, "SELECT mtime, quote(hash), quote(content) FROM concealed"
643 " WHERE mtime>=%lld", iStart);
644 while( db_step(&q)==SQLITE_ROW ){
645 blob_appendf(&rec,"%s %s content %s",
646 db_column_text(&q, 0),
647 db_column_text(&q, 1),
648 db_column_text(&q, 2)
649 );
650 blob_appendf(pOut, "config /concealed %d\n%s\n",
651 blob_size(&rec), blob_str(&rec));
652 nCard++;
653 blob_reset(&rec);
654 }
655 db_finalize(&q);
656 }
657 db_prepare(&q, "SELECT mtime, quote(name), quote(value) FROM config"
658 " WHERE name=:name AND mtime>=%lld", iStart);
659 for(ii=0; ii<count(aConfig); ii++){
660 if( (aConfig[ii].groupMask & groupMask)!=0 && aConfig[ii].zName[0]!='@' ){
661 db_bind_text(&q, ":name", aConfig[ii].zName);
662 while( db_step(&q)==SQLITE_ROW ){
663 blob_appendf(&rec,"%s %s value %s",
664 db_column_text(&q, 0),
665 db_column_text(&q, 1),
666 db_column_text(&q, 2)
667 );
668 blob_appendf(pOut, "config /config %d\n%s\n",
669 blob_size(&rec), blob_str(&rec));
670 nCard++;
671 blob_reset(&rec);
672 }
673 db_reset(&q);
674 }
675 }
676 db_finalize(&q);
677 return nCard;
678 }
679
680 /*
681 ** Identify a configuration group by name. Return its mask.
682 ** Throw an error if no match.
683 */
684 int configure_name_to_mask(const char *z, int notFoundIsFatal){
685 int i;
686 int n = strlen(z);
687 for(i=0; i<count(aGroupName); i++){
688 if( strncmp(z, &aGroupName[i].zName[1], n)==0 ){
689 return aGroupName[i].groupMask;
690 }
691 }
692 if( notFoundIsFatal ){
693 fossil_print("Available configuration areas:\n");
694 for(i=0; i<count(aGroupName); i++){
695 fossil_print(" %-10s %s\n", &aGroupName[i].zName[1], aGroupName[i].zHelp);
696 }
697 fossil_fatal("no such configuration area: \"%s\"", z);
698 }
 
699 return 0;
700 }
701
702 /*
703 ** Write SQL text into file zFilename that will restore the configuration
704 ** area identified by mask to its current state from any other state.
705 */
706 static void export_config(
707 int groupMask, /* Mask indicating which configuration to export */
708 const char *zMask, /* Name of the configuration */
709 sqlite3_int64 iStart, /* Start date */
710 const char *zFilename /* Write into this file */
711 ){
 
712 Blob out;
713 blob_zero(&out);
714 blob_appendf(&out,
715 "# The \"%s\" configuration exported from\n"
716 "# repository \"%s\"\n"
717 "# on %s\n",
718 zMask, g.zRepositoryName,
719 db_text(0, "SELECT datetime('now')")
720 );
721 configure_send_group(&out, groupMask, iStart);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
722 blob_write_to_file(&out, zFilename);
723 blob_reset(&out);
724 }
725
726
@@ -395,25 +750,31 @@
750 **
751 ** %fossil configuration pull AREA ?URL?
752 **
753 ** Pull and install the configuration from a different server
754 ** identified by URL. If no URL is specified, then the default
755 ** server is used. Use the --legacy option for the older protocol
756 ** (when talking to servers compiled prior to 2011-04-27.) Use
757 ** the --overwrite flag to completely replace local settings with
758 ** content received from URL.
759 **
760 ** %fossil configuration push AREA ?URL?
761 **
762 ** Push the local configuration into the remote server identified
763 ** by URL. Admin privilege is required on the remote server for
764 ** this to work. When the same record exists both locally and on
765 ** the remote end, the one that was most recently changed wins.
766 ** Use the --legacy flag when talking to holder servers.
767 **
768 ** %fossil configuration reset AREA
769 **
770 ** Restore the configuration to the default. AREA as above.
771 **
772 ** %fossil configuration sync AREA ?URL?
773 **
774 ** Synchronize configuration changes in the local repository with
775 ** the remote repository at URL.
776 **
777 **
778 ** SUMMARY: fossil configure METHOD ... ?-R|--repository REPOSITORY?
779 ** Where: METHOD = export, import, merge, pull, push or reset
780 **
@@ -438,36 +799,59 @@
799 db_find_and_open_repository(0, 0);
800 zMethod = g.argv[2];
801 n = strlen(zMethod);
802 if( strncmp(zMethod, "export", n)==0 ){
803 int mask;
804 const char *zSince = find_option("since",0,1);
805 sqlite3_int64 iStart;
806 if( g.argc!=5 ){
807 usage("export AREA FILENAME");
808 }
809 mask = configure_name_to_mask(g.argv[3], 1);
810 if( zSince ){
811 iStart = db_multi_exec(
812 "SELECT coalesce(strftime('%%s',%Q),strftime('%%s','now',%Q))+0",
813 zSince, zSince
814 );
815 }else{
816 iStart = 0;
817 }
818 export_config(mask, g.argv[3], iStart, g.argv[4]);
819 }else
820 if( strncmp(zMethod, "import", n)==0
821 || strncmp(zMethod, "merge", n)==0 ){
822 Blob in;
823 int groupMask;
824 if( g.argc!=4 ) usage(mprintf("%s FILENAME",zMethod));
825 blob_read_from_file(&in, g.argv[3]);
826 db_begin_transaction();
827 if( zMethod[0]=='i' ){
828 groupMask = CONFIGSET_ALL | CONFIGSET_OVERWRITE;
829 }else{
830 groupMask = CONFIGSET_ALL;
831 }
832 configure_receive_all(&in, groupMask);
833 db_end_transaction(0);
834 }else
835 if( strncmp(zMethod, "pull", n)==0
836 || strncmp(zMethod, "push", n)==0
837 || strncmp(zMethod, "sync", n)==0
838 ){
839 int mask;
840 const char *zServer;
841 const char *zPw;
842 int legacyFlag = 0;
843 int overwriteFlag = 0;
844 if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
845 if( strncmp(zMethod,"pull",n)==0 ){
846 overwriteFlag = find_option("overwrite",0,0)!=0;
847 }
848 url_proxy_options();
849 if( g.argc!=4 && g.argc!=5 ){
850 usage("pull AREA ?URL?");
851 }
852 mask = configure_name_to_mask(g.argv[3], 1);
853 if( g.argc==5 ){
854 zServer = g.argv[4];
855 zPw = 0;
856 g.dontKeepUrl = 1;
857 }else{
@@ -479,25 +863,29 @@
863 }
864 url_parse(zServer);
865 if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
866 user_select();
867 url_enable_proxy("via proxy: ");
868 if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
869 if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
870 if( strncmp(zMethod, "push", n)==0 ){
871 client_sync(0,0,0,0,0,mask);
872 }else if( strncmp(zMethod, "pull", n)==0 ){
873 client_sync(0,0,0,0,mask,0);
874 }else{
875 client_sync(0,0,0,0,mask,mask);
876 }
877 }else
878 if( strncmp(zMethod, "reset", n)==0 ){
879 int mask, i;
880 char *zBackup;
881 if( g.argc!=4 ) usage("reset AREA");
882 mask = configure_name_to_mask(g.argv[3], 1);
883 zBackup = db_text(0,
884 "SELECT strftime('config-backup-%%Y%%m%%d%%H%%M%%f','now')");
885 db_begin_transaction();
886 export_config(mask, g.argv[3], 0, zBackup);
887 for(i=0; i<count(aConfig); i++){
888 const char *zName = aConfig[i].zName;
889 if( (aConfig[i].groupMask & mask)==0 ) continue;
890 if( zName[0]!='@' ){
891 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -511,14 +899,14 @@
899 }else if( fossil_strcmp(zName,"@reportfmt")==0 ){
900 db_multi_exec("DELETE FROM reportfmt");
901 }
902 }
903 db_end_transaction(0);
904 fossil_print("Configuration reset to factory defaults.\n");
905 fossil_print("To recover, use: %s %s import %s\n",
906 fossil_nameofexe(), g.argv[1], zBackup);
907 }else
908 {
909 fossil_fatal("METHOD should be one of:"
910 " export import merge pull push reset");
911 }
912 }
913
+479 -91
--- src/configure.c
+++ src/configure.c
@@ -2,11 +2,11 @@
22
** Copyright (c) 2008 D. Richard Hipp
33
**
44
** This program is free software; you can redistribute it and/or
55
** modify it under the terms of the Simplified BSD License (also
66
** known as the "2-Clause License" or "FreeBSD License".)
7
-
7
+**
88
** This program is distributed in the hope that it will be useful,
99
** but without any warranty; without even the implied warranty of
1010
** merchantability or fitness for a particular purpose.
1111
**
1212
** Author contact information:
@@ -14,10 +14,11 @@
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
1818
** This file contains code used to manage repository configurations.
19
+**
1920
** By "responsitory configure" we mean the local state of a repository
2021
** distinct from the versioned files.
2122
*/
2223
#include "config.h"
2324
#include "configure.h"
@@ -26,18 +27,21 @@
2627
#if INTERFACE
2728
/*
2829
** Configuration transfers occur in groups. These are the allowed
2930
** groupings:
3031
*/
31
-#define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
32
-#define CONFIGSET_TKT 0x000002 /* Ticket configuration */
33
-#define CONFIGSET_PROJ 0x000004 /* Project name */
34
-#define CONFIGSET_SHUN 0x000008 /* Shun settings */
35
-#define CONFIGSET_USER 0x000010 /* The USER table */
36
-#define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
37
-
38
-#define CONFIGSET_ALL 0xffffff /* Everything */
32
+#define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
33
+#define CONFIGSET_TKT 0x000002 /* Ticket configuration */
34
+#define CONFIGSET_PROJ 0x000004 /* Project name */
35
+#define CONFIGSET_SHUN 0x000008 /* Shun settings */
36
+#define CONFIGSET_USER 0x000010 /* The USER table */
37
+#define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
38
+
39
+#define CONFIGSET_ALL 0x0000ff /* Everything */
40
+
41
+#define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
42
+#define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
3943
4044
#endif /* INTERFACE */
4145
4246
/*
4347
** Names of the configuration sets
@@ -45,17 +49,17 @@
4549
static struct {
4650
const char *zName; /* Name of the configuration set */
4751
int groupMask; /* Mask for that configuration set */
4852
const char *zHelp; /* What it does */
4953
} aGroupName[] = {
50
- { "email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
51
- { "project", CONFIGSET_PROJ, "Project name and description" },
52
- { "skin", CONFIGSET_SKIN, "Web interface apparance settings" },
53
- { "shun", CONFIGSET_SHUN, "List of shunned artifacts" },
54
- { "ticket", CONFIGSET_TKT, "Ticket setup", },
55
- { "user", CONFIGSET_USER, "Users and privilege settings" },
56
- { "all", CONFIGSET_ALL, "All of the above" },
54
+ { "/email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
55
+ { "/project", CONFIGSET_PROJ, "Project name and description" },
56
+ { "/skin", CONFIGSET_SKIN, "Web interface apparance settings" },
57
+ { "/shun", CONFIGSET_SHUN, "List of shunned artifacts" },
58
+ { "/ticket", CONFIGSET_TKT, "Ticket setup", },
59
+ { "/user", CONFIGSET_USER, "Users and privilege settings" },
60
+ { "/all", CONFIGSET_ALL, "All of the above" },
5761
};
5862
5963
6064
/*
6165
** The following is a list of settings that we are willing to
@@ -105,28 +109,52 @@
105109
const char *configure_first_name(int iMask){
106110
iConfig = 0;
107111
return configure_next_name(iMask);
108112
}
109113
const char *configure_next_name(int iMask){
110
- while( iConfig<count(aConfig) ){
111
- if( aConfig[iConfig].groupMask & iMask ){
112
- return aConfig[iConfig++].zName;
113
- }else{
114
- iConfig++;
114
+ if( iMask & CONFIGSET_OLDFORMAT ){
115
+ while( iConfig<count(aConfig) ){
116
+ if( aConfig[iConfig].groupMask & iMask ){
117
+ return aConfig[iConfig++].zName;
118
+ }else{
119
+ iConfig++;
120
+ }
121
+ }
122
+ }else{
123
+ if( iConfig==0 && (iMask & CONFIGSET_ALL)==CONFIGSET_ALL ){
124
+ iConfig = count(aGroupName);
125
+ return "/all";
126
+ }
127
+ while( iConfig<count(aGroupName)-1 ){
128
+ if( aGroupName[iConfig].groupMask & iMask ){
129
+ return aGroupName[iConfig++].zName;
130
+ }else{
131
+ iConfig++;
132
+ }
115133
}
116134
}
117135
return 0;
118136
}
119137
120138
/*
121139
** Return the mask for the named configuration parameter if it can be
122140
** safely exported. Return 0 if the parameter is not safe to export.
141
+**
142
+** "Safe" in the previous paragraph means the permission is created to
143
+** export the property. In other words, the requesting side has presented
144
+** login credentials and has sufficient capabilities to access the requested
145
+** information.
123146
*/
124147
int configure_is_exportable(const char *zName){
125148
int i;
149
+ int n = strlen(zName);
150
+ if( n>2 && zName[0]=='\'' && zName[n-1]=='\'' ){
151
+ zName++;
152
+ n -= 2;
153
+ }
126154
for(i=0; i<count(aConfig); i++){
127
- if( fossil_strcmp(zName, aConfig[i].zName)==0 ){
155
+ if( memcmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
128156
int m = aConfig[i].groupMask;
129157
if( !g.okAdmin ){
130158
m &= ~CONFIGSET_USER;
131159
}
132160
if( !g.okRdAddr ){
@@ -194,38 +222,39 @@
194222
}
195223
196224
/*
197225
** Two SQL functions:
198226
**
199
-** flag_test(int)
200
-** flag_clear(int)
227
+** config_is_reset(int)
228
+** config_reset(int)
201229
**
202
-** The flag_test() function takes the integer valued argument and
203
-** ANDs it against the static variable "flag_value" below. The
204
-** function returns TRUE or false depending on the result. The
205
-** flag_clear() function masks off the bits from "flag_value" that
230
+** The config_is_reset() function takes the integer valued argument and
231
+** ANDs it against the static variable "configHasBeenReset" below. The
232
+** function returns TRUE or FALSE depending on the result depending on
233
+** whether or not the corresponding configuration table has been reset. The
234
+** config_reset() function adds the bits to "configHasBeenReset" that
206235
** are given in the argument.
207236
**
208237
** These functions are used below in the WHEN clause of a trigger to
209238
** get the trigger to fire exactly once.
210239
*/
211
-static int flag_value = 0xffff;
212
-static void flag_test_function(
240
+static int configHasBeenReset = 0;
241
+static void config_is_reset_function(
213242
sqlite3_context *context,
214243
int argc,
215244
sqlite3_value **argv
216245
){
217246
int m = sqlite3_value_int(argv[0]);
218
- sqlite3_result_int(context, (flag_value&m)!=0 );
247
+ sqlite3_result_int(context, (configHasBeenReset&m)!=0 );
219248
}
220
-static void flag_clear_function(
249
+static void config_reset_function(
221250
sqlite3_context *context,
222251
int argc,
223252
sqlite3_value **argv
224253
){
225254
int m = sqlite3_value_int(argv[0]);
226
- flag_value &= ~m;
255
+ configHasBeenReset |= m;
227256
}
228257
229258
/*
230259
** Create the temporary _xfer_reportfmt and _xfer_user tables that are
231260
** necessary in order to evalute the SQL text generated by the
@@ -255,12 +284,14 @@
255284
@ ipaddr TEXT, -- IP address for which cookie is valid
256285
@ cexpire DATETIME, -- Time when cookie expires
257286
@ info TEXT, -- contact information
258287
@ photo BLOB -- JPEG image of this user
259288
@ );
260
- @ INSERT INTO _xfer_reportfmt SELECT * FROM reportfmt;
261
- @ INSERT INTO _xfer_user SELECT * FROM user;
289
+ @ INSERT INTO _xfer_reportfmt
290
+ @ SELECT rn,owner,title,cols,sqlcode FROM reportfmt;
291
+ @ INSERT INTO _xfer_user
292
+ @ SELECT uid,login,pw,cap,cookie,ipaddr,cexpire,info,photo FROM user;
262293
;
263294
db_multi_exec(zSQL1);
264295
265296
/* When the replace flag is set, add triggers that run the first time
266297
** that new data is seen. The triggers run only once and delete all the
@@ -267,30 +298,30 @@
267298
** existing data.
268299
*/
269300
if( replaceFlag ){
270301
static const char zSQL2[] =
271302
@ CREATE TRIGGER _xfer_r1 BEFORE INSERT ON _xfer_reportfmt
272
- @ WHEN flag_test(1) BEGIN
303
+ @ WHEN NOT config_is_reset(2) BEGIN
273304
@ DELETE FROM _xfer_reportfmt;
274
- @ SELECT flag_clear(1);
305
+ @ SELECT config_reset(2);
275306
@ END;
276307
@ CREATE TRIGGER _xfer_r2 BEFORE INSERT ON _xfer_user
277
- @ WHEN flag_test(2) BEGIN
308
+ @ WHEN NOT config_is_reset(16) BEGIN
278309
@ DELETE FROM _xfer_user;
279
- @ SELECT flag_clear(2);
310
+ @ SELECT config_reset(16);
280311
@ END;
281312
@ CREATE TEMP TRIGGER _xfer_r3 BEFORE INSERT ON shun
282
- @ WHEN flag_test(4) BEGIN
313
+ @ WHEN NOT config_is_reset(8) BEGIN
283314
@ DELETE FROM shun;
284
- @ SELECT flag_clear(4);
315
+ @ SELECT config_reset(8);
285316
@ END;
286317
;
287
- sqlite3_create_function(g.db, "flag_test", 1, SQLITE_UTF8, 0,
288
- flag_test_function, 0, 0);
289
- sqlite3_create_function(g.db, "flag_clear", 1, SQLITE_UTF8, 0,
290
- flag_clear_function, 0, 0);
291
- flag_value = 0xffff;
318
+ sqlite3_create_function(g.db, "config_is_reset", 1, SQLITE_UTF8, 0,
319
+ config_is_reset_function, 0, 0);
320
+ sqlite3_create_function(g.db, "config_reset", 1, SQLITE_UTF8, 0,
321
+ config_reset_function, 0, 0);
322
+ configHasBeenReset = 0;
292323
db_multi_exec(zSQL2);
293324
}
294325
}
295326
296327
/*
@@ -306,66 +337,390 @@
306337
@ DROP TABLE _xfer_user;
307338
@ DROP TABLE _xfer_reportfmt;
308339
;
309340
db_multi_exec(zSQL);
310341
}
342
+
343
+/*
344
+** Return true if z[] is not a "safe" SQL token. A safe token is one of:
345
+**
346
+** * A string literal
347
+** * A blob literal
348
+** * An integer literal (no floating point)
349
+** * NULL
350
+*/
351
+static int safeSql(const char *z){
352
+ int i;
353
+ if( z==0 || z[0]==0 ) return 0;
354
+ if( (z[0]=='x' || z[0]=='X') && z[1]=='\'' ) z++;
355
+ if( z[0]=='\'' ){
356
+ for(i=1; z[i]; i++){
357
+ if( z[i]=='\'' ){
358
+ i++;
359
+ if( z[i]=='\'' ){ continue; }
360
+ return z[i]==0;
361
+ }
362
+ }
363
+ return 0;
364
+ }else{
365
+ char c;
366
+ for(i=0; (c = z[i])!=0; i++){
367
+ if( !fossil_isalnum(c) ) return 0;
368
+ }
369
+ }
370
+ return 1;
371
+}
372
+
373
+/*
374
+** Return true if z[] consists of nothing but digits
375
+*/
376
+static int safeInt(const char *z){
377
+ int i;
378
+ if( z==0 || z[0]==0 ) return 0;
379
+ for(i=0; fossil_isdigit(z[i]); i++){}
380
+ return z[i]==0;
381
+}
382
+
383
+/*
384
+** Process a single "config" card received from the other side of a
385
+** sync session.
386
+**
387
+** Mask consists of one or more CONFIGSET_* values ORed together, to
388
+** designate what types of configuration we are allowed to receive.
389
+**
390
+** NEW FORMAT:
391
+**
392
+** zName is one of "/config", "/user", "/shun", "/reportfmt", or "/concealed".
393
+** zName indicates the table that holds the configuration information being
394
+** transferred. pContent is a string that consist of alternating Fossil
395
+** and SQL tokens. The First token is a timestamp in seconds since 1970.
396
+** The second token is a primary key for the table identified by zName. If
397
+** The entry with the corresponding primary key exists and has a more recent
398
+** mtime, then nothing happens. If the entry does not exist or if it has
399
+** an older mtime, then the content described by subsequent token pairs is
400
+** inserted. The first element of each token pair is a column name and
401
+** the second is its value.
402
+**
403
+** In overview, we have:
404
+**
405
+** NAME CONTENT
406
+** ------- -----------------------------------------------------------
407
+** /config $MTIME $NAME value $VALUE
408
+** /user $MTIME $LOGIN pw $VALUE cap $VALUE info $VALUE photo $VALUE
409
+** /shun $MTIME $UUID scom $VALUE
410
+** /reportfmt $MTIME $TITLE owner $VALUE cols $VALUE sqlcode $VALUE
411
+** /concealed $MTIME $HASH content $VALUE
412
+**
413
+** OLD FORMAT:
414
+**
415
+** The old format is retained for backwards compatiblity, but is deprecated.
416
+** The cutover from old format to new was on 2011-04-25. After sufficient
417
+** time has passed, support for the old format will be removed.
418
+**
419
+** zName is either the NAME of an element of the CONFIG table, or else
420
+** one of the special names "@shun", "@reportfmt", "@user", or "@concealed".
421
+** If zName is a CONFIG table name, then CONTENT replaces (overwrites) the
422
+** element in the CONFIG table. For one of the @-labels, CONTENT is raw
423
+** SQL that is evaluated. Note that the raw SQL in CONTENT might not
424
+** insert directly into the target table but might instead use a proxy
425
+** table like _fer_reportfmt or _xfer_user. Such tables must be created
426
+** ahead of time using configure_prepare_to_receive(). Then after multiple
427
+** calls to this routine, configure_finalize_receive() to transfer the
428
+** information received into the true target table.
429
+*/
430
+void configure_receive(const char *zName, Blob *pContent, int groupMask){
431
+ if( zName[0]=='/' ){
432
+ /* The new format */
433
+ char *azToken[12];
434
+ int nToken = 0;
435
+ int ii, jj;
436
+ int thisMask;
437
+ Blob name, value, sql;
438
+ static const struct receiveType {
439
+ const char *zName;
440
+ const char *zPrimKey;
441
+ int nField;
442
+ const char *azField[4];
443
+ } aType[] = {
444
+ { "/config", "name", 1, { "value", 0, 0, 0 } },
445
+ { "@user", "login", 4, { "pw", "cap", "info", "photo" } },
446
+ { "@shun", "uuid", 1, { "scom", 0, 0, 0 } },
447
+ { "@reportfmt", "title", 3, { "owner", "cols", "sqlcode", 0 } },
448
+ { "@concealed", "hash", 1, { "content", 0, 0, 0 } },
449
+ };
450
+ for(ii=0; ii<count(aType); ii++){
451
+ if( fossil_strcmp(&aType[ii].zName[1],&zName[1])==0 ) break;
452
+ }
453
+ if( ii>=count(aType) ) return;
454
+ while( blob_token(pContent, &name) && blob_sqltoken(pContent, &value) ){
455
+ char *z = blob_terminate(&name);
456
+ if( !safeSql(z) ) return;
457
+ if( nToken>0 ){
458
+ for(jj=0; jj<aType[ii].nField; jj++){
459
+ if( fossil_strcmp(aType[ii].azField[jj], z)==0 ) break;
460
+ }
461
+ if( jj>=aType[ii].nField ) continue;
462
+ }else{
463
+ if( !safeInt(z) ) return;
464
+ }
465
+ azToken[nToken++] = z;
466
+ azToken[nToken++] = z = blob_terminate(&value);
467
+ if( !safeSql(z) ) return;
468
+ if( nToken>=count(azToken) ) break;
469
+ }
470
+ if( nToken<2 ) return;
471
+ if( aType[ii].zName[0]=='/' ){
472
+ thisMask = configure_is_exportable(azToken[1]);
473
+ }else{
474
+ thisMask = configure_is_exportable(aType[ii].zName);
475
+ }
476
+ if( (thisMask & groupMask)==0 ) return;
477
+
478
+ blob_zero(&sql);
479
+ if( groupMask & CONFIGSET_OVERWRITE ){
480
+ if( (thisMask & configHasBeenReset)==0 && aType[ii].zName[0]!='/' ){
481
+ db_multi_exec("DELETE FROM %s", &aType[ii].zName[1]);
482
+ configHasBeenReset |= thisMask;
483
+ }
484
+ blob_append(&sql, "REPLACE INTO ", -1);
485
+ }else{
486
+ blob_append(&sql, "INSERT OR IGNORE INTO ", -1);
487
+ }
488
+ blob_appendf(&sql, "%s(%s, mtime", &zName[1], aType[ii].zPrimKey);
489
+ for(jj=2; jj<nToken; jj+=2){
490
+ blob_appendf(&sql, ",%s", azToken[jj]);
491
+ }
492
+ blob_appendf(&sql,") VALUES(%s,%s", azToken[1], azToken[0]);
493
+ for(jj=2; jj<nToken; jj+=2){
494
+ blob_appendf(&sql, ",%s", azToken[jj+1]);
495
+ }
496
+ db_multi_exec("%s)", blob_str(&sql));
497
+ if( db_changes()==0 ){
498
+ blob_reset(&sql);
499
+ blob_appendf(&sql, "UPDATE %s SET mtime=%s", &zName[1], azToken[0]);
500
+ for(jj=2; jj<nToken; jj+=2){
501
+ blob_appendf(&sql, ", %s=%s", azToken[jj], azToken[jj+1]);
502
+ }
503
+ blob_appendf(&sql, " WHERE %s=%s AND mtime<%s",
504
+ aType[ii].zPrimKey, azToken[1], azToken[0]);
505
+ db_multi_exec("%s", blob_str(&sql));
506
+ }
507
+ blob_reset(&sql);
508
+ }else{
509
+ /* Otherwise, the old format */
510
+ if( (configure_is_exportable(zName) & groupMask)==0 ) return;
511
+ if( strcmp(zName, "logo-image")==0 ){
512
+ Stmt ins;
513
+ db_prepare(&ins,
514
+ "REPLACE INTO config(name, value, mtime) VALUES(:name, :value, now())"
515
+ );
516
+ db_bind_text(&ins, ":name", zName);
517
+ db_bind_blob(&ins, ":value", pContent);
518
+ db_step(&ins);
519
+ db_finalize(&ins);
520
+ }else if( zName[0]=='@' ){
521
+ /* Notice that we are evaluating arbitrary SQL received from the
522
+ ** client. But this can only happen if the client has authenticated
523
+ ** as an administrator, so presumably we trust the client at this
524
+ ** point.
525
+ */
526
+ db_multi_exec("%s", blob_str(pContent));
527
+ }else{
528
+ db_multi_exec(
529
+ "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
530
+ zName, blob_str(pContent)
531
+ );
532
+ }
533
+ }
534
+}
535
+
536
+/*
537
+** Process a file full of "config" cards.
538
+*/
539
+void configure_receive_all(Blob *pIn, int groupMask){
540
+ Blob line;
541
+ int nToken;
542
+ int size;
543
+ Blob aToken[4];
544
+
545
+ configHasBeenReset = 0;
546
+ while( blob_line(pIn, &line) ){
547
+ if( blob_buffer(&line)[0]=='#' ) continue;
548
+ nToken = blob_tokenize(&line, aToken, count(aToken));
549
+ if( blob_eq(&aToken[0],"config")
550
+ && nToken==3
551
+ && blob_is_int(&aToken[2], &size)
552
+ ){
553
+ const char *zName = blob_str(&aToken[1]);
554
+ Blob content;
555
+ blob_zero(&content);
556
+ blob_extract(pIn, size, &content);
557
+ g.okAdmin = g.okRdAddr = 1;
558
+ configure_receive(zName, &content, groupMask);
559
+ blob_reset(&content);
560
+ blob_seek(pIn, 1, BLOB_SEEK_CUR);
561
+ }
562
+ }
563
+}
564
+
565
+
566
+/*
567
+** Send "config" cards using the new format for all elements of a group
568
+** that have recently changed.
569
+**
570
+** Output goes into pOut. The groupMask identifies the group(s) to be sent.
571
+** Send only entries whose timestamp is later than or equal to iStart.
572
+**
573
+** Return the number of cards sent.
574
+*/
575
+int configure_send_group(
576
+ Blob *pOut, /* Write output here */
577
+ int groupMask, /* Mask of groups to be send */
578
+ sqlite3_int64 iStart /* Only write values changed since this time */
579
+){
580
+ Stmt q;
581
+ Blob rec;
582
+ int ii;
583
+ int nCard = 0;
584
+
585
+ blob_zero(&rec);
586
+ if( groupMask & CONFIGSET_SHUN ){
587
+ db_prepare(&q, "SELECT mtime, quote(uuid), quote(scom) FROM shun"
588
+ " WHERE mtime>=%lld", iStart);
589
+ while( db_step(&q)==SQLITE_ROW ){
590
+ blob_appendf(&rec,"%s %s scom %s",
591
+ db_column_text(&q, 0),
592
+ db_column_text(&q, 1),
593
+ db_column_text(&q, 2)
594
+ );
595
+ blob_appendf(pOut, "config /shun %d\n%s\n",
596
+ blob_size(&rec), blob_str(&rec));
597
+ nCard++;
598
+ blob_reset(&rec);
599
+ }
600
+ db_finalize(&q);
601
+ }
602
+ if( groupMask & CONFIGSET_USER ){
603
+ db_prepare(&q, "SELECT mtime, quote(login), quote(pw), quote(cap),"
604
+ " quote(info), quote(photo) FROM user"
605
+ " WHERE mtime>=%lld", iStart);
606
+ while( db_step(&q)==SQLITE_ROW ){
607
+ blob_appendf(&rec,"%s %s pw %s cap %s info %s photo %s",
608
+ db_column_text(&q, 0),
609
+ db_column_text(&q, 1),
610
+ db_column_text(&q, 2),
611
+ db_column_text(&q, 3),
612
+ db_column_text(&q, 4),
613
+ db_column_text(&q, 5)
614
+ );
615
+ blob_appendf(pOut, "config /user %d\n%s\n",
616
+ blob_size(&rec), blob_str(&rec));
617
+ nCard++;
618
+ blob_reset(&rec);
619
+ }
620
+ db_finalize(&q);
621
+ }
622
+ if( groupMask & CONFIGSET_TKT ){
623
+ db_prepare(&q, "SELECT mtime, quote(title), quote(owner), quote(cols),"
624
+ " quote(sqlcode) FROM reportfmt"
625
+ " WHERE mtime>=%lld", iStart);
626
+ while( db_step(&q)==SQLITE_ROW ){
627
+ blob_appendf(&rec,"%s %s owner %s cols %s sqlcode %s",
628
+ db_column_text(&q, 0),
629
+ db_column_text(&q, 1),
630
+ db_column_text(&q, 2),
631
+ db_column_text(&q, 3),
632
+ db_column_text(&q, 4)
633
+ );
634
+ blob_appendf(pOut, "config /reportfmt %d\n%s\n",
635
+ blob_size(&rec), blob_str(&rec));
636
+ nCard++;
637
+ blob_reset(&rec);
638
+ }
639
+ db_finalize(&q);
640
+ }
641
+ if( groupMask & CONFIGSET_ADDR ){
642
+ db_prepare(&q, "SELECT mtime, quote(hash), quote(content) FROM concealed"
643
+ " WHERE mtime>=%lld", iStart);
644
+ while( db_step(&q)==SQLITE_ROW ){
645
+ blob_appendf(&rec,"%s %s content %s",
646
+ db_column_text(&q, 0),
647
+ db_column_text(&q, 1),
648
+ db_column_text(&q, 2)
649
+ );
650
+ blob_appendf(pOut, "config /concealed %d\n%s\n",
651
+ blob_size(&rec), blob_str(&rec));
652
+ nCard++;
653
+ blob_reset(&rec);
654
+ }
655
+ db_finalize(&q);
656
+ }
657
+ db_prepare(&q, "SELECT mtime, quote(name), quote(value) FROM config"
658
+ " WHERE name=:name AND mtime>=%lld", iStart);
659
+ for(ii=0; ii<count(aConfig); ii++){
660
+ if( (aConfig[ii].groupMask & groupMask)!=0 && aConfig[ii].zName[0]!='@' ){
661
+ db_bind_text(&q, ":name", aConfig[ii].zName);
662
+ while( db_step(&q)==SQLITE_ROW ){
663
+ blob_appendf(&rec,"%s %s value %s",
664
+ db_column_text(&q, 0),
665
+ db_column_text(&q, 1),
666
+ db_column_text(&q, 2)
667
+ );
668
+ blob_appendf(pOut, "config /config %d\n%s\n",
669
+ blob_size(&rec), blob_str(&rec));
670
+ nCard++;
671
+ blob_reset(&rec);
672
+ }
673
+ db_reset(&q);
674
+ }
675
+ }
676
+ db_finalize(&q);
677
+ return nCard;
678
+}
311679
312680
/*
313681
** Identify a configuration group by name. Return its mask.
314682
** Throw an error if no match.
315683
*/
316
-static int find_area(const char *z){
684
+int configure_name_to_mask(const char *z, int notFoundIsFatal){
317685
int i;
318686
int n = strlen(z);
319687
for(i=0; i<count(aGroupName); i++){
320
- if( strncmp(z, aGroupName[i].zName, n)==0 ){
688
+ if( strncmp(z, &aGroupName[i].zName[1], n)==0 ){
321689
return aGroupName[i].groupMask;
322690
}
323691
}
324
- printf("Available configuration areas:\n");
325
- for(i=0; i<count(aGroupName); i++){
326
- printf(" %-10s %s\n", aGroupName[i].zName, aGroupName[i].zHelp);
692
+ if( notFoundIsFatal ){
693
+ fossil_print("Available configuration areas:\n");
694
+ for(i=0; i<count(aGroupName); i++){
695
+ fossil_print(" %-10s %s\n", &aGroupName[i].zName[1], aGroupName[i].zHelp);
696
+ }
697
+ fossil_fatal("no such configuration area: \"%s\"", z);
327698
}
328
- fossil_fatal("no such configuration area: \"%s\"", z);
329699
return 0;
330700
}
331701
332702
/*
333703
** Write SQL text into file zFilename that will restore the configuration
334704
** area identified by mask to its current state from any other state.
335705
*/
336706
static void export_config(
337
- int mask, /* Mask indicating which configuration to export */
707
+ int groupMask, /* Mask indicating which configuration to export */
338708
const char *zMask, /* Name of the configuration */
709
+ sqlite3_int64 iStart, /* Start date */
339710
const char *zFilename /* Write into this file */
340711
){
341
- int i;
342712
Blob out;
343713
blob_zero(&out);
344
- blob_appendf(&out,
345
- "-- The \"%s\" configuration exported from\n"
346
- "-- repository \"%s\"\n"
347
- "-- on %s\n",
714
+ blob_appendf(&out,
715
+ "# The \"%s\" configuration exported from\n"
716
+ "# repository \"%s\"\n"
717
+ "# on %s\n",
348718
zMask, g.zRepositoryName,
349719
db_text(0, "SELECT datetime('now')")
350720
);
351
- for(i=0; i<count(aConfig); i++){
352
- if( (aConfig[i].groupMask & mask)!=0 ){
353
- const char *zName = aConfig[i].zName;
354
- if( zName[0]!='@' ){
355
- char *zValue = db_text(0,
356
- "SELECT quote(value) FROM config WHERE name=%Q", zName);
357
- if( zValue ){
358
- blob_appendf(&out,"REPLACE INTO config VALUES(%Q,%s);\n",
359
- zName, zValue);
360
- }
361
- free(zValue);
362
- }else{
363
- configure_render_special_name(zName, &out);
364
- }
365
- }
366
- }
721
+ configure_send_group(&out, groupMask, iStart);
367722
blob_write_to_file(&out, zFilename);
368723
blob_reset(&out);
369724
}
370725
371726
@@ -395,25 +750,31 @@
395750
**
396751
** %fossil configuration pull AREA ?URL?
397752
**
398753
** Pull and install the configuration from a different server
399754
** identified by URL. If no URL is specified, then the default
400
-** server is used.
755
+** server is used. Use the --legacy option for the older protocol
756
+** (when talking to servers compiled prior to 2011-04-27.) Use
757
+** the --overwrite flag to completely replace local settings with
758
+** content received from URL.
401759
**
402760
** %fossil configuration push AREA ?URL?
403761
**
404762
** Push the local configuration into the remote server identified
405763
** by URL. Admin privilege is required on the remote server for
406
-** this to work.
764
+** this to work. When the same record exists both locally and on
765
+** the remote end, the one that was most recently changed wins.
766
+** Use the --legacy flag when talking to holder servers.
407767
**
408768
** %fossil configuration reset AREA
409769
**
410770
** Restore the configuration to the default. AREA as above.
411771
**
412
-** WARNING: Do not import, merge, or pull configurations from an untrusted
413
-** source. The inbound configuration is not checked for safety and can
414
-** introduce security vulnerabilities.
772
+** %fossil configuration sync AREA ?URL?
773
+**
774
+** Synchronize configuration changes in the local repository with
775
+** the remote repository at URL.
415776
**
416777
**
417778
** SUMMARY: fossil configure METHOD ... ?-R|--repository REPOSITORY?
418779
** Where: METHOD = export, import, merge, pull, push or reset
419780
**
@@ -438,36 +799,59 @@
438799
db_find_and_open_repository(0, 0);
439800
zMethod = g.argv[2];
440801
n = strlen(zMethod);
441802
if( strncmp(zMethod, "export", n)==0 ){
442803
int mask;
804
+ const char *zSince = find_option("since",0,1);
805
+ sqlite3_int64 iStart;
443806
if( g.argc!=5 ){
444807
usage("export AREA FILENAME");
445808
}
446
- mask = find_area(g.argv[3]);
447
- export_config(mask, g.argv[3], g.argv[4]);
809
+ mask = configure_name_to_mask(g.argv[3], 1);
810
+ if( zSince ){
811
+ iStart = db_multi_exec(
812
+ "SELECT coalesce(strftime('%%s',%Q),strftime('%%s','now',%Q))+0",
813
+ zSince, zSince
814
+ );
815
+ }else{
816
+ iStart = 0;
817
+ }
818
+ export_config(mask, g.argv[3], iStart, g.argv[4]);
448819
}else
449820
if( strncmp(zMethod, "import", n)==0
450821
|| strncmp(zMethod, "merge", n)==0 ){
451822
Blob in;
823
+ int groupMask;
452824
if( g.argc!=4 ) usage(mprintf("%s FILENAME",zMethod));
453825
blob_read_from_file(&in, g.argv[3]);
454826
db_begin_transaction();
455
- configure_prepare_to_receive(zMethod[0]=='i');
456
- db_multi_exec("%s", blob_str(&in));
457
- configure_finalize_receive();
827
+ if( zMethod[0]=='i' ){
828
+ groupMask = CONFIGSET_ALL | CONFIGSET_OVERWRITE;
829
+ }else{
830
+ groupMask = CONFIGSET_ALL;
831
+ }
832
+ configure_receive_all(&in, groupMask);
458833
db_end_transaction(0);
459834
}else
460
- if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
835
+ if( strncmp(zMethod, "pull", n)==0
836
+ || strncmp(zMethod, "push", n)==0
837
+ || strncmp(zMethod, "sync", n)==0
838
+ ){
461839
int mask;
462840
const char *zServer;
463841
const char *zPw;
842
+ int legacyFlag = 0;
843
+ int overwriteFlag = 0;
844
+ if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
845
+ if( strncmp(zMethod,"pull",n)==0 ){
846
+ overwriteFlag = find_option("overwrite",0,0)!=0;
847
+ }
464848
url_proxy_options();
465849
if( g.argc!=4 && g.argc!=5 ){
466850
usage("pull AREA ?URL?");
467851
}
468
- mask = find_area(g.argv[3]);
852
+ mask = configure_name_to_mask(g.argv[3], 1);
469853
if( g.argc==5 ){
470854
zServer = g.argv[4];
471855
zPw = 0;
472856
g.dontKeepUrl = 1;
473857
}else{
@@ -479,25 +863,29 @@
479863
}
480864
url_parse(zServer);
481865
if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
482866
user_select();
483867
url_enable_proxy("via proxy: ");
868
+ if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
869
+ if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
484870
if( strncmp(zMethod, "push", n)==0 ){
485871
client_sync(0,0,0,0,0,mask);
486
- }else{
872
+ }else if( strncmp(zMethod, "pull", n)==0 ){
487873
client_sync(0,0,0,0,mask,0);
874
+ }else{
875
+ client_sync(0,0,0,0,mask,mask);
488876
}
489877
}else
490878
if( strncmp(zMethod, "reset", n)==0 ){
491879
int mask, i;
492880
char *zBackup;
493881
if( g.argc!=4 ) usage("reset AREA");
494
- mask = find_area(g.argv[3]);
882
+ mask = configure_name_to_mask(g.argv[3], 1);
495883
zBackup = db_text(0,
496884
"SELECT strftime('config-backup-%%Y%%m%%d%%H%%M%%f','now')");
497885
db_begin_transaction();
498
- export_config(mask, g.argv[3], zBackup);
886
+ export_config(mask, g.argv[3], 0, zBackup);
499887
for(i=0; i<count(aConfig); i++){
500888
const char *zName = aConfig[i].zName;
501889
if( (aConfig[i].groupMask & mask)==0 ) continue;
502890
if( zName[0]!='@' ){
503891
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -511,14 +899,14 @@
511899
}else if( fossil_strcmp(zName,"@reportfmt")==0 ){
512900
db_multi_exec("DELETE FROM reportfmt");
513901
}
514902
}
515903
db_end_transaction(0);
516
- printf("Configuration reset to factory defaults.\n");
517
- printf("To recover, use: %s %s import %s\n",
904
+ fossil_print("Configuration reset to factory defaults.\n");
905
+ fossil_print("To recover, use: %s %s import %s\n",
518906
fossil_nameofexe(), g.argv[1], zBackup);
519907
}else
520908
{
521909
fossil_fatal("METHOD should be one of:"
522910
" export import merge pull push reset");
523911
}
524912
}
525913
--- src/configure.c
+++ src/configure.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2008 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -14,10 +14,11 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to manage repository configurations.
 
19 ** By "responsitory configure" we mean the local state of a repository
20 ** distinct from the versioned files.
21 */
22 #include "config.h"
23 #include "configure.h"
@@ -26,18 +27,21 @@
26 #if INTERFACE
27 /*
28 ** Configuration transfers occur in groups. These are the allowed
29 ** groupings:
30 */
31 #define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
32 #define CONFIGSET_TKT 0x000002 /* Ticket configuration */
33 #define CONFIGSET_PROJ 0x000004 /* Project name */
34 #define CONFIGSET_SHUN 0x000008 /* Shun settings */
35 #define CONFIGSET_USER 0x000010 /* The USER table */
36 #define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
37
38 #define CONFIGSET_ALL 0xffffff /* Everything */
 
 
 
39
40 #endif /* INTERFACE */
41
42 /*
43 ** Names of the configuration sets
@@ -45,17 +49,17 @@
45 static struct {
46 const char *zName; /* Name of the configuration set */
47 int groupMask; /* Mask for that configuration set */
48 const char *zHelp; /* What it does */
49 } aGroupName[] = {
50 { "email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
51 { "project", CONFIGSET_PROJ, "Project name and description" },
52 { "skin", CONFIGSET_SKIN, "Web interface apparance settings" },
53 { "shun", CONFIGSET_SHUN, "List of shunned artifacts" },
54 { "ticket", CONFIGSET_TKT, "Ticket setup", },
55 { "user", CONFIGSET_USER, "Users and privilege settings" },
56 { "all", CONFIGSET_ALL, "All of the above" },
57 };
58
59
60 /*
61 ** The following is a list of settings that we are willing to
@@ -105,28 +109,52 @@
105 const char *configure_first_name(int iMask){
106 iConfig = 0;
107 return configure_next_name(iMask);
108 }
109 const char *configure_next_name(int iMask){
110 while( iConfig<count(aConfig) ){
111 if( aConfig[iConfig].groupMask & iMask ){
112 return aConfig[iConfig++].zName;
113 }else{
114 iConfig++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115 }
116 }
117 return 0;
118 }
119
120 /*
121 ** Return the mask for the named configuration parameter if it can be
122 ** safely exported. Return 0 if the parameter is not safe to export.
 
 
 
 
 
123 */
124 int configure_is_exportable(const char *zName){
125 int i;
 
 
 
 
 
126 for(i=0; i<count(aConfig); i++){
127 if( fossil_strcmp(zName, aConfig[i].zName)==0 ){
128 int m = aConfig[i].groupMask;
129 if( !g.okAdmin ){
130 m &= ~CONFIGSET_USER;
131 }
132 if( !g.okRdAddr ){
@@ -194,38 +222,39 @@
194 }
195
196 /*
197 ** Two SQL functions:
198 **
199 ** flag_test(int)
200 ** flag_clear(int)
201 **
202 ** The flag_test() function takes the integer valued argument and
203 ** ANDs it against the static variable "flag_value" below. The
204 ** function returns TRUE or false depending on the result. The
205 ** flag_clear() function masks off the bits from "flag_value" that
 
206 ** are given in the argument.
207 **
208 ** These functions are used below in the WHEN clause of a trigger to
209 ** get the trigger to fire exactly once.
210 */
211 static int flag_value = 0xffff;
212 static void flag_test_function(
213 sqlite3_context *context,
214 int argc,
215 sqlite3_value **argv
216 ){
217 int m = sqlite3_value_int(argv[0]);
218 sqlite3_result_int(context, (flag_value&m)!=0 );
219 }
220 static void flag_clear_function(
221 sqlite3_context *context,
222 int argc,
223 sqlite3_value **argv
224 ){
225 int m = sqlite3_value_int(argv[0]);
226 flag_value &= ~m;
227 }
228
229 /*
230 ** Create the temporary _xfer_reportfmt and _xfer_user tables that are
231 ** necessary in order to evalute the SQL text generated by the
@@ -255,12 +284,14 @@
255 @ ipaddr TEXT, -- IP address for which cookie is valid
256 @ cexpire DATETIME, -- Time when cookie expires
257 @ info TEXT, -- contact information
258 @ photo BLOB -- JPEG image of this user
259 @ );
260 @ INSERT INTO _xfer_reportfmt SELECT * FROM reportfmt;
261 @ INSERT INTO _xfer_user SELECT * FROM user;
 
 
262 ;
263 db_multi_exec(zSQL1);
264
265 /* When the replace flag is set, add triggers that run the first time
266 ** that new data is seen. The triggers run only once and delete all the
@@ -267,30 +298,30 @@
267 ** existing data.
268 */
269 if( replaceFlag ){
270 static const char zSQL2[] =
271 @ CREATE TRIGGER _xfer_r1 BEFORE INSERT ON _xfer_reportfmt
272 @ WHEN flag_test(1) BEGIN
273 @ DELETE FROM _xfer_reportfmt;
274 @ SELECT flag_clear(1);
275 @ END;
276 @ CREATE TRIGGER _xfer_r2 BEFORE INSERT ON _xfer_user
277 @ WHEN flag_test(2) BEGIN
278 @ DELETE FROM _xfer_user;
279 @ SELECT flag_clear(2);
280 @ END;
281 @ CREATE TEMP TRIGGER _xfer_r3 BEFORE INSERT ON shun
282 @ WHEN flag_test(4) BEGIN
283 @ DELETE FROM shun;
284 @ SELECT flag_clear(4);
285 @ END;
286 ;
287 sqlite3_create_function(g.db, "flag_test", 1, SQLITE_UTF8, 0,
288 flag_test_function, 0, 0);
289 sqlite3_create_function(g.db, "flag_clear", 1, SQLITE_UTF8, 0,
290 flag_clear_function, 0, 0);
291 flag_value = 0xffff;
292 db_multi_exec(zSQL2);
293 }
294 }
295
296 /*
@@ -306,66 +337,390 @@
306 @ DROP TABLE _xfer_user;
307 @ DROP TABLE _xfer_reportfmt;
308 ;
309 db_multi_exec(zSQL);
310 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
312 /*
313 ** Identify a configuration group by name. Return its mask.
314 ** Throw an error if no match.
315 */
316 static int find_area(const char *z){
317 int i;
318 int n = strlen(z);
319 for(i=0; i<count(aGroupName); i++){
320 if( strncmp(z, aGroupName[i].zName, n)==0 ){
321 return aGroupName[i].groupMask;
322 }
323 }
324 printf("Available configuration areas:\n");
325 for(i=0; i<count(aGroupName); i++){
326 printf(" %-10s %s\n", aGroupName[i].zName, aGroupName[i].zHelp);
 
 
 
327 }
328 fossil_fatal("no such configuration area: \"%s\"", z);
329 return 0;
330 }
331
332 /*
333 ** Write SQL text into file zFilename that will restore the configuration
334 ** area identified by mask to its current state from any other state.
335 */
336 static void export_config(
337 int mask, /* Mask indicating which configuration to export */
338 const char *zMask, /* Name of the configuration */
 
339 const char *zFilename /* Write into this file */
340 ){
341 int i;
342 Blob out;
343 blob_zero(&out);
344 blob_appendf(&out,
345 "-- The \"%s\" configuration exported from\n"
346 "-- repository \"%s\"\n"
347 "-- on %s\n",
348 zMask, g.zRepositoryName,
349 db_text(0, "SELECT datetime('now')")
350 );
351 for(i=0; i<count(aConfig); i++){
352 if( (aConfig[i].groupMask & mask)!=0 ){
353 const char *zName = aConfig[i].zName;
354 if( zName[0]!='@' ){
355 char *zValue = db_text(0,
356 "SELECT quote(value) FROM config WHERE name=%Q", zName);
357 if( zValue ){
358 blob_appendf(&out,"REPLACE INTO config VALUES(%Q,%s);\n",
359 zName, zValue);
360 }
361 free(zValue);
362 }else{
363 configure_render_special_name(zName, &out);
364 }
365 }
366 }
367 blob_write_to_file(&out, zFilename);
368 blob_reset(&out);
369 }
370
371
@@ -395,25 +750,31 @@
395 **
396 ** %fossil configuration pull AREA ?URL?
397 **
398 ** Pull and install the configuration from a different server
399 ** identified by URL. If no URL is specified, then the default
400 ** server is used.
 
 
 
401 **
402 ** %fossil configuration push AREA ?URL?
403 **
404 ** Push the local configuration into the remote server identified
405 ** by URL. Admin privilege is required on the remote server for
406 ** this to work.
 
 
407 **
408 ** %fossil configuration reset AREA
409 **
410 ** Restore the configuration to the default. AREA as above.
411 **
412 ** WARNING: Do not import, merge, or pull configurations from an untrusted
413 ** source. The inbound configuration is not checked for safety and can
414 ** introduce security vulnerabilities.
 
415 **
416 **
417 ** SUMMARY: fossil configure METHOD ... ?-R|--repository REPOSITORY?
418 ** Where: METHOD = export, import, merge, pull, push or reset
419 **
@@ -438,36 +799,59 @@
438 db_find_and_open_repository(0, 0);
439 zMethod = g.argv[2];
440 n = strlen(zMethod);
441 if( strncmp(zMethod, "export", n)==0 ){
442 int mask;
 
 
443 if( g.argc!=5 ){
444 usage("export AREA FILENAME");
445 }
446 mask = find_area(g.argv[3]);
447 export_config(mask, g.argv[3], g.argv[4]);
 
 
 
 
 
 
 
 
448 }else
449 if( strncmp(zMethod, "import", n)==0
450 || strncmp(zMethod, "merge", n)==0 ){
451 Blob in;
 
452 if( g.argc!=4 ) usage(mprintf("%s FILENAME",zMethod));
453 blob_read_from_file(&in, g.argv[3]);
454 db_begin_transaction();
455 configure_prepare_to_receive(zMethod[0]=='i');
456 db_multi_exec("%s", blob_str(&in));
457 configure_finalize_receive();
 
 
 
458 db_end_transaction(0);
459 }else
460 if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
 
 
 
461 int mask;
462 const char *zServer;
463 const char *zPw;
 
 
 
 
 
 
464 url_proxy_options();
465 if( g.argc!=4 && g.argc!=5 ){
466 usage("pull AREA ?URL?");
467 }
468 mask = find_area(g.argv[3]);
469 if( g.argc==5 ){
470 zServer = g.argv[4];
471 zPw = 0;
472 g.dontKeepUrl = 1;
473 }else{
@@ -479,25 +863,29 @@
479 }
480 url_parse(zServer);
481 if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
482 user_select();
483 url_enable_proxy("via proxy: ");
 
 
484 if( strncmp(zMethod, "push", n)==0 ){
485 client_sync(0,0,0,0,0,mask);
486 }else{
487 client_sync(0,0,0,0,mask,0);
 
 
488 }
489 }else
490 if( strncmp(zMethod, "reset", n)==0 ){
491 int mask, i;
492 char *zBackup;
493 if( g.argc!=4 ) usage("reset AREA");
494 mask = find_area(g.argv[3]);
495 zBackup = db_text(0,
496 "SELECT strftime('config-backup-%%Y%%m%%d%%H%%M%%f','now')");
497 db_begin_transaction();
498 export_config(mask, g.argv[3], zBackup);
499 for(i=0; i<count(aConfig); i++){
500 const char *zName = aConfig[i].zName;
501 if( (aConfig[i].groupMask & mask)==0 ) continue;
502 if( zName[0]!='@' ){
503 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -511,14 +899,14 @@
511 }else if( fossil_strcmp(zName,"@reportfmt")==0 ){
512 db_multi_exec("DELETE FROM reportfmt");
513 }
514 }
515 db_end_transaction(0);
516 printf("Configuration reset to factory defaults.\n");
517 printf("To recover, use: %s %s import %s\n",
518 fossil_nameofexe(), g.argv[1], zBackup);
519 }else
520 {
521 fossil_fatal("METHOD should be one of:"
522 " export import merge pull push reset");
523 }
524 }
525
--- src/configure.c
+++ src/configure.c
@@ -2,11 +2,11 @@
2 ** Copyright (c) 2008 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
@@ -14,10 +14,11 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to manage repository configurations.
19 **
20 ** By "responsitory configure" we mean the local state of a repository
21 ** distinct from the versioned files.
22 */
23 #include "config.h"
24 #include "configure.h"
@@ -26,18 +27,21 @@
27 #if INTERFACE
28 /*
29 ** Configuration transfers occur in groups. These are the allowed
30 ** groupings:
31 */
32 #define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
33 #define CONFIGSET_TKT 0x000002 /* Ticket configuration */
34 #define CONFIGSET_PROJ 0x000004 /* Project name */
35 #define CONFIGSET_SHUN 0x000008 /* Shun settings */
36 #define CONFIGSET_USER 0x000010 /* The USER table */
37 #define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
38
39 #define CONFIGSET_ALL 0x0000ff /* Everything */
40
41 #define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
42 #define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
43
44 #endif /* INTERFACE */
45
46 /*
47 ** Names of the configuration sets
@@ -45,17 +49,17 @@
49 static struct {
50 const char *zName; /* Name of the configuration set */
51 int groupMask; /* Mask for that configuration set */
52 const char *zHelp; /* What it does */
53 } aGroupName[] = {
54 { "/email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
55 { "/project", CONFIGSET_PROJ, "Project name and description" },
56 { "/skin", CONFIGSET_SKIN, "Web interface apparance settings" },
57 { "/shun", CONFIGSET_SHUN, "List of shunned artifacts" },
58 { "/ticket", CONFIGSET_TKT, "Ticket setup", },
59 { "/user", CONFIGSET_USER, "Users and privilege settings" },
60 { "/all", CONFIGSET_ALL, "All of the above" },
61 };
62
63
64 /*
65 ** The following is a list of settings that we are willing to
@@ -105,28 +109,52 @@
109 const char *configure_first_name(int iMask){
110 iConfig = 0;
111 return configure_next_name(iMask);
112 }
113 const char *configure_next_name(int iMask){
114 if( iMask & CONFIGSET_OLDFORMAT ){
115 while( iConfig<count(aConfig) ){
116 if( aConfig[iConfig].groupMask & iMask ){
117 return aConfig[iConfig++].zName;
118 }else{
119 iConfig++;
120 }
121 }
122 }else{
123 if( iConfig==0 && (iMask & CONFIGSET_ALL)==CONFIGSET_ALL ){
124 iConfig = count(aGroupName);
125 return "/all";
126 }
127 while( iConfig<count(aGroupName)-1 ){
128 if( aGroupName[iConfig].groupMask & iMask ){
129 return aGroupName[iConfig++].zName;
130 }else{
131 iConfig++;
132 }
133 }
134 }
135 return 0;
136 }
137
138 /*
139 ** Return the mask for the named configuration parameter if it can be
140 ** safely exported. Return 0 if the parameter is not safe to export.
141 **
142 ** "Safe" in the previous paragraph means the permission is created to
143 ** export the property. In other words, the requesting side has presented
144 ** login credentials and has sufficient capabilities to access the requested
145 ** information.
146 */
147 int configure_is_exportable(const char *zName){
148 int i;
149 int n = strlen(zName);
150 if( n>2 && zName[0]=='\'' && zName[n-1]=='\'' ){
151 zName++;
152 n -= 2;
153 }
154 for(i=0; i<count(aConfig); i++){
155 if( memcmp(zName, aConfig[i].zName, n)==0 && aConfig[i].zName[n]==0 ){
156 int m = aConfig[i].groupMask;
157 if( !g.okAdmin ){
158 m &= ~CONFIGSET_USER;
159 }
160 if( !g.okRdAddr ){
@@ -194,38 +222,39 @@
222 }
223
224 /*
225 ** Two SQL functions:
226 **
227 ** config_is_reset(int)
228 ** config_reset(int)
229 **
230 ** The config_is_reset() function takes the integer valued argument and
231 ** ANDs it against the static variable "configHasBeenReset" below. The
232 ** function returns TRUE or FALSE depending on the result depending on
233 ** whether or not the corresponding configuration table has been reset. The
234 ** config_reset() function adds the bits to "configHasBeenReset" that
235 ** are given in the argument.
236 **
237 ** These functions are used below in the WHEN clause of a trigger to
238 ** get the trigger to fire exactly once.
239 */
240 static int configHasBeenReset = 0;
241 static void config_is_reset_function(
242 sqlite3_context *context,
243 int argc,
244 sqlite3_value **argv
245 ){
246 int m = sqlite3_value_int(argv[0]);
247 sqlite3_result_int(context, (configHasBeenReset&m)!=0 );
248 }
249 static void config_reset_function(
250 sqlite3_context *context,
251 int argc,
252 sqlite3_value **argv
253 ){
254 int m = sqlite3_value_int(argv[0]);
255 configHasBeenReset |= m;
256 }
257
258 /*
259 ** Create the temporary _xfer_reportfmt and _xfer_user tables that are
260 ** necessary in order to evalute the SQL text generated by the
@@ -255,12 +284,14 @@
284 @ ipaddr TEXT, -- IP address for which cookie is valid
285 @ cexpire DATETIME, -- Time when cookie expires
286 @ info TEXT, -- contact information
287 @ photo BLOB -- JPEG image of this user
288 @ );
289 @ INSERT INTO _xfer_reportfmt
290 @ SELECT rn,owner,title,cols,sqlcode FROM reportfmt;
291 @ INSERT INTO _xfer_user
292 @ SELECT uid,login,pw,cap,cookie,ipaddr,cexpire,info,photo FROM user;
293 ;
294 db_multi_exec(zSQL1);
295
296 /* When the replace flag is set, add triggers that run the first time
297 ** that new data is seen. The triggers run only once and delete all the
@@ -267,30 +298,30 @@
298 ** existing data.
299 */
300 if( replaceFlag ){
301 static const char zSQL2[] =
302 @ CREATE TRIGGER _xfer_r1 BEFORE INSERT ON _xfer_reportfmt
303 @ WHEN NOT config_is_reset(2) BEGIN
304 @ DELETE FROM _xfer_reportfmt;
305 @ SELECT config_reset(2);
306 @ END;
307 @ CREATE TRIGGER _xfer_r2 BEFORE INSERT ON _xfer_user
308 @ WHEN NOT config_is_reset(16) BEGIN
309 @ DELETE FROM _xfer_user;
310 @ SELECT config_reset(16);
311 @ END;
312 @ CREATE TEMP TRIGGER _xfer_r3 BEFORE INSERT ON shun
313 @ WHEN NOT config_is_reset(8) BEGIN
314 @ DELETE FROM shun;
315 @ SELECT config_reset(8);
316 @ END;
317 ;
318 sqlite3_create_function(g.db, "config_is_reset", 1, SQLITE_UTF8, 0,
319 config_is_reset_function, 0, 0);
320 sqlite3_create_function(g.db, "config_reset", 1, SQLITE_UTF8, 0,
321 config_reset_function, 0, 0);
322 configHasBeenReset = 0;
323 db_multi_exec(zSQL2);
324 }
325 }
326
327 /*
@@ -306,66 +337,390 @@
337 @ DROP TABLE _xfer_user;
338 @ DROP TABLE _xfer_reportfmt;
339 ;
340 db_multi_exec(zSQL);
341 }
342
343 /*
344 ** Return true if z[] is not a "safe" SQL token. A safe token is one of:
345 **
346 ** * A string literal
347 ** * A blob literal
348 ** * An integer literal (no floating point)
349 ** * NULL
350 */
351 static int safeSql(const char *z){
352 int i;
353 if( z==0 || z[0]==0 ) return 0;
354 if( (z[0]=='x' || z[0]=='X') && z[1]=='\'' ) z++;
355 if( z[0]=='\'' ){
356 for(i=1; z[i]; i++){
357 if( z[i]=='\'' ){
358 i++;
359 if( z[i]=='\'' ){ continue; }
360 return z[i]==0;
361 }
362 }
363 return 0;
364 }else{
365 char c;
366 for(i=0; (c = z[i])!=0; i++){
367 if( !fossil_isalnum(c) ) return 0;
368 }
369 }
370 return 1;
371 }
372
373 /*
374 ** Return true if z[] consists of nothing but digits
375 */
376 static int safeInt(const char *z){
377 int i;
378 if( z==0 || z[0]==0 ) return 0;
379 for(i=0; fossil_isdigit(z[i]); i++){}
380 return z[i]==0;
381 }
382
383 /*
384 ** Process a single "config" card received from the other side of a
385 ** sync session.
386 **
387 ** Mask consists of one or more CONFIGSET_* values ORed together, to
388 ** designate what types of configuration we are allowed to receive.
389 **
390 ** NEW FORMAT:
391 **
392 ** zName is one of "/config", "/user", "/shun", "/reportfmt", or "/concealed".
393 ** zName indicates the table that holds the configuration information being
394 ** transferred. pContent is a string that consist of alternating Fossil
395 ** and SQL tokens. The First token is a timestamp in seconds since 1970.
396 ** The second token is a primary key for the table identified by zName. If
397 ** The entry with the corresponding primary key exists and has a more recent
398 ** mtime, then nothing happens. If the entry does not exist or if it has
399 ** an older mtime, then the content described by subsequent token pairs is
400 ** inserted. The first element of each token pair is a column name and
401 ** the second is its value.
402 **
403 ** In overview, we have:
404 **
405 ** NAME CONTENT
406 ** ------- -----------------------------------------------------------
407 ** /config $MTIME $NAME value $VALUE
408 ** /user $MTIME $LOGIN pw $VALUE cap $VALUE info $VALUE photo $VALUE
409 ** /shun $MTIME $UUID scom $VALUE
410 ** /reportfmt $MTIME $TITLE owner $VALUE cols $VALUE sqlcode $VALUE
411 ** /concealed $MTIME $HASH content $VALUE
412 **
413 ** OLD FORMAT:
414 **
415 ** The old format is retained for backwards compatiblity, but is deprecated.
416 ** The cutover from old format to new was on 2011-04-25. After sufficient
417 ** time has passed, support for the old format will be removed.
418 **
419 ** zName is either the NAME of an element of the CONFIG table, or else
420 ** one of the special names "@shun", "@reportfmt", "@user", or "@concealed".
421 ** If zName is a CONFIG table name, then CONTENT replaces (overwrites) the
422 ** element in the CONFIG table. For one of the @-labels, CONTENT is raw
423 ** SQL that is evaluated. Note that the raw SQL in CONTENT might not
424 ** insert directly into the target table but might instead use a proxy
425 ** table like _fer_reportfmt or _xfer_user. Such tables must be created
426 ** ahead of time using configure_prepare_to_receive(). Then after multiple
427 ** calls to this routine, configure_finalize_receive() to transfer the
428 ** information received into the true target table.
429 */
430 void configure_receive(const char *zName, Blob *pContent, int groupMask){
431 if( zName[0]=='/' ){
432 /* The new format */
433 char *azToken[12];
434 int nToken = 0;
435 int ii, jj;
436 int thisMask;
437 Blob name, value, sql;
438 static const struct receiveType {
439 const char *zName;
440 const char *zPrimKey;
441 int nField;
442 const char *azField[4];
443 } aType[] = {
444 { "/config", "name", 1, { "value", 0, 0, 0 } },
445 { "@user", "login", 4, { "pw", "cap", "info", "photo" } },
446 { "@shun", "uuid", 1, { "scom", 0, 0, 0 } },
447 { "@reportfmt", "title", 3, { "owner", "cols", "sqlcode", 0 } },
448 { "@concealed", "hash", 1, { "content", 0, 0, 0 } },
449 };
450 for(ii=0; ii<count(aType); ii++){
451 if( fossil_strcmp(&aType[ii].zName[1],&zName[1])==0 ) break;
452 }
453 if( ii>=count(aType) ) return;
454 while( blob_token(pContent, &name) && blob_sqltoken(pContent, &value) ){
455 char *z = blob_terminate(&name);
456 if( !safeSql(z) ) return;
457 if( nToken>0 ){
458 for(jj=0; jj<aType[ii].nField; jj++){
459 if( fossil_strcmp(aType[ii].azField[jj], z)==0 ) break;
460 }
461 if( jj>=aType[ii].nField ) continue;
462 }else{
463 if( !safeInt(z) ) return;
464 }
465 azToken[nToken++] = z;
466 azToken[nToken++] = z = blob_terminate(&value);
467 if( !safeSql(z) ) return;
468 if( nToken>=count(azToken) ) break;
469 }
470 if( nToken<2 ) return;
471 if( aType[ii].zName[0]=='/' ){
472 thisMask = configure_is_exportable(azToken[1]);
473 }else{
474 thisMask = configure_is_exportable(aType[ii].zName);
475 }
476 if( (thisMask & groupMask)==0 ) return;
477
478 blob_zero(&sql);
479 if( groupMask & CONFIGSET_OVERWRITE ){
480 if( (thisMask & configHasBeenReset)==0 && aType[ii].zName[0]!='/' ){
481 db_multi_exec("DELETE FROM %s", &aType[ii].zName[1]);
482 configHasBeenReset |= thisMask;
483 }
484 blob_append(&sql, "REPLACE INTO ", -1);
485 }else{
486 blob_append(&sql, "INSERT OR IGNORE INTO ", -1);
487 }
488 blob_appendf(&sql, "%s(%s, mtime", &zName[1], aType[ii].zPrimKey);
489 for(jj=2; jj<nToken; jj+=2){
490 blob_appendf(&sql, ",%s", azToken[jj]);
491 }
492 blob_appendf(&sql,") VALUES(%s,%s", azToken[1], azToken[0]);
493 for(jj=2; jj<nToken; jj+=2){
494 blob_appendf(&sql, ",%s", azToken[jj+1]);
495 }
496 db_multi_exec("%s)", blob_str(&sql));
497 if( db_changes()==0 ){
498 blob_reset(&sql);
499 blob_appendf(&sql, "UPDATE %s SET mtime=%s", &zName[1], azToken[0]);
500 for(jj=2; jj<nToken; jj+=2){
501 blob_appendf(&sql, ", %s=%s", azToken[jj], azToken[jj+1]);
502 }
503 blob_appendf(&sql, " WHERE %s=%s AND mtime<%s",
504 aType[ii].zPrimKey, azToken[1], azToken[0]);
505 db_multi_exec("%s", blob_str(&sql));
506 }
507 blob_reset(&sql);
508 }else{
509 /* Otherwise, the old format */
510 if( (configure_is_exportable(zName) & groupMask)==0 ) return;
511 if( strcmp(zName, "logo-image")==0 ){
512 Stmt ins;
513 db_prepare(&ins,
514 "REPLACE INTO config(name, value, mtime) VALUES(:name, :value, now())"
515 );
516 db_bind_text(&ins, ":name", zName);
517 db_bind_blob(&ins, ":value", pContent);
518 db_step(&ins);
519 db_finalize(&ins);
520 }else if( zName[0]=='@' ){
521 /* Notice that we are evaluating arbitrary SQL received from the
522 ** client. But this can only happen if the client has authenticated
523 ** as an administrator, so presumably we trust the client at this
524 ** point.
525 */
526 db_multi_exec("%s", blob_str(pContent));
527 }else{
528 db_multi_exec(
529 "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
530 zName, blob_str(pContent)
531 );
532 }
533 }
534 }
535
536 /*
537 ** Process a file full of "config" cards.
538 */
539 void configure_receive_all(Blob *pIn, int groupMask){
540 Blob line;
541 int nToken;
542 int size;
543 Blob aToken[4];
544
545 configHasBeenReset = 0;
546 while( blob_line(pIn, &line) ){
547 if( blob_buffer(&line)[0]=='#' ) continue;
548 nToken = blob_tokenize(&line, aToken, count(aToken));
549 if( blob_eq(&aToken[0],"config")
550 && nToken==3
551 && blob_is_int(&aToken[2], &size)
552 ){
553 const char *zName = blob_str(&aToken[1]);
554 Blob content;
555 blob_zero(&content);
556 blob_extract(pIn, size, &content);
557 g.okAdmin = g.okRdAddr = 1;
558 configure_receive(zName, &content, groupMask);
559 blob_reset(&content);
560 blob_seek(pIn, 1, BLOB_SEEK_CUR);
561 }
562 }
563 }
564
565
566 /*
567 ** Send "config" cards using the new format for all elements of a group
568 ** that have recently changed.
569 **
570 ** Output goes into pOut. The groupMask identifies the group(s) to be sent.
571 ** Send only entries whose timestamp is later than or equal to iStart.
572 **
573 ** Return the number of cards sent.
574 */
575 int configure_send_group(
576 Blob *pOut, /* Write output here */
577 int groupMask, /* Mask of groups to be send */
578 sqlite3_int64 iStart /* Only write values changed since this time */
579 ){
580 Stmt q;
581 Blob rec;
582 int ii;
583 int nCard = 0;
584
585 blob_zero(&rec);
586 if( groupMask & CONFIGSET_SHUN ){
587 db_prepare(&q, "SELECT mtime, quote(uuid), quote(scom) FROM shun"
588 " WHERE mtime>=%lld", iStart);
589 while( db_step(&q)==SQLITE_ROW ){
590 blob_appendf(&rec,"%s %s scom %s",
591 db_column_text(&q, 0),
592 db_column_text(&q, 1),
593 db_column_text(&q, 2)
594 );
595 blob_appendf(pOut, "config /shun %d\n%s\n",
596 blob_size(&rec), blob_str(&rec));
597 nCard++;
598 blob_reset(&rec);
599 }
600 db_finalize(&q);
601 }
602 if( groupMask & CONFIGSET_USER ){
603 db_prepare(&q, "SELECT mtime, quote(login), quote(pw), quote(cap),"
604 " quote(info), quote(photo) FROM user"
605 " WHERE mtime>=%lld", iStart);
606 while( db_step(&q)==SQLITE_ROW ){
607 blob_appendf(&rec,"%s %s pw %s cap %s info %s photo %s",
608 db_column_text(&q, 0),
609 db_column_text(&q, 1),
610 db_column_text(&q, 2),
611 db_column_text(&q, 3),
612 db_column_text(&q, 4),
613 db_column_text(&q, 5)
614 );
615 blob_appendf(pOut, "config /user %d\n%s\n",
616 blob_size(&rec), blob_str(&rec));
617 nCard++;
618 blob_reset(&rec);
619 }
620 db_finalize(&q);
621 }
622 if( groupMask & CONFIGSET_TKT ){
623 db_prepare(&q, "SELECT mtime, quote(title), quote(owner), quote(cols),"
624 " quote(sqlcode) FROM reportfmt"
625 " WHERE mtime>=%lld", iStart);
626 while( db_step(&q)==SQLITE_ROW ){
627 blob_appendf(&rec,"%s %s owner %s cols %s sqlcode %s",
628 db_column_text(&q, 0),
629 db_column_text(&q, 1),
630 db_column_text(&q, 2),
631 db_column_text(&q, 3),
632 db_column_text(&q, 4)
633 );
634 blob_appendf(pOut, "config /reportfmt %d\n%s\n",
635 blob_size(&rec), blob_str(&rec));
636 nCard++;
637 blob_reset(&rec);
638 }
639 db_finalize(&q);
640 }
641 if( groupMask & CONFIGSET_ADDR ){
642 db_prepare(&q, "SELECT mtime, quote(hash), quote(content) FROM concealed"
643 " WHERE mtime>=%lld", iStart);
644 while( db_step(&q)==SQLITE_ROW ){
645 blob_appendf(&rec,"%s %s content %s",
646 db_column_text(&q, 0),
647 db_column_text(&q, 1),
648 db_column_text(&q, 2)
649 );
650 blob_appendf(pOut, "config /concealed %d\n%s\n",
651 blob_size(&rec), blob_str(&rec));
652 nCard++;
653 blob_reset(&rec);
654 }
655 db_finalize(&q);
656 }
657 db_prepare(&q, "SELECT mtime, quote(name), quote(value) FROM config"
658 " WHERE name=:name AND mtime>=%lld", iStart);
659 for(ii=0; ii<count(aConfig); ii++){
660 if( (aConfig[ii].groupMask & groupMask)!=0 && aConfig[ii].zName[0]!='@' ){
661 db_bind_text(&q, ":name", aConfig[ii].zName);
662 while( db_step(&q)==SQLITE_ROW ){
663 blob_appendf(&rec,"%s %s value %s",
664 db_column_text(&q, 0),
665 db_column_text(&q, 1),
666 db_column_text(&q, 2)
667 );
668 blob_appendf(pOut, "config /config %d\n%s\n",
669 blob_size(&rec), blob_str(&rec));
670 nCard++;
671 blob_reset(&rec);
672 }
673 db_reset(&q);
674 }
675 }
676 db_finalize(&q);
677 return nCard;
678 }
679
680 /*
681 ** Identify a configuration group by name. Return its mask.
682 ** Throw an error if no match.
683 */
684 int configure_name_to_mask(const char *z, int notFoundIsFatal){
685 int i;
686 int n = strlen(z);
687 for(i=0; i<count(aGroupName); i++){
688 if( strncmp(z, &aGroupName[i].zName[1], n)==0 ){
689 return aGroupName[i].groupMask;
690 }
691 }
692 if( notFoundIsFatal ){
693 fossil_print("Available configuration areas:\n");
694 for(i=0; i<count(aGroupName); i++){
695 fossil_print(" %-10s %s\n", &aGroupName[i].zName[1], aGroupName[i].zHelp);
696 }
697 fossil_fatal("no such configuration area: \"%s\"", z);
698 }
 
699 return 0;
700 }
701
702 /*
703 ** Write SQL text into file zFilename that will restore the configuration
704 ** area identified by mask to its current state from any other state.
705 */
706 static void export_config(
707 int groupMask, /* Mask indicating which configuration to export */
708 const char *zMask, /* Name of the configuration */
709 sqlite3_int64 iStart, /* Start date */
710 const char *zFilename /* Write into this file */
711 ){
 
712 Blob out;
713 blob_zero(&out);
714 blob_appendf(&out,
715 "# The \"%s\" configuration exported from\n"
716 "# repository \"%s\"\n"
717 "# on %s\n",
718 zMask, g.zRepositoryName,
719 db_text(0, "SELECT datetime('now')")
720 );
721 configure_send_group(&out, groupMask, iStart);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
722 blob_write_to_file(&out, zFilename);
723 blob_reset(&out);
724 }
725
726
@@ -395,25 +750,31 @@
750 **
751 ** %fossil configuration pull AREA ?URL?
752 **
753 ** Pull and install the configuration from a different server
754 ** identified by URL. If no URL is specified, then the default
755 ** server is used. Use the --legacy option for the older protocol
756 ** (when talking to servers compiled prior to 2011-04-27.) Use
757 ** the --overwrite flag to completely replace local settings with
758 ** content received from URL.
759 **
760 ** %fossil configuration push AREA ?URL?
761 **
762 ** Push the local configuration into the remote server identified
763 ** by URL. Admin privilege is required on the remote server for
764 ** this to work. When the same record exists both locally and on
765 ** the remote end, the one that was most recently changed wins.
766 ** Use the --legacy flag when talking to holder servers.
767 **
768 ** %fossil configuration reset AREA
769 **
770 ** Restore the configuration to the default. AREA as above.
771 **
772 ** %fossil configuration sync AREA ?URL?
773 **
774 ** Synchronize configuration changes in the local repository with
775 ** the remote repository at URL.
776 **
777 **
778 ** SUMMARY: fossil configure METHOD ... ?-R|--repository REPOSITORY?
779 ** Where: METHOD = export, import, merge, pull, push or reset
780 **
@@ -438,36 +799,59 @@
799 db_find_and_open_repository(0, 0);
800 zMethod = g.argv[2];
801 n = strlen(zMethod);
802 if( strncmp(zMethod, "export", n)==0 ){
803 int mask;
804 const char *zSince = find_option("since",0,1);
805 sqlite3_int64 iStart;
806 if( g.argc!=5 ){
807 usage("export AREA FILENAME");
808 }
809 mask = configure_name_to_mask(g.argv[3], 1);
810 if( zSince ){
811 iStart = db_multi_exec(
812 "SELECT coalesce(strftime('%%s',%Q),strftime('%%s','now',%Q))+0",
813 zSince, zSince
814 );
815 }else{
816 iStart = 0;
817 }
818 export_config(mask, g.argv[3], iStart, g.argv[4]);
819 }else
820 if( strncmp(zMethod, "import", n)==0
821 || strncmp(zMethod, "merge", n)==0 ){
822 Blob in;
823 int groupMask;
824 if( g.argc!=4 ) usage(mprintf("%s FILENAME",zMethod));
825 blob_read_from_file(&in, g.argv[3]);
826 db_begin_transaction();
827 if( zMethod[0]=='i' ){
828 groupMask = CONFIGSET_ALL | CONFIGSET_OVERWRITE;
829 }else{
830 groupMask = CONFIGSET_ALL;
831 }
832 configure_receive_all(&in, groupMask);
833 db_end_transaction(0);
834 }else
835 if( strncmp(zMethod, "pull", n)==0
836 || strncmp(zMethod, "push", n)==0
837 || strncmp(zMethod, "sync", n)==0
838 ){
839 int mask;
840 const char *zServer;
841 const char *zPw;
842 int legacyFlag = 0;
843 int overwriteFlag = 0;
844 if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
845 if( strncmp(zMethod,"pull",n)==0 ){
846 overwriteFlag = find_option("overwrite",0,0)!=0;
847 }
848 url_proxy_options();
849 if( g.argc!=4 && g.argc!=5 ){
850 usage("pull AREA ?URL?");
851 }
852 mask = configure_name_to_mask(g.argv[3], 1);
853 if( g.argc==5 ){
854 zServer = g.argv[4];
855 zPw = 0;
856 g.dontKeepUrl = 1;
857 }else{
@@ -479,25 +863,29 @@
863 }
864 url_parse(zServer);
865 if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
866 user_select();
867 url_enable_proxy("via proxy: ");
868 if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
869 if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
870 if( strncmp(zMethod, "push", n)==0 ){
871 client_sync(0,0,0,0,0,mask);
872 }else if( strncmp(zMethod, "pull", n)==0 ){
873 client_sync(0,0,0,0,mask,0);
874 }else{
875 client_sync(0,0,0,0,mask,mask);
876 }
877 }else
878 if( strncmp(zMethod, "reset", n)==0 ){
879 int mask, i;
880 char *zBackup;
881 if( g.argc!=4 ) usage("reset AREA");
882 mask = configure_name_to_mask(g.argv[3], 1);
883 zBackup = db_text(0,
884 "SELECT strftime('config-backup-%%Y%%m%%d%%H%%M%%f','now')");
885 db_begin_transaction();
886 export_config(mask, g.argv[3], 0, zBackup);
887 for(i=0; i<count(aConfig); i++){
888 const char *zName = aConfig[i].zName;
889 if( (aConfig[i].groupMask & mask)==0 ) continue;
890 if( zName[0]!='@' ){
891 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -511,14 +899,14 @@
899 }else if( fossil_strcmp(zName,"@reportfmt")==0 ){
900 db_multi_exec("DELETE FROM reportfmt");
901 }
902 }
903 db_end_transaction(0);
904 fossil_print("Configuration reset to factory defaults.\n");
905 fossil_print("To recover, use: %s %s import %s\n",
906 fossil_nameofexe(), g.argv[1], zBackup);
907 }else
908 {
909 fossil_fatal("METHOD should be one of:"
910 " export import merge pull push reset");
911 }
912 }
913
+9 -5
--- src/content.c
+++ src/content.c
@@ -79,11 +79,15 @@
7979
** The cache will deallocate memory when it has finished with it.
8080
*/
8181
void content_cache_insert(int rid, Blob *pBlob){
8282
struct cacheLine *p;
8383
if( contentCache.n>500 || contentCache.szTotal>50000000 ){
84
- content_cache_expire_oldest();
84
+ i64 szBefore;
85
+ do{
86
+ szBefore = contentCache.szTotal;
87
+ content_cache_expire_oldest();
88
+ }while( contentCache.szTotal>50000000 && contentCache.szTotal<szBefore );
8589
}
8690
if( contentCache.n>=contentCache.nAlloc ){
8791
contentCache.nAlloc = contentCache.nAlloc*2 + 10;
8892
contentCache.a = fossil_realloc(contentCache.a,
8993
contentCache.nAlloc*sizeof(contentCache.a[0]));
@@ -666,11 +670,11 @@
666670
if( g.argc!=3 ) usage("FILENAME");
667671
db_must_be_within_tree();
668672
user_select();
669673
blob_read_from_file(&content, g.argv[2]);
670674
rid = content_put(&content);
671
- printf("inserted as record %d\n", rid);
675
+ fossil_print("inserted as record %d\n", rid);
672676
}
673677
674678
/*
675679
** Make sure the content at rid is the original content and is not a
676680
** delta.
@@ -834,14 +838,14 @@
834838
while( db_step(&q)==SQLITE_ROW ){
835839
int rid = db_column_int(&q, 0);
836840
const char *zUuid = db_column_text(&q, 1);
837841
int size = db_column_int(&q, 2);
838842
n1++;
839
- printf(" %d/%d\r", n1, total);
843
+ fossil_print(" %d/%d\r", n1, total);
840844
fflush(stdout);
841845
if( size<0 ){
842
- printf("skip phantom %d %s\n", rid, zUuid);
846
+ fossil_print("skip phantom %d %s\n", rid, zUuid);
843847
continue; /* Ignore phantoms */
844848
}
845849
content_get(rid, &content);
846850
if( blob_size(&content)!=size ){
847851
fossil_warning("size mismatch on blob rid=%d: %d vs %d",
@@ -855,7 +859,7 @@
855859
blob_reset(&cksum);
856860
blob_reset(&content);
857861
n2++;
858862
}
859863
db_finalize(&q);
860
- printf("%d non-phantom blobs (out of %d total) verified\n", n2, n1);
864
+ fossil_print("%d non-phantom blobs (out of %d total) verified\n", n2, n1);
861865
}
862866
--- src/content.c
+++ src/content.c
@@ -79,11 +79,15 @@
79 ** The cache will deallocate memory when it has finished with it.
80 */
81 void content_cache_insert(int rid, Blob *pBlob){
82 struct cacheLine *p;
83 if( contentCache.n>500 || contentCache.szTotal>50000000 ){
84 content_cache_expire_oldest();
 
 
 
 
85 }
86 if( contentCache.n>=contentCache.nAlloc ){
87 contentCache.nAlloc = contentCache.nAlloc*2 + 10;
88 contentCache.a = fossil_realloc(contentCache.a,
89 contentCache.nAlloc*sizeof(contentCache.a[0]));
@@ -666,11 +670,11 @@
666 if( g.argc!=3 ) usage("FILENAME");
667 db_must_be_within_tree();
668 user_select();
669 blob_read_from_file(&content, g.argv[2]);
670 rid = content_put(&content);
671 printf("inserted as record %d\n", rid);
672 }
673
674 /*
675 ** Make sure the content at rid is the original content and is not a
676 ** delta.
@@ -834,14 +838,14 @@
834 while( db_step(&q)==SQLITE_ROW ){
835 int rid = db_column_int(&q, 0);
836 const char *zUuid = db_column_text(&q, 1);
837 int size = db_column_int(&q, 2);
838 n1++;
839 printf(" %d/%d\r", n1, total);
840 fflush(stdout);
841 if( size<0 ){
842 printf("skip phantom %d %s\n", rid, zUuid);
843 continue; /* Ignore phantoms */
844 }
845 content_get(rid, &content);
846 if( blob_size(&content)!=size ){
847 fossil_warning("size mismatch on blob rid=%d: %d vs %d",
@@ -855,7 +859,7 @@
855 blob_reset(&cksum);
856 blob_reset(&content);
857 n2++;
858 }
859 db_finalize(&q);
860 printf("%d non-phantom blobs (out of %d total) verified\n", n2, n1);
861 }
862
--- src/content.c
+++ src/content.c
@@ -79,11 +79,15 @@
79 ** The cache will deallocate memory when it has finished with it.
80 */
81 void content_cache_insert(int rid, Blob *pBlob){
82 struct cacheLine *p;
83 if( contentCache.n>500 || contentCache.szTotal>50000000 ){
84 i64 szBefore;
85 do{
86 szBefore = contentCache.szTotal;
87 content_cache_expire_oldest();
88 }while( contentCache.szTotal>50000000 && contentCache.szTotal<szBefore );
89 }
90 if( contentCache.n>=contentCache.nAlloc ){
91 contentCache.nAlloc = contentCache.nAlloc*2 + 10;
92 contentCache.a = fossil_realloc(contentCache.a,
93 contentCache.nAlloc*sizeof(contentCache.a[0]));
@@ -666,11 +670,11 @@
670 if( g.argc!=3 ) usage("FILENAME");
671 db_must_be_within_tree();
672 user_select();
673 blob_read_from_file(&content, g.argv[2]);
674 rid = content_put(&content);
675 fossil_print("inserted as record %d\n", rid);
676 }
677
678 /*
679 ** Make sure the content at rid is the original content and is not a
680 ** delta.
@@ -834,14 +838,14 @@
838 while( db_step(&q)==SQLITE_ROW ){
839 int rid = db_column_int(&q, 0);
840 const char *zUuid = db_column_text(&q, 1);
841 int size = db_column_int(&q, 2);
842 n1++;
843 fossil_print(" %d/%d\r", n1, total);
844 fflush(stdout);
845 if( size<0 ){
846 fossil_print("skip phantom %d %s\n", rid, zUuid);
847 continue; /* Ignore phantoms */
848 }
849 content_get(rid, &content);
850 if( blob_size(&content)!=size ){
851 fossil_warning("size mismatch on blob rid=%d: %d vs %d",
@@ -855,7 +859,7 @@
859 blob_reset(&cksum);
860 blob_reset(&content);
861 n2++;
862 }
863 db_finalize(&q);
864 fossil_print("%d non-phantom blobs (out of %d total) verified\n", n2, n1);
865 }
866
+60 -47
--- src/db.c
+++ src/db.c
@@ -34,10 +34,11 @@
3434
#endif
3535
#include <sqlite3.h>
3636
#include <sys/types.h>
3737
#include <sys/stat.h>
3838
#include <unistd.h>
39
+#include <time.h>
3940
#include "db.h"
4041
4142
#if INTERFACE
4243
/*
4344
** An single SQL statement is represented as an instance of the following
@@ -80,19 +81,29 @@
8081
db_force_rollback();
8182
fossil_exit(1);
8283
}
8384
8485
static int nBegin = 0; /* Nesting depth of BEGIN */
85
-static int isNewRepo = 0; /* True if the repository is newly created */
8686
static int doRollback = 0; /* True to force a rollback */
8787
static int nCommitHook = 0; /* Number of commit hooks */
8888
static struct sCommitHook {
8989
int (*xHook)(void); /* Functions to call at db_end_transaction() */
9090
int sequence; /* Call functions in sequence order */
9191
} aHook[5];
9292
static Stmt *pAllStmt = 0; /* List of all unfinalized statements */
9393
static int nPrepare = 0; /* Number of calls to sqlite3_prepare() */
94
+static int nDeleteOnFail = 0; /* Number of entries in azDeleteOnFail[] */
95
+static char *azDeleteOnFail[3]; /* Files to delete on a failure */
96
+
97
+
98
+/*
99
+** Arrange for the given file to be deleted on a failure.
100
+*/
101
+void db_delete_on_failure(const char *zFilename){
102
+ assert( nDeleteOnFail<count(azDeleteOnFail) );
103
+ azDeleteOnFail[nDeleteOnFail++] = fossil_strdup(zFilename);
104
+}
94105
95106
/*
96107
** This routine is called by the SQLite commit-hook mechanism
97108
** just prior to each commit. All this routine does is verify
98109
** that nBegin really is zero. That insures that transactions
@@ -140,10 +151,11 @@
140151
141152
/*
142153
** Force a rollback and shutdown the database
143154
*/
144155
void db_force_rollback(void){
156
+ int i;
145157
static int busy = 0;
146158
if( busy || g.db==0 ) return;
147159
busy = 1;
148160
undo_rollback();
149161
while( pAllStmt ){
@@ -150,17 +162,16 @@
150162
db_finalize(pAllStmt);
151163
}
152164
if( nBegin ){
153165
sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
154166
nBegin = 0;
155
- if( isNewRepo ){
156
- db_close(0);
157
- unlink(g.zRepositoryName);
158
- }
159167
}
160168
busy = 0;
161169
db_close(0);
170
+ for(i=0; i<nDeleteOnFail; i++){
171
+ file_delete(azDeleteOnFail[i]);
172
+ }
162173
}
163174
164175
/*
165176
** Install a commit hook. Hooks are installed in sequence order.
166177
** It is an error to install the same commit hook more than once.
@@ -564,14 +575,10 @@
564575
}
565576
db_finalize(&s);
566577
return z;
567578
}
568579
569
-#if defined(_WIN32)
570
-extern char *sqlite3_win32_mbcs_to_utf8(const char*);
571
-#endif
572
-
573580
/*
574581
** Initialize a new database file with the given schema. If anything
575582
** goes wrong, call db_err() to exit.
576583
*/
577584
void db_init_database(
@@ -582,13 +589,10 @@
582589
sqlite3 *db;
583590
int rc;
584591
const char *zSql;
585592
va_list ap;
586593
587
-#if defined(_WIN32)
588
- zFileName = sqlite3_win32_mbcs_to_utf8(zFileName);
589
-#endif
590594
rc = sqlite3_open(zFileName, &db);
591595
if( rc!=SQLITE_OK ){
592596
db_err(sqlite3_errmsg(db));
593597
}
594598
sqlite3_busy_timeout(db, 5000);
@@ -606,10 +610,23 @@
606610
}
607611
va_end(ap);
608612
sqlite3_exec(db, "COMMIT", 0, 0, 0);
609613
sqlite3_close(db);
610614
}
615
+
616
+/*
617
+** Function to return the number of seconds since 1970. This is
618
+** the same as strftime('%s','now') but is more compact.
619
+*/
620
+static void db_now_function(
621
+ sqlite3_context *context,
622
+ int argc,
623
+ sqlite3_value **argv
624
+){
625
+ sqlite3_result_int64(context, time(0));
626
+}
627
+
611628
612629
/*
613630
** Open a database file. Return a pointer to the new database
614631
** connection. An error results in process abort.
615632
*/
@@ -617,13 +634,10 @@
617634
int rc;
618635
const char *zVfs;
619636
sqlite3 *db;
620637
621638
zVfs = getenv("FOSSIL_VFS");
622
-#if defined(_WIN32)
623
- zDbName = sqlite3_win32_mbcs_to_utf8(zDbName);
624
-#endif
625639
rc = sqlite3_open_v2(
626640
zDbName, &db,
627641
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
628642
zVfs
629643
);
@@ -630,10 +644,11 @@
630644
if( rc!=SQLITE_OK ){
631645
db_err(sqlite3_errmsg(db));
632646
}
633647
sqlite3_busy_timeout(db, 5000);
634648
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
649
+ sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
635650
return db;
636651
}
637652
638653
639654
/*
@@ -645,13 +660,10 @@
645660
if( !g.db ){
646661
g.db = openDatabase(zDbName);
647662
g.zMainDbType = zLabel;
648663
db_connection_init();
649664
}else{
650
-#if defined(_WIN32)
651
- zDbName = sqlite3_win32_mbcs_to_utf8(zDbName);
652
-#endif
653665
db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel);
654666
}
655667
}
656668
657669
/*
@@ -673,17 +685,21 @@
673685
#if defined(_WIN32)
674686
zHome = getenv("LOCALAPPDATA");
675687
if( zHome==0 ){
676688
zHome = getenv("APPDATA");
677689
if( zHome==0 ){
690
+ char *zDrive = getenv("HOMEDRIVE");
678691
zHome = getenv("HOMEPATH");
692
+ if( zDrive && zHome ) zHome = mprintf("%s%s", zDrive, zHome);
679693
}
680694
}
681695
if( zHome==0 ){
682696
fossil_fatal("cannot locate home directory - "
683
- "please set the HOMEPATH environment variable");
697
+ "please set the LOCALAPPDATA or APPDATA or HOMEPATH "
698
+ "environment variables");
684699
}
700
+ zHome = fossil_mbcs_to_utf8(zHome);
685701
#else
686702
zHome = getenv("HOME");
687703
if( zHome==0 ){
688704
fossil_fatal("cannot locate home directory - "
689705
"please set the HOME environment variable");
@@ -725,11 +741,11 @@
725741
static int isValidLocalDb(const char *zDbName){
726742
i64 lsize;
727743
int rc;
728744
sqlite3_stmt *pStmt;
729745
730
- if( access(zDbName, F_OK) ) return 0;
746
+ if( file_access(zDbName, F_OK) ) return 0;
731747
lsize = file_size(zDbName);
732748
if( lsize%1024!=0 || lsize<4096 ) return 0;
733749
db_open_or_attach(zDbName, "localdb");
734750
g.localOpen = 1;
735751
db_open_config(0);
@@ -788,23 +804,17 @@
788804
** is found, it is attached to the open database connection too.
789805
*/
790806
int db_open_local(void){
791807
int i, n;
792808
char zPwd[2000];
793
- char *zPwdConv;
794809
static const char *aDbName[] = { "/_FOSSIL_", "/.fos" };
795810
796811
if( g.localOpen) return 1;
797
- if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
798
- db_err("pwd too big: max %d", sizeof(zPwd)-20);
799
- }
812
+ file_getcwd(zPwd, sizeof(zPwd)-20);
800813
n = strlen(zPwd);
801
- zPwdConv = mprintf("%/", zPwd);
802
- strncpy(zPwd, zPwdConv, 2000-20);
803
- free(zPwdConv);
804814
while( n>0 ){
805
- if( access(zPwd, W_OK) ) break;
815
+ if( file_access(zPwd, W_OK) ) break;
806816
for(i=0; i<sizeof(aDbName)/sizeof(aDbName[0]); i++){
807817
sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "%s", aDbName[i]);
808818
if( isValidLocalDb(zPwd) ){
809819
/* Found a valid checkout database file */
810820
zPwd[n] = 0;
@@ -838,15 +848,15 @@
838848
}
839849
if( zDbName==0 ){
840850
db_err("unable to find the name of a repository database");
841851
}
842852
}
843
- if( access(zDbName, R_OK) || file_size(zDbName)<1024 ){
844
- if( access(zDbName, 0) ){
853
+ if( file_access(zDbName, R_OK) || file_size(zDbName)<1024 ){
854
+ if( file_access(zDbName, 0) ){
845855
fossil_panic("repository does not exist or"
846856
" is in an unreadable directory: %s", zDbName);
847
- }else if( access(zDbName, R_OK) ){
857
+ }else if( file_access(zDbName, R_OK) ){
848858
fossil_panic("read permission denied for repository %s", zDbName);
849859
}else{
850860
fossil_panic("not a valid repository: %s", zDbName);
851861
}
852862
}
@@ -949,11 +959,11 @@
949959
fossil_fatal("not in a local checkout");
950960
return;
951961
}
952962
file_canonical_name(g.argv[2], &repo);
953963
zRepo = blob_str(&repo);
954
- if( access(zRepo, 0) ){
964
+ if( file_access(zRepo, 0) ){
955965
fossil_fatal("no such file: %s", zRepo);
956966
}
957967
db_open_or_attach(zRepo, "test_repo");
958968
db_lset("repository", blob_str(&repo));
959969
db_close(1);
@@ -1041,11 +1051,11 @@
10411051
zFilename,
10421052
zRepositorySchema1,
10431053
zRepositorySchema2,
10441054
(char*)0
10451055
);
1046
- isNewRepo = 1;
1056
+ db_delete_on_failure(zFilename);
10471057
}
10481058
10491059
/*
10501060
** Create the default user accounts in the USER table.
10511061
*/
@@ -1105,14 +1115,14 @@
11051115
11061116
db_set("content-schema", CONTENT_SCHEMA, 0);
11071117
db_set("aux-schema", AUX_SCHEMA, 0);
11081118
if( makeServerCodes ){
11091119
db_multi_exec(
1110
- "INSERT INTO config(name,value)"
1111
- " VALUES('server-code', lower(hex(randomblob(20))));"
1112
- "INSERT INTO config(name,value)"
1113
- " VALUES('project-code', lower(hex(randomblob(20))));"
1120
+ "INSERT INTO config(name,value,mtime)"
1121
+ " VALUES('server-code', lower(hex(randomblob(20))),now());"
1122
+ "INSERT INTO config(name,value,mtime)"
1123
+ " VALUES('project-code', lower(hex(randomblob(20))),now());"
11141124
);
11151125
}
11161126
if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
11171127
if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
11181128
db_create_default_users(0, zDefaultUser);
@@ -1174,14 +1184,15 @@
11741184
db_open_repository(g.argv[2]);
11751185
db_open_config(0);
11761186
db_begin_transaction();
11771187
db_initial_setup(zDate, zDefaultUser, 1);
11781188
db_end_transaction(0);
1179
- printf("project-id: %s\n", db_get("project-code", 0));
1180
- printf("server-id: %s\n", db_get("server-code", 0));
1189
+ fossil_print("project-id: %s\n", db_get("project-code", 0));
1190
+ fossil_print("server-id: %s\n", db_get("server-code", 0));
11811191
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
1182
- printf("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
1192
+ fossil_print("admin-user: %s (initial password is \"%s\")\n",
1193
+ g.zLogin, zPassword);
11831194
}
11841195
11851196
/*
11861197
** SQL functions for debugging.
11871198
**
@@ -1195,11 +1206,11 @@
11951206
){
11961207
int i;
11971208
if( g.fSqlPrint ){
11981209
for(i=0; i<argc; i++){
11991210
char c = i==argc-1 ? '\n' : ' ';
1200
- printf("%s%c", sqlite3_value_text(argv[i]), c);
1211
+ fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
12011212
}
12021213
}
12031214
}
12041215
static void db_sql_trace(void *notUsed, const char *zSql){
12051216
int n = strlen(zSql);
@@ -1295,11 +1306,12 @@
12951306
sha1sum_step_text(zContent, n);
12961307
sha1sum_finish(&out);
12971308
sqlite3_snprintf(sizeof(zHash), zHash, "%s", blob_str(&out));
12981309
blob_reset(&out);
12991310
db_multi_exec(
1300
- "INSERT OR IGNORE INTO concealed VALUES(%Q,%#Q)",
1311
+ "INSERT OR IGNORE INTO concealed(hash,content,mtime)"
1312
+ " VALUES(%Q,%#Q,now())",
13011313
zHash, n, zContent
13021314
);
13031315
}
13041316
return zHash;
13051317
}
@@ -1406,11 +1418,11 @@
14061418
db_swap_connections();
14071419
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
14081420
zName, zValue);
14091421
db_swap_connections();
14101422
}else{
1411
- db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%Q)",
1423
+ db_multi_exec("REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
14121424
zName, zValue);
14131425
}
14141426
if( globalFlag && g.repositoryOpen ){
14151427
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
14161428
}
@@ -1465,11 +1477,11 @@
14651477
db_swap_connections();
14661478
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
14671479
zName, value);
14681480
db_swap_connections();
14691481
}else{
1470
- db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%d)",
1482
+ db_multi_exec("REPLACE INTO config(name,value,mtime) VALUES(%Q,%d,now())",
14711483
zName, value);
14721484
}
14731485
if( globalFlag && g.repositoryOpen ){
14741486
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
14751487
}
@@ -1550,10 +1562,11 @@
15501562
fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
15511563
}
15521564
file_canonical_name(g.argv[2], &path);
15531565
db_open_repository(blob_str(&path));
15541566
db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
1567
+ db_delete_on_failure("./_FOSSIL_");
15551568
db_open_local();
15561569
db_lset("repository", blob_str(&path));
15571570
db_record_repository_filename(blob_str(&path));
15581571
vid = db_int(0, "SELECT pid FROM plink y"
15591572
" WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)");
@@ -1597,14 +1610,14 @@
15971610
"SELECT '(global)', value FROM global_config WHERE name=%Q",
15981611
zName
15991612
);
16001613
}
16011614
if( db_step(&q)==SQLITE_ROW ){
1602
- printf("%-20s %-8s %s\n", zName, db_column_text(&q, 0),
1615
+ fossil_print("%-20s %-8s %s\n", zName, db_column_text(&q, 0),
16031616
db_column_text(&q, 1));
16041617
}else{
1605
- printf("%-20s\n", zName);
1618
+ fossil_print("%-20s\n", zName);
16061619
}
16071620
db_finalize(&q);
16081621
}
16091622
16101623
@@ -1853,9 +1866,9 @@
18531866
void test_timespan_cmd(void){
18541867
double rDiff;
18551868
if( g.argc!=3 ) usage("TIMESTAMP");
18561869
sqlite3_open(":memory:", &g.db);
18571870
rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]);
1858
- printf("Time differences: %s\n", db_timespan_name(rDiff));
1871
+ fossil_print("Time differences: %s\n", db_timespan_name(rDiff));
18591872
sqlite3_close(g.db);
18601873
g.db = 0;
18611874
}
18621875
--- src/db.c
+++ src/db.c
@@ -34,10 +34,11 @@
34 #endif
35 #include <sqlite3.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <unistd.h>
 
39 #include "db.h"
40
41 #if INTERFACE
42 /*
43 ** An single SQL statement is represented as an instance of the following
@@ -80,19 +81,29 @@
80 db_force_rollback();
81 fossil_exit(1);
82 }
83
84 static int nBegin = 0; /* Nesting depth of BEGIN */
85 static int isNewRepo = 0; /* True if the repository is newly created */
86 static int doRollback = 0; /* True to force a rollback */
87 static int nCommitHook = 0; /* Number of commit hooks */
88 static struct sCommitHook {
89 int (*xHook)(void); /* Functions to call at db_end_transaction() */
90 int sequence; /* Call functions in sequence order */
91 } aHook[5];
92 static Stmt *pAllStmt = 0; /* List of all unfinalized statements */
93 static int nPrepare = 0; /* Number of calls to sqlite3_prepare() */
 
 
 
 
 
 
 
 
 
 
 
94
95 /*
96 ** This routine is called by the SQLite commit-hook mechanism
97 ** just prior to each commit. All this routine does is verify
98 ** that nBegin really is zero. That insures that transactions
@@ -140,10 +151,11 @@
140
141 /*
142 ** Force a rollback and shutdown the database
143 */
144 void db_force_rollback(void){
 
145 static int busy = 0;
146 if( busy || g.db==0 ) return;
147 busy = 1;
148 undo_rollback();
149 while( pAllStmt ){
@@ -150,17 +162,16 @@
150 db_finalize(pAllStmt);
151 }
152 if( nBegin ){
153 sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
154 nBegin = 0;
155 if( isNewRepo ){
156 db_close(0);
157 unlink(g.zRepositoryName);
158 }
159 }
160 busy = 0;
161 db_close(0);
 
 
 
162 }
163
164 /*
165 ** Install a commit hook. Hooks are installed in sequence order.
166 ** It is an error to install the same commit hook more than once.
@@ -564,14 +575,10 @@
564 }
565 db_finalize(&s);
566 return z;
567 }
568
569 #if defined(_WIN32)
570 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
571 #endif
572
573 /*
574 ** Initialize a new database file with the given schema. If anything
575 ** goes wrong, call db_err() to exit.
576 */
577 void db_init_database(
@@ -582,13 +589,10 @@
582 sqlite3 *db;
583 int rc;
584 const char *zSql;
585 va_list ap;
586
587 #if defined(_WIN32)
588 zFileName = sqlite3_win32_mbcs_to_utf8(zFileName);
589 #endif
590 rc = sqlite3_open(zFileName, &db);
591 if( rc!=SQLITE_OK ){
592 db_err(sqlite3_errmsg(db));
593 }
594 sqlite3_busy_timeout(db, 5000);
@@ -606,10 +610,23 @@
606 }
607 va_end(ap);
608 sqlite3_exec(db, "COMMIT", 0, 0, 0);
609 sqlite3_close(db);
610 }
 
 
 
 
 
 
 
 
 
 
 
 
 
611
612 /*
613 ** Open a database file. Return a pointer to the new database
614 ** connection. An error results in process abort.
615 */
@@ -617,13 +634,10 @@
617 int rc;
618 const char *zVfs;
619 sqlite3 *db;
620
621 zVfs = getenv("FOSSIL_VFS");
622 #if defined(_WIN32)
623 zDbName = sqlite3_win32_mbcs_to_utf8(zDbName);
624 #endif
625 rc = sqlite3_open_v2(
626 zDbName, &db,
627 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
628 zVfs
629 );
@@ -630,10 +644,11 @@
630 if( rc!=SQLITE_OK ){
631 db_err(sqlite3_errmsg(db));
632 }
633 sqlite3_busy_timeout(db, 5000);
634 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
 
635 return db;
636 }
637
638
639 /*
@@ -645,13 +660,10 @@
645 if( !g.db ){
646 g.db = openDatabase(zDbName);
647 g.zMainDbType = zLabel;
648 db_connection_init();
649 }else{
650 #if defined(_WIN32)
651 zDbName = sqlite3_win32_mbcs_to_utf8(zDbName);
652 #endif
653 db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel);
654 }
655 }
656
657 /*
@@ -673,17 +685,21 @@
673 #if defined(_WIN32)
674 zHome = getenv("LOCALAPPDATA");
675 if( zHome==0 ){
676 zHome = getenv("APPDATA");
677 if( zHome==0 ){
 
678 zHome = getenv("HOMEPATH");
 
679 }
680 }
681 if( zHome==0 ){
682 fossil_fatal("cannot locate home directory - "
683 "please set the HOMEPATH environment variable");
 
684 }
 
685 #else
686 zHome = getenv("HOME");
687 if( zHome==0 ){
688 fossil_fatal("cannot locate home directory - "
689 "please set the HOME environment variable");
@@ -725,11 +741,11 @@
725 static int isValidLocalDb(const char *zDbName){
726 i64 lsize;
727 int rc;
728 sqlite3_stmt *pStmt;
729
730 if( access(zDbName, F_OK) ) return 0;
731 lsize = file_size(zDbName);
732 if( lsize%1024!=0 || lsize<4096 ) return 0;
733 db_open_or_attach(zDbName, "localdb");
734 g.localOpen = 1;
735 db_open_config(0);
@@ -788,23 +804,17 @@
788 ** is found, it is attached to the open database connection too.
789 */
790 int db_open_local(void){
791 int i, n;
792 char zPwd[2000];
793 char *zPwdConv;
794 static const char *aDbName[] = { "/_FOSSIL_", "/.fos" };
795
796 if( g.localOpen) return 1;
797 if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
798 db_err("pwd too big: max %d", sizeof(zPwd)-20);
799 }
800 n = strlen(zPwd);
801 zPwdConv = mprintf("%/", zPwd);
802 strncpy(zPwd, zPwdConv, 2000-20);
803 free(zPwdConv);
804 while( n>0 ){
805 if( access(zPwd, W_OK) ) break;
806 for(i=0; i<sizeof(aDbName)/sizeof(aDbName[0]); i++){
807 sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "%s", aDbName[i]);
808 if( isValidLocalDb(zPwd) ){
809 /* Found a valid checkout database file */
810 zPwd[n] = 0;
@@ -838,15 +848,15 @@
838 }
839 if( zDbName==0 ){
840 db_err("unable to find the name of a repository database");
841 }
842 }
843 if( access(zDbName, R_OK) || file_size(zDbName)<1024 ){
844 if( access(zDbName, 0) ){
845 fossil_panic("repository does not exist or"
846 " is in an unreadable directory: %s", zDbName);
847 }else if( access(zDbName, R_OK) ){
848 fossil_panic("read permission denied for repository %s", zDbName);
849 }else{
850 fossil_panic("not a valid repository: %s", zDbName);
851 }
852 }
@@ -949,11 +959,11 @@
949 fossil_fatal("not in a local checkout");
950 return;
951 }
952 file_canonical_name(g.argv[2], &repo);
953 zRepo = blob_str(&repo);
954 if( access(zRepo, 0) ){
955 fossil_fatal("no such file: %s", zRepo);
956 }
957 db_open_or_attach(zRepo, "test_repo");
958 db_lset("repository", blob_str(&repo));
959 db_close(1);
@@ -1041,11 +1051,11 @@
1041 zFilename,
1042 zRepositorySchema1,
1043 zRepositorySchema2,
1044 (char*)0
1045 );
1046 isNewRepo = 1;
1047 }
1048
1049 /*
1050 ** Create the default user accounts in the USER table.
1051 */
@@ -1105,14 +1115,14 @@
1105
1106 db_set("content-schema", CONTENT_SCHEMA, 0);
1107 db_set("aux-schema", AUX_SCHEMA, 0);
1108 if( makeServerCodes ){
1109 db_multi_exec(
1110 "INSERT INTO config(name,value)"
1111 " VALUES('server-code', lower(hex(randomblob(20))));"
1112 "INSERT INTO config(name,value)"
1113 " VALUES('project-code', lower(hex(randomblob(20))));"
1114 );
1115 }
1116 if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
1117 if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
1118 db_create_default_users(0, zDefaultUser);
@@ -1174,14 +1184,15 @@
1174 db_open_repository(g.argv[2]);
1175 db_open_config(0);
1176 db_begin_transaction();
1177 db_initial_setup(zDate, zDefaultUser, 1);
1178 db_end_transaction(0);
1179 printf("project-id: %s\n", db_get("project-code", 0));
1180 printf("server-id: %s\n", db_get("server-code", 0));
1181 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
1182 printf("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
 
1183 }
1184
1185 /*
1186 ** SQL functions for debugging.
1187 **
@@ -1195,11 +1206,11 @@
1195 ){
1196 int i;
1197 if( g.fSqlPrint ){
1198 for(i=0; i<argc; i++){
1199 char c = i==argc-1 ? '\n' : ' ';
1200 printf("%s%c", sqlite3_value_text(argv[i]), c);
1201 }
1202 }
1203 }
1204 static void db_sql_trace(void *notUsed, const char *zSql){
1205 int n = strlen(zSql);
@@ -1295,11 +1306,12 @@
1295 sha1sum_step_text(zContent, n);
1296 sha1sum_finish(&out);
1297 sqlite3_snprintf(sizeof(zHash), zHash, "%s", blob_str(&out));
1298 blob_reset(&out);
1299 db_multi_exec(
1300 "INSERT OR IGNORE INTO concealed VALUES(%Q,%#Q)",
 
1301 zHash, n, zContent
1302 );
1303 }
1304 return zHash;
1305 }
@@ -1406,11 +1418,11 @@
1406 db_swap_connections();
1407 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
1408 zName, zValue);
1409 db_swap_connections();
1410 }else{
1411 db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%Q)",
1412 zName, zValue);
1413 }
1414 if( globalFlag && g.repositoryOpen ){
1415 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1416 }
@@ -1465,11 +1477,11 @@
1465 db_swap_connections();
1466 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
1467 zName, value);
1468 db_swap_connections();
1469 }else{
1470 db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%d)",
1471 zName, value);
1472 }
1473 if( globalFlag && g.repositoryOpen ){
1474 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1475 }
@@ -1550,10 +1562,11 @@
1550 fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
1551 }
1552 file_canonical_name(g.argv[2], &path);
1553 db_open_repository(blob_str(&path));
1554 db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
 
1555 db_open_local();
1556 db_lset("repository", blob_str(&path));
1557 db_record_repository_filename(blob_str(&path));
1558 vid = db_int(0, "SELECT pid FROM plink y"
1559 " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)");
@@ -1597,14 +1610,14 @@
1597 "SELECT '(global)', value FROM global_config WHERE name=%Q",
1598 zName
1599 );
1600 }
1601 if( db_step(&q)==SQLITE_ROW ){
1602 printf("%-20s %-8s %s\n", zName, db_column_text(&q, 0),
1603 db_column_text(&q, 1));
1604 }else{
1605 printf("%-20s\n", zName);
1606 }
1607 db_finalize(&q);
1608 }
1609
1610
@@ -1853,9 +1866,9 @@
1853 void test_timespan_cmd(void){
1854 double rDiff;
1855 if( g.argc!=3 ) usage("TIMESTAMP");
1856 sqlite3_open(":memory:", &g.db);
1857 rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]);
1858 printf("Time differences: %s\n", db_timespan_name(rDiff));
1859 sqlite3_close(g.db);
1860 g.db = 0;
1861 }
1862
--- src/db.c
+++ src/db.c
@@ -34,10 +34,11 @@
34 #endif
35 #include <sqlite3.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <unistd.h>
39 #include <time.h>
40 #include "db.h"
41
42 #if INTERFACE
43 /*
44 ** An single SQL statement is represented as an instance of the following
@@ -80,19 +81,29 @@
81 db_force_rollback();
82 fossil_exit(1);
83 }
84
85 static int nBegin = 0; /* Nesting depth of BEGIN */
 
86 static int doRollback = 0; /* True to force a rollback */
87 static int nCommitHook = 0; /* Number of commit hooks */
88 static struct sCommitHook {
89 int (*xHook)(void); /* Functions to call at db_end_transaction() */
90 int sequence; /* Call functions in sequence order */
91 } aHook[5];
92 static Stmt *pAllStmt = 0; /* List of all unfinalized statements */
93 static int nPrepare = 0; /* Number of calls to sqlite3_prepare() */
94 static int nDeleteOnFail = 0; /* Number of entries in azDeleteOnFail[] */
95 static char *azDeleteOnFail[3]; /* Files to delete on a failure */
96
97
98 /*
99 ** Arrange for the given file to be deleted on a failure.
100 */
101 void db_delete_on_failure(const char *zFilename){
102 assert( nDeleteOnFail<count(azDeleteOnFail) );
103 azDeleteOnFail[nDeleteOnFail++] = fossil_strdup(zFilename);
104 }
105
106 /*
107 ** This routine is called by the SQLite commit-hook mechanism
108 ** just prior to each commit. All this routine does is verify
109 ** that nBegin really is zero. That insures that transactions
@@ -140,10 +151,11 @@
151
152 /*
153 ** Force a rollback and shutdown the database
154 */
155 void db_force_rollback(void){
156 int i;
157 static int busy = 0;
158 if( busy || g.db==0 ) return;
159 busy = 1;
160 undo_rollback();
161 while( pAllStmt ){
@@ -150,17 +162,16 @@
162 db_finalize(pAllStmt);
163 }
164 if( nBegin ){
165 sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0);
166 nBegin = 0;
 
 
 
 
167 }
168 busy = 0;
169 db_close(0);
170 for(i=0; i<nDeleteOnFail; i++){
171 file_delete(azDeleteOnFail[i]);
172 }
173 }
174
175 /*
176 ** Install a commit hook. Hooks are installed in sequence order.
177 ** It is an error to install the same commit hook more than once.
@@ -564,14 +575,10 @@
575 }
576 db_finalize(&s);
577 return z;
578 }
579
 
 
 
 
580 /*
581 ** Initialize a new database file with the given schema. If anything
582 ** goes wrong, call db_err() to exit.
583 */
584 void db_init_database(
@@ -582,13 +589,10 @@
589 sqlite3 *db;
590 int rc;
591 const char *zSql;
592 va_list ap;
593
 
 
 
594 rc = sqlite3_open(zFileName, &db);
595 if( rc!=SQLITE_OK ){
596 db_err(sqlite3_errmsg(db));
597 }
598 sqlite3_busy_timeout(db, 5000);
@@ -606,10 +610,23 @@
610 }
611 va_end(ap);
612 sqlite3_exec(db, "COMMIT", 0, 0, 0);
613 sqlite3_close(db);
614 }
615
616 /*
617 ** Function to return the number of seconds since 1970. This is
618 ** the same as strftime('%s','now') but is more compact.
619 */
620 static void db_now_function(
621 sqlite3_context *context,
622 int argc,
623 sqlite3_value **argv
624 ){
625 sqlite3_result_int64(context, time(0));
626 }
627
628
629 /*
630 ** Open a database file. Return a pointer to the new database
631 ** connection. An error results in process abort.
632 */
@@ -617,13 +634,10 @@
634 int rc;
635 const char *zVfs;
636 sqlite3 *db;
637
638 zVfs = getenv("FOSSIL_VFS");
 
 
 
639 rc = sqlite3_open_v2(
640 zDbName, &db,
641 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
642 zVfs
643 );
@@ -630,10 +644,11 @@
644 if( rc!=SQLITE_OK ){
645 db_err(sqlite3_errmsg(db));
646 }
647 sqlite3_busy_timeout(db, 5000);
648 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
649 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
650 return db;
651 }
652
653
654 /*
@@ -645,13 +660,10 @@
660 if( !g.db ){
661 g.db = openDatabase(zDbName);
662 g.zMainDbType = zLabel;
663 db_connection_init();
664 }else{
 
 
 
665 db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel);
666 }
667 }
668
669 /*
@@ -673,17 +685,21 @@
685 #if defined(_WIN32)
686 zHome = getenv("LOCALAPPDATA");
687 if( zHome==0 ){
688 zHome = getenv("APPDATA");
689 if( zHome==0 ){
690 char *zDrive = getenv("HOMEDRIVE");
691 zHome = getenv("HOMEPATH");
692 if( zDrive && zHome ) zHome = mprintf("%s%s", zDrive, zHome);
693 }
694 }
695 if( zHome==0 ){
696 fossil_fatal("cannot locate home directory - "
697 "please set the LOCALAPPDATA or APPDATA or HOMEPATH "
698 "environment variables");
699 }
700 zHome = fossil_mbcs_to_utf8(zHome);
701 #else
702 zHome = getenv("HOME");
703 if( zHome==0 ){
704 fossil_fatal("cannot locate home directory - "
705 "please set the HOME environment variable");
@@ -725,11 +741,11 @@
741 static int isValidLocalDb(const char *zDbName){
742 i64 lsize;
743 int rc;
744 sqlite3_stmt *pStmt;
745
746 if( file_access(zDbName, F_OK) ) return 0;
747 lsize = file_size(zDbName);
748 if( lsize%1024!=0 || lsize<4096 ) return 0;
749 db_open_or_attach(zDbName, "localdb");
750 g.localOpen = 1;
751 db_open_config(0);
@@ -788,23 +804,17 @@
804 ** is found, it is attached to the open database connection too.
805 */
806 int db_open_local(void){
807 int i, n;
808 char zPwd[2000];
 
809 static const char *aDbName[] = { "/_FOSSIL_", "/.fos" };
810
811 if( g.localOpen) return 1;
812 file_getcwd(zPwd, sizeof(zPwd)-20);
 
 
813 n = strlen(zPwd);
 
 
 
814 while( n>0 ){
815 if( file_access(zPwd, W_OK) ) break;
816 for(i=0; i<sizeof(aDbName)/sizeof(aDbName[0]); i++){
817 sqlite3_snprintf(sizeof(zPwd)-n, &zPwd[n], "%s", aDbName[i]);
818 if( isValidLocalDb(zPwd) ){
819 /* Found a valid checkout database file */
820 zPwd[n] = 0;
@@ -838,15 +848,15 @@
848 }
849 if( zDbName==0 ){
850 db_err("unable to find the name of a repository database");
851 }
852 }
853 if( file_access(zDbName, R_OK) || file_size(zDbName)<1024 ){
854 if( file_access(zDbName, 0) ){
855 fossil_panic("repository does not exist or"
856 " is in an unreadable directory: %s", zDbName);
857 }else if( file_access(zDbName, R_OK) ){
858 fossil_panic("read permission denied for repository %s", zDbName);
859 }else{
860 fossil_panic("not a valid repository: %s", zDbName);
861 }
862 }
@@ -949,11 +959,11 @@
959 fossil_fatal("not in a local checkout");
960 return;
961 }
962 file_canonical_name(g.argv[2], &repo);
963 zRepo = blob_str(&repo);
964 if( file_access(zRepo, 0) ){
965 fossil_fatal("no such file: %s", zRepo);
966 }
967 db_open_or_attach(zRepo, "test_repo");
968 db_lset("repository", blob_str(&repo));
969 db_close(1);
@@ -1041,11 +1051,11 @@
1051 zFilename,
1052 zRepositorySchema1,
1053 zRepositorySchema2,
1054 (char*)0
1055 );
1056 db_delete_on_failure(zFilename);
1057 }
1058
1059 /*
1060 ** Create the default user accounts in the USER table.
1061 */
@@ -1105,14 +1115,14 @@
1115
1116 db_set("content-schema", CONTENT_SCHEMA, 0);
1117 db_set("aux-schema", AUX_SCHEMA, 0);
1118 if( makeServerCodes ){
1119 db_multi_exec(
1120 "INSERT INTO config(name,value,mtime)"
1121 " VALUES('server-code', lower(hex(randomblob(20))),now());"
1122 "INSERT INTO config(name,value,mtime)"
1123 " VALUES('project-code', lower(hex(randomblob(20))),now());"
1124 );
1125 }
1126 if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
1127 if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
1128 db_create_default_users(0, zDefaultUser);
@@ -1174,14 +1184,15 @@
1184 db_open_repository(g.argv[2]);
1185 db_open_config(0);
1186 db_begin_transaction();
1187 db_initial_setup(zDate, zDefaultUser, 1);
1188 db_end_transaction(0);
1189 fossil_print("project-id: %s\n", db_get("project-code", 0));
1190 fossil_print("server-id: %s\n", db_get("server-code", 0));
1191 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
1192 fossil_print("admin-user: %s (initial password is \"%s\")\n",
1193 g.zLogin, zPassword);
1194 }
1195
1196 /*
1197 ** SQL functions for debugging.
1198 **
@@ -1195,11 +1206,11 @@
1206 ){
1207 int i;
1208 if( g.fSqlPrint ){
1209 for(i=0; i<argc; i++){
1210 char c = i==argc-1 ? '\n' : ' ';
1211 fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
1212 }
1213 }
1214 }
1215 static void db_sql_trace(void *notUsed, const char *zSql){
1216 int n = strlen(zSql);
@@ -1295,11 +1306,12 @@
1306 sha1sum_step_text(zContent, n);
1307 sha1sum_finish(&out);
1308 sqlite3_snprintf(sizeof(zHash), zHash, "%s", blob_str(&out));
1309 blob_reset(&out);
1310 db_multi_exec(
1311 "INSERT OR IGNORE INTO concealed(hash,content,mtime)"
1312 " VALUES(%Q,%#Q,now())",
1313 zHash, n, zContent
1314 );
1315 }
1316 return zHash;
1317 }
@@ -1406,11 +1418,11 @@
1418 db_swap_connections();
1419 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
1420 zName, zValue);
1421 db_swap_connections();
1422 }else{
1423 db_multi_exec("REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
1424 zName, zValue);
1425 }
1426 if( globalFlag && g.repositoryOpen ){
1427 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1428 }
@@ -1465,11 +1477,11 @@
1477 db_swap_connections();
1478 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
1479 zName, value);
1480 db_swap_connections();
1481 }else{
1482 db_multi_exec("REPLACE INTO config(name,value,mtime) VALUES(%Q,%d,now())",
1483 zName, value);
1484 }
1485 if( globalFlag && g.repositoryOpen ){
1486 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1487 }
@@ -1550,10 +1562,11 @@
1562 fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
1563 }
1564 file_canonical_name(g.argv[2], &path);
1565 db_open_repository(blob_str(&path));
1566 db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
1567 db_delete_on_failure("./_FOSSIL_");
1568 db_open_local();
1569 db_lset("repository", blob_str(&path));
1570 db_record_repository_filename(blob_str(&path));
1571 vid = db_int(0, "SELECT pid FROM plink y"
1572 " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)");
@@ -1597,14 +1610,14 @@
1610 "SELECT '(global)', value FROM global_config WHERE name=%Q",
1611 zName
1612 );
1613 }
1614 if( db_step(&q)==SQLITE_ROW ){
1615 fossil_print("%-20s %-8s %s\n", zName, db_column_text(&q, 0),
1616 db_column_text(&q, 1));
1617 }else{
1618 fossil_print("%-20s\n", zName);
1619 }
1620 db_finalize(&q);
1621 }
1622
1623
@@ -1853,9 +1866,9 @@
1866 void test_timespan_cmd(void){
1867 double rDiff;
1868 if( g.argc!=3 ) usage("TIMESTAMP");
1869 sqlite3_open(":memory:", &g.db);
1870 rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]);
1871 fossil_print("Time differences: %s\n", db_timespan_name(rDiff));
1872 sqlite3_close(g.db);
1873 g.db = 0;
1874 }
1875
+7 -13
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -52,21 +52,18 @@
5252
Blob orig, target, delta;
5353
if( g.argc!=5 ){
5454
usage("ORIGIN TARGET DELTA");
5555
}
5656
if( blob_read_from_file(&orig, g.argv[2])<0 ){
57
- fprintf(stderr,"cannot read %s\n", g.argv[2]);
58
- fossil_exit(1);
57
+ fossil_fatal("cannot read %s\n", g.argv[2]);
5958
}
6059
if( blob_read_from_file(&target, g.argv[3])<0 ){
61
- fprintf(stderr,"cannot read %s\n", g.argv[3]);
62
- fossil_exit(1);
60
+ fossil_fatal("cannot read %s\n", g.argv[3]);
6361
}
6462
blob_delta_create(&orig, &target, &delta);
6563
if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){
66
- fprintf(stderr,"cannot write %s\n", g.argv[4]);
67
- fossil_exit(1);
64
+ fossil_fatal("cannot write %s\n", g.argv[4]);
6865
}
6966
blob_reset(&orig);
7067
blob_reset(&target);
7168
blob_reset(&delta);
7269
}
@@ -114,21 +111,18 @@
114111
Blob orig, target, delta;
115112
if( g.argc!=5 ){
116113
usage("ORIGIN DELTA TARGET");
117114
}
118115
if( blob_read_from_file(&orig, g.argv[2])<0 ){
119
- fprintf(stderr,"cannot read %s\n", g.argv[2]);
120
- fossil_exit(1);
116
+ fossil_fatal("cannot read %s\n", g.argv[2]);
121117
}
122118
if( blob_read_from_file(&delta, g.argv[3])<0 ){
123
- fprintf(stderr,"cannot read %s\n", g.argv[3]);
124
- fossil_exit(1);
119
+ fossil_fatal("cannot read %s\n", g.argv[3]);
125120
}
126121
blob_delta_apply(&orig, &delta, &target);
127122
if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){
128
- fprintf(stderr,"cannot write %s\n", g.argv[4]);
129
- fossil_exit(1);
123
+ fossil_fatal("cannot write %s\n", g.argv[4]);
130124
}
131125
blob_reset(&orig);
132126
blob_reset(&target);
133127
blob_reset(&delta);
134128
}
@@ -152,7 +146,7 @@
152146
blob_delta_apply(&f1, &d12, &a2);
153147
blob_delta_apply(&f2, &d21, &a1);
154148
if( blob_compare(&f1,&a1) || blob_compare(&f2, &a2) ){
155149
fossil_panic("delta test failed");
156150
}
157
- printf("ok\n");
151
+ fossil_print("ok\n");
158152
}
159153
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -52,21 +52,18 @@
52 Blob orig, target, delta;
53 if( g.argc!=5 ){
54 usage("ORIGIN TARGET DELTA");
55 }
56 if( blob_read_from_file(&orig, g.argv[2])<0 ){
57 fprintf(stderr,"cannot read %s\n", g.argv[2]);
58 fossil_exit(1);
59 }
60 if( blob_read_from_file(&target, g.argv[3])<0 ){
61 fprintf(stderr,"cannot read %s\n", g.argv[3]);
62 fossil_exit(1);
63 }
64 blob_delta_create(&orig, &target, &delta);
65 if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){
66 fprintf(stderr,"cannot write %s\n", g.argv[4]);
67 fossil_exit(1);
68 }
69 blob_reset(&orig);
70 blob_reset(&target);
71 blob_reset(&delta);
72 }
@@ -114,21 +111,18 @@
114 Blob orig, target, delta;
115 if( g.argc!=5 ){
116 usage("ORIGIN DELTA TARGET");
117 }
118 if( blob_read_from_file(&orig, g.argv[2])<0 ){
119 fprintf(stderr,"cannot read %s\n", g.argv[2]);
120 fossil_exit(1);
121 }
122 if( blob_read_from_file(&delta, g.argv[3])<0 ){
123 fprintf(stderr,"cannot read %s\n", g.argv[3]);
124 fossil_exit(1);
125 }
126 blob_delta_apply(&orig, &delta, &target);
127 if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){
128 fprintf(stderr,"cannot write %s\n", g.argv[4]);
129 fossil_exit(1);
130 }
131 blob_reset(&orig);
132 blob_reset(&target);
133 blob_reset(&delta);
134 }
@@ -152,7 +146,7 @@
152 blob_delta_apply(&f1, &d12, &a2);
153 blob_delta_apply(&f2, &d21, &a1);
154 if( blob_compare(&f1,&a1) || blob_compare(&f2, &a2) ){
155 fossil_panic("delta test failed");
156 }
157 printf("ok\n");
158 }
159
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -52,21 +52,18 @@
52 Blob orig, target, delta;
53 if( g.argc!=5 ){
54 usage("ORIGIN TARGET DELTA");
55 }
56 if( blob_read_from_file(&orig, g.argv[2])<0 ){
57 fossil_fatal("cannot read %s\n", g.argv[2]);
 
58 }
59 if( blob_read_from_file(&target, g.argv[3])<0 ){
60 fossil_fatal("cannot read %s\n", g.argv[3]);
 
61 }
62 blob_delta_create(&orig, &target, &delta);
63 if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){
64 fossil_fatal("cannot write %s\n", g.argv[4]);
 
65 }
66 blob_reset(&orig);
67 blob_reset(&target);
68 blob_reset(&delta);
69 }
@@ -114,21 +111,18 @@
111 Blob orig, target, delta;
112 if( g.argc!=5 ){
113 usage("ORIGIN DELTA TARGET");
114 }
115 if( blob_read_from_file(&orig, g.argv[2])<0 ){
116 fossil_fatal("cannot read %s\n", g.argv[2]);
 
117 }
118 if( blob_read_from_file(&delta, g.argv[3])<0 ){
119 fossil_fatal("cannot read %s\n", g.argv[3]);
 
120 }
121 blob_delta_apply(&orig, &delta, &target);
122 if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){
123 fossil_fatal("cannot write %s\n", g.argv[4]);
 
124 }
125 blob_reset(&orig);
126 blob_reset(&target);
127 blob_reset(&delta);
128 }
@@ -152,7 +146,7 @@
146 blob_delta_apply(&f1, &d12, &a2);
147 blob_delta_apply(&f2, &d21, &a1);
148 if( blob_compare(&f1,&a1) || blob_compare(&f2, &a2) ){
149 fossil_panic("delta test failed");
150 }
151 fossil_print("ok\n");
152 }
153
+26 -11
--- src/descendants.c
+++ src/descendants.c
@@ -159,60 +159,75 @@
159159
** the "ok" table.
160160
*/
161161
void compute_ancestors(int rid, int N){
162162
Bag seen;
163163
PQueue queue;
164
+ Stmt ins;
165
+ Stmt q;
164166
bag_init(&seen);
165167
pqueue_init(&queue);
166168
bag_insert(&seen, rid);
167169
pqueue_insert(&queue, rid, 0.0, 0);
170
+ db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
171
+ db_prepare(&q,
172
+ "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
173
+ " WHERE a.cid=:rid"
174
+ );
168175
while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
169
- Stmt q;
170
- db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid);
171
- db_prepare(&q,
172
- "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
173
- " WHERE a.cid=%d", rid
174
- );
176
+ db_bind_int(&ins, ":rid", rid);
177
+ db_step(&ins);
178
+ db_reset(&ins);
179
+ db_bind_int(&q, ":rid", rid);
175180
while( db_step(&q)==SQLITE_ROW ){
176181
int pid = db_column_int(&q, 0);
177182
double mtime = db_column_double(&q, 1);
178183
if( bag_insert(&seen, pid) ){
179184
pqueue_insert(&queue, pid, -mtime, 0);
180185
}
181186
}
182
- db_finalize(&q);
187
+ db_reset(&q);
183188
}
184189
bag_clear(&seen);
185190
pqueue_clear(&queue);
191
+ db_finalize(&ins);
192
+ db_finalize(&q);
186193
}
187194
188195
/*
189196
** Load the record ID rid and up to N-1 closest descendants into
190197
** the "ok" table.
191198
*/
192199
void compute_descendants(int rid, int N){
193200
Bag seen;
194201
PQueue queue;
202
+ Stmt ins;
203
+ Stmt q;
204
+
195205
bag_init(&seen);
196206
pqueue_init(&queue);
197207
bag_insert(&seen, rid);
198208
pqueue_insert(&queue, rid, 0.0, 0);
209
+ db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
210
+ db_prepare(&q, "SELECT cid, mtime FROM plink WHERE pid=:rid");
199211
while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
200
- Stmt q;
201
- db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid);
202
- db_prepare(&q,"SELECT cid, mtime FROM plink WHERE pid=%d", rid);
212
+ db_bind_int(&ins, ":rid", rid);
213
+ db_step(&ins);
214
+ db_reset(&ins);
215
+ db_bind_int(&q, ":rid", rid);
203216
while( db_step(&q)==SQLITE_ROW ){
204217
int pid = db_column_int(&q, 0);
205218
double mtime = db_column_double(&q, 1);
206219
if( bag_insert(&seen, pid) ){
207220
pqueue_insert(&queue, pid, mtime, 0);
208221
}
209222
}
210
- db_finalize(&q);
223
+ db_reset(&q);
211224
}
212225
bag_clear(&seen);
213226
pqueue_clear(&queue);
227
+ db_finalize(&ins);
228
+ db_finalize(&q);
214229
}
215230
216231
/*
217232
** COMMAND: descendants
218233
**
219234
--- src/descendants.c
+++ src/descendants.c
@@ -159,60 +159,75 @@
159 ** the "ok" table.
160 */
161 void compute_ancestors(int rid, int N){
162 Bag seen;
163 PQueue queue;
 
 
164 bag_init(&seen);
165 pqueue_init(&queue);
166 bag_insert(&seen, rid);
167 pqueue_insert(&queue, rid, 0.0, 0);
 
 
 
 
 
168 while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
169 Stmt q;
170 db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid);
171 db_prepare(&q,
172 "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
173 " WHERE a.cid=%d", rid
174 );
175 while( db_step(&q)==SQLITE_ROW ){
176 int pid = db_column_int(&q, 0);
177 double mtime = db_column_double(&q, 1);
178 if( bag_insert(&seen, pid) ){
179 pqueue_insert(&queue, pid, -mtime, 0);
180 }
181 }
182 db_finalize(&q);
183 }
184 bag_clear(&seen);
185 pqueue_clear(&queue);
 
 
186 }
187
188 /*
189 ** Load the record ID rid and up to N-1 closest descendants into
190 ** the "ok" table.
191 */
192 void compute_descendants(int rid, int N){
193 Bag seen;
194 PQueue queue;
 
 
 
195 bag_init(&seen);
196 pqueue_init(&queue);
197 bag_insert(&seen, rid);
198 pqueue_insert(&queue, rid, 0.0, 0);
 
 
199 while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
200 Stmt q;
201 db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid);
202 db_prepare(&q,"SELECT cid, mtime FROM plink WHERE pid=%d", rid);
 
203 while( db_step(&q)==SQLITE_ROW ){
204 int pid = db_column_int(&q, 0);
205 double mtime = db_column_double(&q, 1);
206 if( bag_insert(&seen, pid) ){
207 pqueue_insert(&queue, pid, mtime, 0);
208 }
209 }
210 db_finalize(&q);
211 }
212 bag_clear(&seen);
213 pqueue_clear(&queue);
 
 
214 }
215
216 /*
217 ** COMMAND: descendants
218 **
219
--- src/descendants.c
+++ src/descendants.c
@@ -159,60 +159,75 @@
159 ** the "ok" table.
160 */
161 void compute_ancestors(int rid, int N){
162 Bag seen;
163 PQueue queue;
164 Stmt ins;
165 Stmt q;
166 bag_init(&seen);
167 pqueue_init(&queue);
168 bag_insert(&seen, rid);
169 pqueue_insert(&queue, rid, 0.0, 0);
170 db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
171 db_prepare(&q,
172 "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
173 " WHERE a.cid=:rid"
174 );
175 while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
176 db_bind_int(&ins, ":rid", rid);
177 db_step(&ins);
178 db_reset(&ins);
179 db_bind_int(&q, ":rid", rid);
 
 
180 while( db_step(&q)==SQLITE_ROW ){
181 int pid = db_column_int(&q, 0);
182 double mtime = db_column_double(&q, 1);
183 if( bag_insert(&seen, pid) ){
184 pqueue_insert(&queue, pid, -mtime, 0);
185 }
186 }
187 db_reset(&q);
188 }
189 bag_clear(&seen);
190 pqueue_clear(&queue);
191 db_finalize(&ins);
192 db_finalize(&q);
193 }
194
195 /*
196 ** Load the record ID rid and up to N-1 closest descendants into
197 ** the "ok" table.
198 */
199 void compute_descendants(int rid, int N){
200 Bag seen;
201 PQueue queue;
202 Stmt ins;
203 Stmt q;
204
205 bag_init(&seen);
206 pqueue_init(&queue);
207 bag_insert(&seen, rid);
208 pqueue_insert(&queue, rid, 0.0, 0);
209 db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
210 db_prepare(&q, "SELECT cid, mtime FROM plink WHERE pid=:rid");
211 while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
212 db_bind_int(&ins, ":rid", rid);
213 db_step(&ins);
214 db_reset(&ins);
215 db_bind_int(&q, ":rid", rid);
216 while( db_step(&q)==SQLITE_ROW ){
217 int pid = db_column_int(&q, 0);
218 double mtime = db_column_double(&q, 1);
219 if( bag_insert(&seen, pid) ){
220 pqueue_insert(&queue, pid, mtime, 0);
221 }
222 }
223 db_reset(&q);
224 }
225 bag_clear(&seen);
226 pqueue_clear(&queue);
227 db_finalize(&ins);
228 db_finalize(&q);
229 }
230
231 /*
232 ** COMMAND: descendants
233 **
234
+88 -18
--- src/diff.c
+++ src/diff.c
@@ -590,15 +590,15 @@
590590
int i;
591591
int *R;
592592
if( g.argc<4 ) usage("FILE1 FILE2 ...");
593593
blob_read_from_file(&a, g.argv[2]);
594594
for(i=3; i<g.argc; i++){
595
- if( i>3 ) printf("-------------------------------\n");
595
+ if( i>3 ) fossil_print("-------------------------------\n");
596596
blob_read_from_file(&b, g.argv[i]);
597597
R = text_diff(&a, &b, 0, 0, 0);
598598
for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
599
- printf(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
599
+ fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
600600
}
601601
/* free(R); */
602602
blob_reset(&b);
603603
}
604604
}
@@ -626,17 +626,21 @@
626626
** of the following structure.
627627
*/
628628
typedef struct Annotator Annotator;
629629
struct Annotator {
630630
DContext c; /* The diff-engine context */
631
- struct { /* Lines of the original files... */
631
+ struct AnnLine { /* Lines of the original files... */
632632
const char *z; /* The text of the line */
633
- int n; /* Number of bytes (omitting trailing space and \n) */
633
+ short int n; /* Number of bytes (omitting trailing space and \n) */
634
+ short int iLevel; /* Level at which tag was set */
634635
const char *zSrc; /* Tag showing origin of this line */
635636
} *aOrig;
636637
int nOrig; /* Number of elements in aOrig[] */
637638
int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */
639
+ int iLevel; /* Current level */
640
+ int nVers; /* Number of versions analyzed */
641
+ char **azVers; /* Names of versions analyzed */
638642
};
639643
640644
/*
641645
** Initialize the annotation process by specifying the file that is
642646
** to be annotated. The annotator takes control of the input Blob and
@@ -668,10 +672,12 @@
668672
** pParent. Memory to hold zPName is leaked.
669673
*/
670674
static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
671675
int i, j;
672676
int lnTo;
677
+ int iPrevLevel;
678
+ int iThisLevel;
673679
674680
/* Prepare the parent file to be diffed */
675681
p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent),
676682
&p->c.nFrom, 1);
677683
if( p->c.aFrom==0 ){
@@ -683,13 +689,20 @@
683689
diff_all(&p->c);
684690
685691
/* Where new lines are inserted on this difference, record the
686692
** zPName as the source of the new line.
687693
*/
694
+ iPrevLevel = p->iLevel;
695
+ p->iLevel++;
696
+ iThisLevel = p->iLevel;
688697
for(i=lnTo=0; i<p->c.nEdit; i+=3){
689
- for(j=0; j<p->c.aEdit[i]; j++, lnTo++){
690
- p->aOrig[lnTo].zSrc = zPName;
698
+ struct AnnLine *x = &p->aOrig[lnTo];
699
+ for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
700
+ if( x->zSrc==0 || x->iLevel==iPrevLevel ){
701
+ x->zSrc = zPName;
702
+ x->iLevel = iThisLevel;
703
+ }
691704
}
692705
lnTo += p->c.aEdit[i+2];
693706
}
694707
695708
/* Clear out the diff results */
@@ -730,20 +743,30 @@
730743
}
731744
}
732745
for(i=0; i<x.nOrig; i++){
733746
const char *zSrc = x.aOrig[i].zSrc;
734747
if( zSrc==0 ) zSrc = g.argv[g.argc-1];
735
- printf("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
748
+ fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
736749
}
737750
}
738751
752
+/* Annotation flags */
753
+#define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
754
+
739755
/*
740756
** Compute a complete annotation on a file. The file is identified
741757
** by its filename number (filename.fnid) and the baseline in which
742758
** it was checked in (mlink.mid).
743759
*/
744
-static void annotate_file(Annotator *p, int fnid, int mid, int webLabel){
760
+static void annotate_file(
761
+ Annotator *p, /* The annotator */
762
+ int fnid, /* The name of the file to be annotated */
763
+ int mid, /* The specific version of the file for this step */
764
+ int webLabel, /* Use web-style annotations if true */
765
+ int iLimit, /* Limit the number of levels if greater than zero */
766
+ int annFlags /* Flags to alter the annotation */
767
+){
745768
Blob toAnnotate; /* Text of the final version of the file */
746769
Blob step; /* Text of previous revision */
747770
int rid; /* Artifact ID of the file being annotated */
748771
char *zLabel; /* Label to apply to a line */
749772
Stmt q; /* Query returning all ancestor versions */
@@ -759,31 +782,40 @@
759782
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
760783
compute_ancestors(mid, 1000000000);
761784
annotation_start(p, &toAnnotate);
762785
763786
db_prepare(&q,
764
- "SELECT mlink.fid, blob.uuid, date(event.mtime), "
787
+ "SELECT mlink.fid,"
788
+ " (SELECT uuid FROM blob WHERE rid=mlink.%s),"
789
+ " date(event.mtime), "
765790
" coalesce(event.euser,event.user) "
766
- " FROM mlink, blob, event"
791
+ " FROM mlink, event"
767792
" WHERE mlink.fnid=%d"
768793
" AND mlink.mid IN ok"
769
- " AND blob.rid=mlink.mid"
770794
" AND event.objid=mlink.mid"
771
- " ORDER BY event.mtime DESC",
772
- fnid
795
+ " ORDER BY event.mtime DESC"
796
+ " LIMIT %d",
797
+ (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid",
798
+ fnid,
799
+ iLimit>0 ? iLimit : 10000000
773800
);
774801
while( db_step(&q)==SQLITE_ROW ){
775802
int pid = db_column_int(&q, 0);
776803
const char *zUuid = db_column_text(&q, 1);
777804
const char *zDate = db_column_text(&q, 2);
778805
const char *zUser = db_column_text(&q, 3);
779806
if( webLabel ){
780
- zLabel = mprintf("<a href='%s/info/%s'>%.10s</a> %s %9.9s",
781
- g.zTop, zUuid, zUuid, zDate, zUser);
807
+ zLabel = mprintf(
808
+ "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s",
809
+ g.zTop, zUuid, zUuid, zDate, zUser
810
+ );
782811
}else{
783812
zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
784813
}
814
+ p->nVers++;
815
+ p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
816
+ p->azVers[p->nVers-1] = zLabel;
785817
content_get(pid, &step);
786818
annotation_step(p, &step, zLabel);
787819
blob_reset(&step);
788820
}
789821
db_finalize(&q);
@@ -799,22 +831,37 @@
799831
*/
800832
void annotation_page(void){
801833
int mid;
802834
int fnid;
803835
int i;
836
+ int iLimit;
837
+ int annFlags = 0;
804838
Annotator ann;
805839
806840
login_check_credentials();
807841
if( !g.okRead ){ login_needed(); return; }
808842
mid = name_to_rid(PD("checkin","0"));
809843
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
810844
if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
845
+ iLimit = atoi(PD("limit","-1"));
811846
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
812847
fossil_redirect_home();
813848
}
814849
style_header("File Annotation");
815
- annotate_file(&ann, fnid, mid, g.okHistory);
850
+ if( P("filevers") ) annFlags |= ANN_FILE_VERS;
851
+ annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags);
852
+ if( P("log") ){
853
+ int i;
854
+ @ <h2>Versions analyzed:</h2>
855
+ @ <ol>
856
+ for(i=0; i<ann.nVers; i++){
857
+ @ <li><tt>%s(ann.azVers[i])</tt></li>
858
+ }
859
+ @ </ol>
860
+ @ <hr>
861
+ @ <h2>Annotation:</h2>
862
+ }
816863
@ <pre>
817864
for(i=0; i<ann.nOrig; i++){
818865
((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
819866
@ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
820867
}
@@ -827,20 +874,35 @@
827874
**
828875
** %fossil annotate FILENAME
829876
**
830877
** Output the text of a file with markings to show when each line of
831878
** the file was last modified.
879
+**
880
+** Options:
881
+** --limit N Only look backwards in time by N versions
882
+** --log List all versions analyzed
883
+** --filevers Show file version numbers rather than check-in versions
832884
*/
833885
void annotate_cmd(void){
834886
int fnid; /* Filename ID */
835887
int fid; /* File instance ID */
836888
int mid; /* Manifest where file was checked in */
837889
Blob treename; /* FILENAME translated to canonical form */
838890
char *zFilename; /* Cannonical filename */
839891
Annotator ann; /* The annotation of the file */
840892
int i; /* Loop counter */
893
+ const char *zLimit; /* The value to the --limit option */
894
+ int iLimit; /* How far back in time to look */
895
+ int showLog; /* True to show the log */
896
+ int fileVers; /* Show file version instead of check-in versions */
897
+ int annFlags = 0; /* Flags to control annotation properties */
841898
899
+ zLimit = find_option("limit",0,1);
900
+ if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
901
+ iLimit = atoi(zLimit);
902
+ showLog = find_option("log",0,0)!=0;
903
+ fileVers = find_option("filevers",0,0)!=0;
842904
db_must_be_within_tree();
843905
if (g.argc<3) {
844906
usage("FILENAME");
845907
}
846908
file_tree_name(g.argv[2], &treename, 1);
@@ -855,10 +917,18 @@
855917
}
856918
mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
857919
if( mid==0 ){
858920
fossil_panic("unable to find manifest");
859921
}
860
- annotate_file(&ann, fnid, mid, 0);
922
+ if( fileVers ) annFlags |= ANN_FILE_VERS;
923
+ annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
924
+ if( showLog ){
925
+ for(i=0; i<ann.nVers; i++){
926
+ printf("version %3d: %s\n", i+1, ann.azVers[i]);
927
+ }
928
+ printf("---------------------------------------------------\n");
929
+ }
861930
for(i=0; i<ann.nOrig; i++){
862
- printf("%s: %.*s\n", ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
931
+ fossil_print("%s: %.*s\n",
932
+ ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
863933
}
864934
}
865935
--- src/diff.c
+++ src/diff.c
@@ -590,15 +590,15 @@
590 int i;
591 int *R;
592 if( g.argc<4 ) usage("FILE1 FILE2 ...");
593 blob_read_from_file(&a, g.argv[2]);
594 for(i=3; i<g.argc; i++){
595 if( i>3 ) printf("-------------------------------\n");
596 blob_read_from_file(&b, g.argv[i]);
597 R = text_diff(&a, &b, 0, 0, 0);
598 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
599 printf(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
600 }
601 /* free(R); */
602 blob_reset(&b);
603 }
604 }
@@ -626,17 +626,21 @@
626 ** of the following structure.
627 */
628 typedef struct Annotator Annotator;
629 struct Annotator {
630 DContext c; /* The diff-engine context */
631 struct { /* Lines of the original files... */
632 const char *z; /* The text of the line */
633 int n; /* Number of bytes (omitting trailing space and \n) */
 
634 const char *zSrc; /* Tag showing origin of this line */
635 } *aOrig;
636 int nOrig; /* Number of elements in aOrig[] */
637 int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */
 
 
 
638 };
639
640 /*
641 ** Initialize the annotation process by specifying the file that is
642 ** to be annotated. The annotator takes control of the input Blob and
@@ -668,10 +672,12 @@
668 ** pParent. Memory to hold zPName is leaked.
669 */
670 static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
671 int i, j;
672 int lnTo;
 
 
673
674 /* Prepare the parent file to be diffed */
675 p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent),
676 &p->c.nFrom, 1);
677 if( p->c.aFrom==0 ){
@@ -683,13 +689,20 @@
683 diff_all(&p->c);
684
685 /* Where new lines are inserted on this difference, record the
686 ** zPName as the source of the new line.
687 */
 
 
 
688 for(i=lnTo=0; i<p->c.nEdit; i+=3){
689 for(j=0; j<p->c.aEdit[i]; j++, lnTo++){
690 p->aOrig[lnTo].zSrc = zPName;
 
 
 
 
691 }
692 lnTo += p->c.aEdit[i+2];
693 }
694
695 /* Clear out the diff results */
@@ -730,20 +743,30 @@
730 }
731 }
732 for(i=0; i<x.nOrig; i++){
733 const char *zSrc = x.aOrig[i].zSrc;
734 if( zSrc==0 ) zSrc = g.argv[g.argc-1];
735 printf("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
736 }
737 }
738
 
 
 
739 /*
740 ** Compute a complete annotation on a file. The file is identified
741 ** by its filename number (filename.fnid) and the baseline in which
742 ** it was checked in (mlink.mid).
743 */
744 static void annotate_file(Annotator *p, int fnid, int mid, int webLabel){
 
 
 
 
 
 
 
745 Blob toAnnotate; /* Text of the final version of the file */
746 Blob step; /* Text of previous revision */
747 int rid; /* Artifact ID of the file being annotated */
748 char *zLabel; /* Label to apply to a line */
749 Stmt q; /* Query returning all ancestor versions */
@@ -759,31 +782,40 @@
759 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
760 compute_ancestors(mid, 1000000000);
761 annotation_start(p, &toAnnotate);
762
763 db_prepare(&q,
764 "SELECT mlink.fid, blob.uuid, date(event.mtime), "
 
 
765 " coalesce(event.euser,event.user) "
766 " FROM mlink, blob, event"
767 " WHERE mlink.fnid=%d"
768 " AND mlink.mid IN ok"
769 " AND blob.rid=mlink.mid"
770 " AND event.objid=mlink.mid"
771 " ORDER BY event.mtime DESC",
772 fnid
 
 
 
773 );
774 while( db_step(&q)==SQLITE_ROW ){
775 int pid = db_column_int(&q, 0);
776 const char *zUuid = db_column_text(&q, 1);
777 const char *zDate = db_column_text(&q, 2);
778 const char *zUser = db_column_text(&q, 3);
779 if( webLabel ){
780 zLabel = mprintf("<a href='%s/info/%s'>%.10s</a> %s %9.9s",
781 g.zTop, zUuid, zUuid, zDate, zUser);
 
 
782 }else{
783 zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
784 }
 
 
 
785 content_get(pid, &step);
786 annotation_step(p, &step, zLabel);
787 blob_reset(&step);
788 }
789 db_finalize(&q);
@@ -799,22 +831,37 @@
799 */
800 void annotation_page(void){
801 int mid;
802 int fnid;
803 int i;
 
 
804 Annotator ann;
805
806 login_check_credentials();
807 if( !g.okRead ){ login_needed(); return; }
808 mid = name_to_rid(PD("checkin","0"));
809 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
810 if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
 
811 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
812 fossil_redirect_home();
813 }
814 style_header("File Annotation");
815 annotate_file(&ann, fnid, mid, g.okHistory);
 
 
 
 
 
 
 
 
 
 
 
 
816 @ <pre>
817 for(i=0; i<ann.nOrig; i++){
818 ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
819 @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
820 }
@@ -827,20 +874,35 @@
827 **
828 ** %fossil annotate FILENAME
829 **
830 ** Output the text of a file with markings to show when each line of
831 ** the file was last modified.
 
 
 
 
 
832 */
833 void annotate_cmd(void){
834 int fnid; /* Filename ID */
835 int fid; /* File instance ID */
836 int mid; /* Manifest where file was checked in */
837 Blob treename; /* FILENAME translated to canonical form */
838 char *zFilename; /* Cannonical filename */
839 Annotator ann; /* The annotation of the file */
840 int i; /* Loop counter */
 
 
 
 
 
841
 
 
 
 
 
842 db_must_be_within_tree();
843 if (g.argc<3) {
844 usage("FILENAME");
845 }
846 file_tree_name(g.argv[2], &treename, 1);
@@ -855,10 +917,18 @@
855 }
856 mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
857 if( mid==0 ){
858 fossil_panic("unable to find manifest");
859 }
860 annotate_file(&ann, fnid, mid, 0);
 
 
 
 
 
 
 
861 for(i=0; i<ann.nOrig; i++){
862 printf("%s: %.*s\n", ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
 
863 }
864 }
865
--- src/diff.c
+++ src/diff.c
@@ -590,15 +590,15 @@
590 int i;
591 int *R;
592 if( g.argc<4 ) usage("FILE1 FILE2 ...");
593 blob_read_from_file(&a, g.argv[2]);
594 for(i=3; i<g.argc; i++){
595 if( i>3 ) fossil_print("-------------------------------\n");
596 blob_read_from_file(&b, g.argv[i]);
597 R = text_diff(&a, &b, 0, 0, 0);
598 for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
599 fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
600 }
601 /* free(R); */
602 blob_reset(&b);
603 }
604 }
@@ -626,17 +626,21 @@
626 ** of the following structure.
627 */
628 typedef struct Annotator Annotator;
629 struct Annotator {
630 DContext c; /* The diff-engine context */
631 struct AnnLine { /* Lines of the original files... */
632 const char *z; /* The text of the line */
633 short int n; /* Number of bytes (omitting trailing space and \n) */
634 short int iLevel; /* Level at which tag was set */
635 const char *zSrc; /* Tag showing origin of this line */
636 } *aOrig;
637 int nOrig; /* Number of elements in aOrig[] */
638 int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */
639 int iLevel; /* Current level */
640 int nVers; /* Number of versions analyzed */
641 char **azVers; /* Names of versions analyzed */
642 };
643
644 /*
645 ** Initialize the annotation process by specifying the file that is
646 ** to be annotated. The annotator takes control of the input Blob and
@@ -668,10 +672,12 @@
672 ** pParent. Memory to hold zPName is leaked.
673 */
674 static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
675 int i, j;
676 int lnTo;
677 int iPrevLevel;
678 int iThisLevel;
679
680 /* Prepare the parent file to be diffed */
681 p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent),
682 &p->c.nFrom, 1);
683 if( p->c.aFrom==0 ){
@@ -683,13 +689,20 @@
689 diff_all(&p->c);
690
691 /* Where new lines are inserted on this difference, record the
692 ** zPName as the source of the new line.
693 */
694 iPrevLevel = p->iLevel;
695 p->iLevel++;
696 iThisLevel = p->iLevel;
697 for(i=lnTo=0; i<p->c.nEdit; i+=3){
698 struct AnnLine *x = &p->aOrig[lnTo];
699 for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
700 if( x->zSrc==0 || x->iLevel==iPrevLevel ){
701 x->zSrc = zPName;
702 x->iLevel = iThisLevel;
703 }
704 }
705 lnTo += p->c.aEdit[i+2];
706 }
707
708 /* Clear out the diff results */
@@ -730,20 +743,30 @@
743 }
744 }
745 for(i=0; i<x.nOrig; i++){
746 const char *zSrc = x.aOrig[i].zSrc;
747 if( zSrc==0 ) zSrc = g.argv[g.argc-1];
748 fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
749 }
750 }
751
752 /* Annotation flags */
753 #define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
754
755 /*
756 ** Compute a complete annotation on a file. The file is identified
757 ** by its filename number (filename.fnid) and the baseline in which
758 ** it was checked in (mlink.mid).
759 */
760 static void annotate_file(
761 Annotator *p, /* The annotator */
762 int fnid, /* The name of the file to be annotated */
763 int mid, /* The specific version of the file for this step */
764 int webLabel, /* Use web-style annotations if true */
765 int iLimit, /* Limit the number of levels if greater than zero */
766 int annFlags /* Flags to alter the annotation */
767 ){
768 Blob toAnnotate; /* Text of the final version of the file */
769 Blob step; /* Text of previous revision */
770 int rid; /* Artifact ID of the file being annotated */
771 char *zLabel; /* Label to apply to a line */
772 Stmt q; /* Query returning all ancestor versions */
@@ -759,31 +782,40 @@
782 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
783 compute_ancestors(mid, 1000000000);
784 annotation_start(p, &toAnnotate);
785
786 db_prepare(&q,
787 "SELECT mlink.fid,"
788 " (SELECT uuid FROM blob WHERE rid=mlink.%s),"
789 " date(event.mtime), "
790 " coalesce(event.euser,event.user) "
791 " FROM mlink, event"
792 " WHERE mlink.fnid=%d"
793 " AND mlink.mid IN ok"
 
794 " AND event.objid=mlink.mid"
795 " ORDER BY event.mtime DESC"
796 " LIMIT %d",
797 (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid",
798 fnid,
799 iLimit>0 ? iLimit : 10000000
800 );
801 while( db_step(&q)==SQLITE_ROW ){
802 int pid = db_column_int(&q, 0);
803 const char *zUuid = db_column_text(&q, 1);
804 const char *zDate = db_column_text(&q, 2);
805 const char *zUser = db_column_text(&q, 3);
806 if( webLabel ){
807 zLabel = mprintf(
808 "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s",
809 g.zTop, zUuid, zUuid, zDate, zUser
810 );
811 }else{
812 zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
813 }
814 p->nVers++;
815 p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
816 p->azVers[p->nVers-1] = zLabel;
817 content_get(pid, &step);
818 annotation_step(p, &step, zLabel);
819 blob_reset(&step);
820 }
821 db_finalize(&q);
@@ -799,22 +831,37 @@
831 */
832 void annotation_page(void){
833 int mid;
834 int fnid;
835 int i;
836 int iLimit;
837 int annFlags = 0;
838 Annotator ann;
839
840 login_check_credentials();
841 if( !g.okRead ){ login_needed(); return; }
842 mid = name_to_rid(PD("checkin","0"));
843 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
844 if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
845 iLimit = atoi(PD("limit","-1"));
846 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
847 fossil_redirect_home();
848 }
849 style_header("File Annotation");
850 if( P("filevers") ) annFlags |= ANN_FILE_VERS;
851 annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags);
852 if( P("log") ){
853 int i;
854 @ <h2>Versions analyzed:</h2>
855 @ <ol>
856 for(i=0; i<ann.nVers; i++){
857 @ <li><tt>%s(ann.azVers[i])</tt></li>
858 }
859 @ </ol>
860 @ <hr>
861 @ <h2>Annotation:</h2>
862 }
863 @ <pre>
864 for(i=0; i<ann.nOrig; i++){
865 ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
866 @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
867 }
@@ -827,20 +874,35 @@
874 **
875 ** %fossil annotate FILENAME
876 **
877 ** Output the text of a file with markings to show when each line of
878 ** the file was last modified.
879 **
880 ** Options:
881 ** --limit N Only look backwards in time by N versions
882 ** --log List all versions analyzed
883 ** --filevers Show file version numbers rather than check-in versions
884 */
885 void annotate_cmd(void){
886 int fnid; /* Filename ID */
887 int fid; /* File instance ID */
888 int mid; /* Manifest where file was checked in */
889 Blob treename; /* FILENAME translated to canonical form */
890 char *zFilename; /* Cannonical filename */
891 Annotator ann; /* The annotation of the file */
892 int i; /* Loop counter */
893 const char *zLimit; /* The value to the --limit option */
894 int iLimit; /* How far back in time to look */
895 int showLog; /* True to show the log */
896 int fileVers; /* Show file version instead of check-in versions */
897 int annFlags = 0; /* Flags to control annotation properties */
898
899 zLimit = find_option("limit",0,1);
900 if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
901 iLimit = atoi(zLimit);
902 showLog = find_option("log",0,0)!=0;
903 fileVers = find_option("filevers",0,0)!=0;
904 db_must_be_within_tree();
905 if (g.argc<3) {
906 usage("FILENAME");
907 }
908 file_tree_name(g.argv[2], &treename, 1);
@@ -855,10 +917,18 @@
917 }
918 mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
919 if( mid==0 ){
920 fossil_panic("unable to find manifest");
921 }
922 if( fileVers ) annFlags |= ANN_FILE_VERS;
923 annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
924 if( showLog ){
925 for(i=0; i<ann.nVers; i++){
926 printf("version %3d: %s\n", i+1, ann.azVers[i]);
927 }
928 printf("---------------------------------------------------\n");
929 }
930 for(i=0; i<ann.nOrig; i++){
931 fossil_print("%s: %.*s\n",
932 ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
933 }
934 }
935
+5 -5
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -100,11 +100,11 @@
100100
** zFile2 */
101101
blob_zero(&nameFile1);
102102
do{
103103
blob_reset(&nameFile1);
104104
blob_appendf(&nameFile1, "%s~%d", zFile2, cnt++);
105
- }while( access(blob_str(&nameFile1),0)==0 );
105
+ }while( file_access(blob_str(&nameFile1),0)==0 );
106106
blob_write_to_file(pFile1, blob_str(&nameFile1));
107107
108108
/* Construct the external diff command */
109109
blob_zero(&cmd);
110110
blob_appendf(&cmd, "%s ", zDiffCmd);
@@ -114,11 +114,11 @@
114114
115115
/* Run the external diff command */
116116
fossil_system(blob_str(&cmd));
117117
118118
/* Delete the temporary file and clean up memory used */
119
- unlink(blob_str(&nameFile1));
119
+ file_delete(blob_str(&nameFile1));
120120
blob_reset(&nameFile1);
121121
blob_reset(&cmd);
122122
}
123123
}
124124
@@ -168,12 +168,12 @@
168168
169169
/* Run the external diff command */
170170
fossil_system(blob_str(&cmd));
171171
172172
/* Delete the temporary file and clean up memory used */
173
- unlink(zTemp1);
174
- unlink(zTemp2);
173
+ file_delete(zTemp1);
174
+ file_delete(zTemp2);
175175
blob_reset(&cmd);
176176
}
177177
}
178178
179179
/*
@@ -263,11 +263,11 @@
263263
char *zToFree = zFullName;
264264
int showDiff = 1;
265265
if( isDeleted ){
266266
diff_printf("DELETED %s\n", zPathname);
267267
if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
268
- }else if( access(zFullName, 0) ){
268
+ }else if( file_access(zFullName, 0) ){
269269
diff_printf("MISSING %s\n", zPathname);
270270
if( !asNewFile ){ showDiff = 0; }
271271
}else if( isNew ){
272272
diff_printf("ADDED %s\n", zPathname);
273273
srcid = 0;
274274
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -100,11 +100,11 @@
100 ** zFile2 */
101 blob_zero(&nameFile1);
102 do{
103 blob_reset(&nameFile1);
104 blob_appendf(&nameFile1, "%s~%d", zFile2, cnt++);
105 }while( access(blob_str(&nameFile1),0)==0 );
106 blob_write_to_file(pFile1, blob_str(&nameFile1));
107
108 /* Construct the external diff command */
109 blob_zero(&cmd);
110 blob_appendf(&cmd, "%s ", zDiffCmd);
@@ -114,11 +114,11 @@
114
115 /* Run the external diff command */
116 fossil_system(blob_str(&cmd));
117
118 /* Delete the temporary file and clean up memory used */
119 unlink(blob_str(&nameFile1));
120 blob_reset(&nameFile1);
121 blob_reset(&cmd);
122 }
123 }
124
@@ -168,12 +168,12 @@
168
169 /* Run the external diff command */
170 fossil_system(blob_str(&cmd));
171
172 /* Delete the temporary file and clean up memory used */
173 unlink(zTemp1);
174 unlink(zTemp2);
175 blob_reset(&cmd);
176 }
177 }
178
179 /*
@@ -263,11 +263,11 @@
263 char *zToFree = zFullName;
264 int showDiff = 1;
265 if( isDeleted ){
266 diff_printf("DELETED %s\n", zPathname);
267 if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
268 }else if( access(zFullName, 0) ){
269 diff_printf("MISSING %s\n", zPathname);
270 if( !asNewFile ){ showDiff = 0; }
271 }else if( isNew ){
272 diff_printf("ADDED %s\n", zPathname);
273 srcid = 0;
274
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -100,11 +100,11 @@
100 ** zFile2 */
101 blob_zero(&nameFile1);
102 do{
103 blob_reset(&nameFile1);
104 blob_appendf(&nameFile1, "%s~%d", zFile2, cnt++);
105 }while( file_access(blob_str(&nameFile1),0)==0 );
106 blob_write_to_file(pFile1, blob_str(&nameFile1));
107
108 /* Construct the external diff command */
109 blob_zero(&cmd);
110 blob_appendf(&cmd, "%s ", zDiffCmd);
@@ -114,11 +114,11 @@
114
115 /* Run the external diff command */
116 fossil_system(blob_str(&cmd));
117
118 /* Delete the temporary file and clean up memory used */
119 file_delete(blob_str(&nameFile1));
120 blob_reset(&nameFile1);
121 blob_reset(&cmd);
122 }
123 }
124
@@ -168,12 +168,12 @@
168
169 /* Run the external diff command */
170 fossil_system(blob_str(&cmd));
171
172 /* Delete the temporary file and clean up memory used */
173 file_delete(zTemp1);
174 file_delete(zTemp2);
175 blob_reset(&cmd);
176 }
177 }
178
179 /*
@@ -263,11 +263,11 @@
263 char *zToFree = zFullName;
264 int showDiff = 1;
265 if( isDeleted ){
266 diff_printf("DELETED %s\n", zPathname);
267 if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
268 }else if( file_access(zFullName, 0) ){
269 diff_printf("MISSING %s\n", zPathname);
270 if( !asNewFile ){ showDiff = 0; }
271 }else if( isNew ){
272 diff_printf("ADDED %s\n", zPathname);
273 srcid = 0;
274
+4 -4
--- src/encode.c
+++ src/encode.c
@@ -340,11 +340,11 @@
340340
void test_encode64_cmd(void){
341341
char *z;
342342
int i;
343343
for(i=2; i<g.argc; i++){
344344
z = encode64(g.argv[i], -1);
345
- printf("%s\n", z);
345
+ fossil_print("%s\n", z);
346346
free(z);
347347
}
348348
}
349349
350350
@@ -405,11 +405,11 @@
405405
void test_decode64_cmd(void){
406406
char *z;
407407
int i, n;
408408
for(i=2; i<g.argc; i++){
409409
z = decode64(g.argv[i], &n);
410
- printf("%d: %s\n", n, z);
410
+ fossil_print("%d: %s\n", n, z);
411411
free(z);
412412
}
413413
}
414414
415415
/*
@@ -579,13 +579,13 @@
579579
int i;
580580
char *z, *z2;
581581
for(i=2; i<g.argc; i++){
582582
z = obscure(g.argv[i]);
583583
z2 = unobscure(z);
584
- printf("OBSCURE: %s -> %s (%s)\n", g.argv[i], z, z2);
584
+ fossil_print("OBSCURE: %s -> %s (%s)\n", g.argv[i], z, z2);
585585
free(z);
586586
free(z2);
587587
z = unobscure(g.argv[i]);
588
- printf("UNOBSCURE: %s -> %s\n", g.argv[i], z);
588
+ fossil_print("UNOBSCURE: %s -> %s\n", g.argv[i], z);
589589
free(z);
590590
}
591591
}
592592
--- src/encode.c
+++ src/encode.c
@@ -340,11 +340,11 @@
340 void test_encode64_cmd(void){
341 char *z;
342 int i;
343 for(i=2; i<g.argc; i++){
344 z = encode64(g.argv[i], -1);
345 printf("%s\n", z);
346 free(z);
347 }
348 }
349
350
@@ -405,11 +405,11 @@
405 void test_decode64_cmd(void){
406 char *z;
407 int i, n;
408 for(i=2; i<g.argc; i++){
409 z = decode64(g.argv[i], &n);
410 printf("%d: %s\n", n, z);
411 free(z);
412 }
413 }
414
415 /*
@@ -579,13 +579,13 @@
579 int i;
580 char *z, *z2;
581 for(i=2; i<g.argc; i++){
582 z = obscure(g.argv[i]);
583 z2 = unobscure(z);
584 printf("OBSCURE: %s -> %s (%s)\n", g.argv[i], z, z2);
585 free(z);
586 free(z2);
587 z = unobscure(g.argv[i]);
588 printf("UNOBSCURE: %s -> %s\n", g.argv[i], z);
589 free(z);
590 }
591 }
592
--- src/encode.c
+++ src/encode.c
@@ -340,11 +340,11 @@
340 void test_encode64_cmd(void){
341 char *z;
342 int i;
343 for(i=2; i<g.argc; i++){
344 z = encode64(g.argv[i], -1);
345 fossil_print("%s\n", z);
346 free(z);
347 }
348 }
349
350
@@ -405,11 +405,11 @@
405 void test_decode64_cmd(void){
406 char *z;
407 int i, n;
408 for(i=2; i<g.argc; i++){
409 z = decode64(g.argv[i], &n);
410 fossil_print("%d: %s\n", n, z);
411 free(z);
412 }
413 }
414
415 /*
@@ -579,13 +579,13 @@
579 int i;
580 char *z, *z2;
581 for(i=2; i<g.argc; i++){
582 z = obscure(g.argv[i]);
583 z2 = unobscure(z);
584 fossil_print("OBSCURE: %s -> %s (%s)\n", g.argv[i], z, z2);
585 free(z);
586 free(z2);
587 z = unobscure(g.argv[i]);
588 fossil_print("UNOBSCURE: %s -> %s\n", g.argv[i], z);
589 free(z);
590 }
591 }
592
+4 -4
--- src/export.c
+++ src/export.c
@@ -139,11 +139,11 @@
139139
" WHERE type='ci'"
140140
" ORDER BY mtime ASC",
141141
TAG_BRANCH
142142
);
143143
while( db_step(&q)==SQLITE_ROW ){
144
- sqlite3_int64 secondsSince1970 = db_column_int64(&q, 0);
144
+ const char *zSecondsSince1970 = db_column_text(&q, 0);
145145
int ckinId = db_column_int(&q, 1);
146146
const char *zComment = db_column_text(&q, 2);
147147
const char *zUser = db_column_text(&q, 3);
148148
const char *zBranch = db_column_text(&q, 4);
149149
char *zBr;
@@ -159,11 +159,11 @@
159159
}
160160
printf("commit refs/heads/%s\nmark :%d\n", zBr, ckinId+firstCkin);
161161
free(zBr);
162162
printf("committer");
163163
print_person(zUser);
164
- printf(" %lld +0000\n", secondsSince1970);
164
+ printf(" %s +0000\n", zSecondsSince1970);
165165
if( zComment==0 ) zComment = "null comment";
166166
printf("data %d\n%s\n", (int)strlen(zComment), zComment);
167167
p = manifest_get(ckinId, CFTYPE_ANY);
168168
zFromType = "from";
169169
for(i=0; i<p->nParent; i++){
@@ -197,16 +197,16 @@
197197
" WHERE tagtype=1 AND tagname GLOB 'sym-*'"
198198
);
199199
while( db_step(&q)==SQLITE_ROW ){
200200
const char *zTagname = db_column_text(&q, 0);
201201
int rid = db_column_int(&q, 1);
202
- sqlite3_int64 secSince1970 = db_column_int64(&q, 2);
202
+ const char *zSecSince1970 = db_column_text(&q, 2);
203203
if( rid==0 || !bag_find(&vers, rid) ) continue;
204204
zTagname += 4;
205205
printf("tag %s\n", zTagname);
206206
printf("from :%d\n", rid+firstCkin);
207
- printf("tagger <tagger> %lld +0000\n", secSince1970);
207
+ printf("tagger <tagger> %s +0000\n", zSecSince1970);
208208
printf("data 0\n");
209209
}
210210
db_finalize(&q);
211211
bag_clear(&vers);
212212
}
213213
--- src/export.c
+++ src/export.c
@@ -139,11 +139,11 @@
139 " WHERE type='ci'"
140 " ORDER BY mtime ASC",
141 TAG_BRANCH
142 );
143 while( db_step(&q)==SQLITE_ROW ){
144 sqlite3_int64 secondsSince1970 = db_column_int64(&q, 0);
145 int ckinId = db_column_int(&q, 1);
146 const char *zComment = db_column_text(&q, 2);
147 const char *zUser = db_column_text(&q, 3);
148 const char *zBranch = db_column_text(&q, 4);
149 char *zBr;
@@ -159,11 +159,11 @@
159 }
160 printf("commit refs/heads/%s\nmark :%d\n", zBr, ckinId+firstCkin);
161 free(zBr);
162 printf("committer");
163 print_person(zUser);
164 printf(" %lld +0000\n", secondsSince1970);
165 if( zComment==0 ) zComment = "null comment";
166 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
167 p = manifest_get(ckinId, CFTYPE_ANY);
168 zFromType = "from";
169 for(i=0; i<p->nParent; i++){
@@ -197,16 +197,16 @@
197 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
198 );
199 while( db_step(&q)==SQLITE_ROW ){
200 const char *zTagname = db_column_text(&q, 0);
201 int rid = db_column_int(&q, 1);
202 sqlite3_int64 secSince1970 = db_column_int64(&q, 2);
203 if( rid==0 || !bag_find(&vers, rid) ) continue;
204 zTagname += 4;
205 printf("tag %s\n", zTagname);
206 printf("from :%d\n", rid+firstCkin);
207 printf("tagger <tagger> %lld +0000\n", secSince1970);
208 printf("data 0\n");
209 }
210 db_finalize(&q);
211 bag_clear(&vers);
212 }
213
--- src/export.c
+++ src/export.c
@@ -139,11 +139,11 @@
139 " WHERE type='ci'"
140 " ORDER BY mtime ASC",
141 TAG_BRANCH
142 );
143 while( db_step(&q)==SQLITE_ROW ){
144 const char *zSecondsSince1970 = db_column_text(&q, 0);
145 int ckinId = db_column_int(&q, 1);
146 const char *zComment = db_column_text(&q, 2);
147 const char *zUser = db_column_text(&q, 3);
148 const char *zBranch = db_column_text(&q, 4);
149 char *zBr;
@@ -159,11 +159,11 @@
159 }
160 printf("commit refs/heads/%s\nmark :%d\n", zBr, ckinId+firstCkin);
161 free(zBr);
162 printf("committer");
163 print_person(zUser);
164 printf(" %s +0000\n", zSecondsSince1970);
165 if( zComment==0 ) zComment = "null comment";
166 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
167 p = manifest_get(ckinId, CFTYPE_ANY);
168 zFromType = "from";
169 for(i=0; i<p->nParent; i++){
@@ -197,16 +197,16 @@
197 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
198 );
199 while( db_step(&q)==SQLITE_ROW ){
200 const char *zTagname = db_column_text(&q, 0);
201 int rid = db_column_int(&q, 1);
202 const char *zSecSince1970 = db_column_text(&q, 2);
203 if( rid==0 || !bag_find(&vers, rid) ) continue;
204 zTagname += 4;
205 printf("tag %s\n", zTagname);
206 printf("from :%d\n", rid+firstCkin);
207 printf("tagger <tagger> %s +0000\n", zSecSince1970);
208 printf("data 0\n");
209 }
210 db_finalize(&q);
211 bag_clear(&vers);
212 }
213
+176 -28
--- src/file.c
+++ src/file.c
@@ -47,17 +47,19 @@
4747
static int getStat(const char *zFilename){
4848
int rc = 0;
4949
if( zFilename==0 ){
5050
if( fileStatValid==0 ) rc = 1;
5151
}else{
52
- if( stat(zFilename, &fileStat)!=0 ){
52
+ char *zMbcs = fossil_utf8_to_mbcs(zFilename);
53
+ if( stat(zMbcs, &fileStat)!=0 ){
5354
fileStatValid = 0;
5455
rc = 1;
5556
}else{
5657
fileStatValid = 1;
5758
rc = 0;
5859
}
60
+ fossil_mbcs_free(zMbcs);
5961
}
6062
return rc;
6163
}
6264
6365
@@ -120,10 +122,20 @@
120122
}else{
121123
rc = getStat(0);
122124
}
123125
return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
124126
}
127
+
128
+/*
129
+** Wrapper around the access() system call.
130
+*/
131
+int file_access(const char *zFilename, int flags){
132
+ char *zMbcs = fossil_utf8_to_mbcs(zFilename);
133
+ int rc = access(zMbcs, flags);
134
+ fossil_mbcs_free(zMbcs);
135
+ return rc;
136
+}
125137
126138
/*
127139
** Find an unused filename similar to zBase with zSuffix appended.
128140
**
129141
** Make the name relative to the working directory if relFlag is true.
@@ -166,13 +178,13 @@
166178
*/
167179
void file_copy(const char *zFrom, const char *zTo){
168180
FILE *in, *out;
169181
int got;
170182
char zBuf[8192];
171
- in = fopen(zFrom, "rb");
183
+ in = fossil_fopen(zFrom, "rb");
172184
if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
173
- out = fopen(zTo, "wb");
185
+ out = fossil_fopen(zTo, "wb");
174186
if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
175187
while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
176188
fwrite(zBuf, 1, got, out);
177189
}
178190
fclose(in);
@@ -200,10 +212,19 @@
200212
}
201213
}
202214
#endif /* _WIN32 */
203215
return rc;
204216
}
217
+
218
+/*
219
+** Delete a file.
220
+*/
221
+void file_delete(const char *zFilename){
222
+ char *z = fossil_utf8_to_mbcs(zFilename);
223
+ unlink(z);
224
+ fossil_mbcs_free(z);
225
+}
205226
206227
/*
207228
** Create the directory named in the argument, if it does not already
208229
** exist. If forceFlag is 1, delete any prior non-directory object
209230
** with the same name.
@@ -212,15 +233,19 @@
212233
*/
213234
int file_mkdir(const char *zName, int forceFlag){
214235
int rc = file_isdir(zName);
215236
if( rc==2 ){
216237
if( !forceFlag ) return 1;
217
- unlink(zName);
238
+ file_delete(zName);
218239
}
219240
if( rc!=1 ){
220241
#if defined(_WIN32)
221
- return mkdir(zName);
242
+ int rc;
243
+ char *zMbcs = fossil_utf8_to_mbcs(zName);
244
+ rc = mkdir(zMbcs);
245
+ fossil_mbcs_free(zMbcs);
246
+ return rc;
222247
#else
223248
return mkdir(zName, 0755);
224249
#endif
225250
}
226251
return 0;
@@ -350,16 +375,47 @@
350375
void cmd_test_simplify_name(void){
351376
int i;
352377
char *z;
353378
for(i=2; i<g.argc; i++){
354379
z = mprintf("%s", g.argv[i]);
355
- printf("[%s] -> ", z);
380
+ fossil_print("[%s] -> ", z);
356381
file_simplify_name(z, -1);
357
- printf("[%s]\n", z);
382
+ fossil_print("[%s]\n", z);
358383
fossil_free(z);
359384
}
360385
}
386
+
387
+/*
388
+** Get the current working directory.
389
+**
390
+** On windows, the name is converted from MBCS to UTF8 and all '\\'
391
+** characters are converted to '/'. No conversions are needed on
392
+** unix.
393
+*/
394
+void file_getcwd(char *zBuf, int nBuf){
395
+#ifdef _WIN32
396
+ char *zPwdUtf8;
397
+ int nPwd;
398
+ int i;
399
+ char zPwd[2000];
400
+ if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
401
+ fossil_fatal("pwd too big: max %d\n", (int)sizeof(zPwd)-1);
402
+ }
403
+ zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
404
+ nPwd = strlen(zPwdUtf8);
405
+ if( nPwd > nBuf-1 ){
406
+ fossil_fatal("pwd too big: max %d\n", nBuf-1);
407
+ }
408
+ for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
409
+ memcpy(zBuf, zPwdUtf8, nPwd+1);
410
+ fossil_mbcs_free(zPwdUtf8);
411
+#else
412
+ if( getcwd(zBuf, nBuf-1)==0 ){
413
+ fossil_fatal("pwd too big: max %d\n", nBuf-1);
414
+ }
415
+#endif
416
+}
361417
362418
/*
363419
** Compute a canonical pathname for a file or directory.
364420
** Make the name absolute if it is relative.
365421
** Remove redundant / characters
@@ -376,14 +432,11 @@
376432
){
377433
blob_set(pOut, zOrigName);
378434
blob_materialize(pOut);
379435
}else{
380436
char zPwd[2000];
381
- if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
382
- fprintf(stderr, "pwd too big: max %d\n", (int)sizeof(zPwd)-20);
383
- fossil_exit(1);
384
- }
437
+ file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
385438
blob_zero(pOut);
386439
blob_appendf(pOut, "%//%/", zPwd, zOrigName);
387440
}
388441
blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
389442
}
@@ -401,19 +454,19 @@
401454
blob_zero(&x);
402455
for(i=2; i<g.argc; i++){
403456
char zBuf[100];
404457
const char *zName = g.argv[i];
405458
file_canonical_name(zName, &x);
406
- printf("[%s] -> [%s]\n", zName, blob_buffer(&x));
459
+ fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
407460
blob_reset(&x);
408461
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName));
409
- printf(" file_size = %s\n", zBuf);
462
+ fossil_print(" file_size = %s\n", zBuf);
410463
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName));
411
- printf(" file_mtime = %s\n", zBuf);
412
- printf(" file_isfile = %d\n", file_isfile(zName));
413
- printf(" file_isexe = %d\n", file_isexe(zName));
414
- printf(" file_isdir = %d\n", file_isdir(zName));
464
+ fossil_print(" file_mtime = %s\n", zBuf);
465
+ fossil_print(" file_isfile = %d\n", file_isfile(zName));
466
+ fossil_print(" file_isexe = %d\n", file_isexe(zName));
467
+ fossil_print(" file_isdir = %d\n", file_isdir(zName));
415468
}
416469
}
417470
418471
/*
419472
** Return TRUE if the given filename is canonical.
@@ -452,14 +505,11 @@
452505
zPath = blob_buffer(pOut);
453506
if( zPath[0]=='/' ){
454507
int i, j;
455508
Blob tmp;
456509
char zPwd[2000];
457
- if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
458
- fprintf(stderr, "pwd too big: max %d\n", (int)sizeof(zPwd)-20);
459
- fossil_exit(1);
460
- }
510
+ file_getcwd(zPwd, sizeof(zPwd)-20);
461511
for(i=1; zPath[i] && zPwd[i]==zPath[i]; i++){}
462512
if( zPath[i]==0 ){
463513
blob_reset(pOut);
464514
if( zPwd[i]==0 ){
465515
blob_append(pOut, ".", 1);
@@ -502,11 +552,11 @@
502552
int i;
503553
Blob x;
504554
blob_zero(&x);
505555
for(i=2; i<g.argc; i++){
506556
file_relative_name(g.argv[i], &x);
507
- printf("%s\n", blob_buffer(&x));
557
+ fossil_print("%s\n", blob_buffer(&x));
508558
blob_reset(&x);
509559
}
510560
}
511561
512562
/*
@@ -557,11 +607,11 @@
557607
int i;
558608
Blob x;
559609
blob_zero(&x);
560610
for(i=2; i<g.argc; i++){
561611
if( file_tree_name(g.argv[i], &x, 1) ){
562
- printf("%s\n", blob_buffer(&x));
612
+ fossil_print("%s\n", blob_buffer(&x));
563613
blob_reset(&x);
564614
}
565615
}
566616
}
567617
@@ -620,17 +670,14 @@
620670
static const unsigned char zChars[] =
621671
"abcdefghijklmnopqrstuvwxyz"
622672
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
623673
"0123456789";
624674
unsigned int i, j;
625
- struct stat buf;
626675
const char *zDir = ".";
627676
628677
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
629
- if( stat(azDirs[i], &buf) ) continue;
630
- if( !S_ISDIR(buf.st_mode) ) continue;
631
- if( access(azDirs[i], 07) ) continue;
678
+ if( !file_isdir(azDirs[i]) ) continue;
632679
zDir = azDirs[i];
633680
break;
634681
}
635682
636683
/* Check that the output buffer is large enough for the temporary file
@@ -646,11 +693,11 @@
646693
sqlite3_randomness(15, &zBuf[j]);
647694
for(i=0; i<15; i++, j++){
648695
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
649696
}
650697
zBuf[j] = 0;
651
- }while( access(zBuf,0)==0 );
698
+ }while( file_size(zBuf)<0 );
652699
}
653700
654701
655702
/*
656703
** Return true if a file named zName exists and has identical content
@@ -668,5 +715,106 @@
668715
blob_read_from_file(&onDisk, zName);
669716
rc = blob_compare(&onDisk, pContent);
670717
blob_reset(&onDisk);
671718
return rc==0;
672719
}
720
+
721
+
722
+/**************************************************************************
723
+** The following routines translate between MBCS and UTF8 on windows.
724
+** Since everything is always UTF8 on unix, these routines are no-ops
725
+** there.
726
+*/
727
+#ifdef _WIN32
728
+# include <windows.h>
729
+#endif
730
+
731
+/*
732
+** Translate MBCS to UTF8. Return a pointer to the translated text.
733
+** Call fossil_mbcs_free() to deallocate any memory used to store the
734
+** returned pointer when done.
735
+*/
736
+char *fossil_mbcs_to_utf8(const char *zMbcs){
737
+#ifdef _WIN32
738
+ extern char *sqlite3_win32_mbcs_to_utf8(const char*);
739
+ return sqlite3_win32_mbcs_to_utf8(zMbcs);
740
+#else
741
+ return (char*)zMbcs; /* No-op on unix */
742
+#endif
743
+}
744
+
745
+/*
746
+** Translate UTF8 to MBCS for use in system calls. Return a pointer to the
747
+** translated text.. Call fossil_mbcs_free() to deallocate any memory
748
+** used to store the returned pointer when done.
749
+*/
750
+char *fossil_utf8_to_mbcs(const char *zUtf8){
751
+#ifdef _WIN32
752
+ extern char *sqlite3_win32_utf8_to_mbcs(const char*);
753
+ return sqlite3_win32_utf8_to_mbcs(zUtf8);
754
+#else
755
+ return (char*)zUtf8; /* No-op on unix */
756
+#endif
757
+}
758
+
759
+/*
760
+** Translate UTF8 to MBCS for display on the console. Return a pointer to the
761
+** translated text.. Call fossil_mbcs_free() to deallocate any memory
762
+** used to store the returned pointer when done.
763
+*/
764
+char *fossil_utf8_to_console(const char *zUtf8){
765
+#ifdef _WIN32
766
+ int nChar, nByte;
767
+ WCHAR *zUnicode; /* Unicode version of zUtf8 */
768
+ char *zConsole; /* Console version of zUtf8 */
769
+ int codepage; /* Console code page */
770
+
771
+ nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, NULL, 0);
772
+ zUnicode = malloc( nChar*sizeof(zUnicode[0]) );
773
+ if( zUnicode==0 ){
774
+ return 0;
775
+ }
776
+ nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
777
+ if( nChar==0 ){
778
+ free(zUnicode);
779
+ return 0;
780
+ }
781
+ codepage = GetConsoleCP();
782
+ nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, 0, 0, 0, 0);
783
+ zConsole = malloc( nByte );
784
+ if( zConsole==0 ){
785
+ free(zUnicode);
786
+ return 0;
787
+ }
788
+ nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, zConsole, nByte, 0, 0);
789
+ free(zUnicode);
790
+ if( nByte == 0 ){
791
+ free(zConsole);
792
+ zConsole = 0;
793
+ }
794
+ return zConsole;
795
+#else
796
+ return (char*)zUtf8; /* No-op on unix */
797
+#endif
798
+}
799
+
800
+/*
801
+** Translate MBCS to UTF8. Return a pointer. Call fossil_mbcs_free()
802
+** to deallocate any memory used to store the returned pointer when done.
803
+*/
804
+void fossil_mbcs_free(char *zOld){
805
+#ifdef _WIN32
806
+ free(zOld);
807
+#else
808
+ /* No-op on unix */
809
+#endif
810
+}
811
+
812
+/*
813
+** Like fopen() but always takes a UTF8 argument.
814
+*/
815
+FILE *fossil_fopen(const char *zName, const char *zMode){
816
+ char *zMbcs = fossil_utf8_to_mbcs(zName);
817
+ FILE *f = fopen(zMbcs, zMode);
818
+ fossil_mbcs_free(zMbcs);
819
+ return f;
820
+}
673821
--- src/file.c
+++ src/file.c
@@ -47,17 +47,19 @@
47 static int getStat(const char *zFilename){
48 int rc = 0;
49 if( zFilename==0 ){
50 if( fileStatValid==0 ) rc = 1;
51 }else{
52 if( stat(zFilename, &fileStat)!=0 ){
 
53 fileStatValid = 0;
54 rc = 1;
55 }else{
56 fileStatValid = 1;
57 rc = 0;
58 }
 
59 }
60 return rc;
61 }
62
63
@@ -120,10 +122,20 @@
120 }else{
121 rc = getStat(0);
122 }
123 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
124 }
 
 
 
 
 
 
 
 
 
 
125
126 /*
127 ** Find an unused filename similar to zBase with zSuffix appended.
128 **
129 ** Make the name relative to the working directory if relFlag is true.
@@ -166,13 +178,13 @@
166 */
167 void file_copy(const char *zFrom, const char *zTo){
168 FILE *in, *out;
169 int got;
170 char zBuf[8192];
171 in = fopen(zFrom, "rb");
172 if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
173 out = fopen(zTo, "wb");
174 if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
175 while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
176 fwrite(zBuf, 1, got, out);
177 }
178 fclose(in);
@@ -200,10 +212,19 @@
200 }
201 }
202 #endif /* _WIN32 */
203 return rc;
204 }
 
 
 
 
 
 
 
 
 
205
206 /*
207 ** Create the directory named in the argument, if it does not already
208 ** exist. If forceFlag is 1, delete any prior non-directory object
209 ** with the same name.
@@ -212,15 +233,19 @@
212 */
213 int file_mkdir(const char *zName, int forceFlag){
214 int rc = file_isdir(zName);
215 if( rc==2 ){
216 if( !forceFlag ) return 1;
217 unlink(zName);
218 }
219 if( rc!=1 ){
220 #if defined(_WIN32)
221 return mkdir(zName);
 
 
 
 
222 #else
223 return mkdir(zName, 0755);
224 #endif
225 }
226 return 0;
@@ -350,16 +375,47 @@
350 void cmd_test_simplify_name(void){
351 int i;
352 char *z;
353 for(i=2; i<g.argc; i++){
354 z = mprintf("%s", g.argv[i]);
355 printf("[%s] -> ", z);
356 file_simplify_name(z, -1);
357 printf("[%s]\n", z);
358 fossil_free(z);
359 }
360 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
362 /*
363 ** Compute a canonical pathname for a file or directory.
364 ** Make the name absolute if it is relative.
365 ** Remove redundant / characters
@@ -376,14 +432,11 @@
376 ){
377 blob_set(pOut, zOrigName);
378 blob_materialize(pOut);
379 }else{
380 char zPwd[2000];
381 if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
382 fprintf(stderr, "pwd too big: max %d\n", (int)sizeof(zPwd)-20);
383 fossil_exit(1);
384 }
385 blob_zero(pOut);
386 blob_appendf(pOut, "%//%/", zPwd, zOrigName);
387 }
388 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
389 }
@@ -401,19 +454,19 @@
401 blob_zero(&x);
402 for(i=2; i<g.argc; i++){
403 char zBuf[100];
404 const char *zName = g.argv[i];
405 file_canonical_name(zName, &x);
406 printf("[%s] -> [%s]\n", zName, blob_buffer(&x));
407 blob_reset(&x);
408 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName));
409 printf(" file_size = %s\n", zBuf);
410 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName));
411 printf(" file_mtime = %s\n", zBuf);
412 printf(" file_isfile = %d\n", file_isfile(zName));
413 printf(" file_isexe = %d\n", file_isexe(zName));
414 printf(" file_isdir = %d\n", file_isdir(zName));
415 }
416 }
417
418 /*
419 ** Return TRUE if the given filename is canonical.
@@ -452,14 +505,11 @@
452 zPath = blob_buffer(pOut);
453 if( zPath[0]=='/' ){
454 int i, j;
455 Blob tmp;
456 char zPwd[2000];
457 if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
458 fprintf(stderr, "pwd too big: max %d\n", (int)sizeof(zPwd)-20);
459 fossil_exit(1);
460 }
461 for(i=1; zPath[i] && zPwd[i]==zPath[i]; i++){}
462 if( zPath[i]==0 ){
463 blob_reset(pOut);
464 if( zPwd[i]==0 ){
465 blob_append(pOut, ".", 1);
@@ -502,11 +552,11 @@
502 int i;
503 Blob x;
504 blob_zero(&x);
505 for(i=2; i<g.argc; i++){
506 file_relative_name(g.argv[i], &x);
507 printf("%s\n", blob_buffer(&x));
508 blob_reset(&x);
509 }
510 }
511
512 /*
@@ -557,11 +607,11 @@
557 int i;
558 Blob x;
559 blob_zero(&x);
560 for(i=2; i<g.argc; i++){
561 if( file_tree_name(g.argv[i], &x, 1) ){
562 printf("%s\n", blob_buffer(&x));
563 blob_reset(&x);
564 }
565 }
566 }
567
@@ -620,17 +670,14 @@
620 static const unsigned char zChars[] =
621 "abcdefghijklmnopqrstuvwxyz"
622 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
623 "0123456789";
624 unsigned int i, j;
625 struct stat buf;
626 const char *zDir = ".";
627
628 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
629 if( stat(azDirs[i], &buf) ) continue;
630 if( !S_ISDIR(buf.st_mode) ) continue;
631 if( access(azDirs[i], 07) ) continue;
632 zDir = azDirs[i];
633 break;
634 }
635
636 /* Check that the output buffer is large enough for the temporary file
@@ -646,11 +693,11 @@
646 sqlite3_randomness(15, &zBuf[j]);
647 for(i=0; i<15; i++, j++){
648 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
649 }
650 zBuf[j] = 0;
651 }while( access(zBuf,0)==0 );
652 }
653
654
655 /*
656 ** Return true if a file named zName exists and has identical content
@@ -668,5 +715,106 @@
668 blob_read_from_file(&onDisk, zName);
669 rc = blob_compare(&onDisk, pContent);
670 blob_reset(&onDisk);
671 return rc==0;
672 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
--- src/file.c
+++ src/file.c
@@ -47,17 +47,19 @@
47 static int getStat(const char *zFilename){
48 int rc = 0;
49 if( zFilename==0 ){
50 if( fileStatValid==0 ) rc = 1;
51 }else{
52 char *zMbcs = fossil_utf8_to_mbcs(zFilename);
53 if( stat(zMbcs, &fileStat)!=0 ){
54 fileStatValid = 0;
55 rc = 1;
56 }else{
57 fileStatValid = 1;
58 rc = 0;
59 }
60 fossil_mbcs_free(zMbcs);
61 }
62 return rc;
63 }
64
65
@@ -120,10 +122,20 @@
122 }else{
123 rc = getStat(0);
124 }
125 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
126 }
127
128 /*
129 ** Wrapper around the access() system call.
130 */
131 int file_access(const char *zFilename, int flags){
132 char *zMbcs = fossil_utf8_to_mbcs(zFilename);
133 int rc = access(zMbcs, flags);
134 fossil_mbcs_free(zMbcs);
135 return rc;
136 }
137
138 /*
139 ** Find an unused filename similar to zBase with zSuffix appended.
140 **
141 ** Make the name relative to the working directory if relFlag is true.
@@ -166,13 +178,13 @@
178 */
179 void file_copy(const char *zFrom, const char *zTo){
180 FILE *in, *out;
181 int got;
182 char zBuf[8192];
183 in = fossil_fopen(zFrom, "rb");
184 if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
185 out = fossil_fopen(zTo, "wb");
186 if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
187 while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
188 fwrite(zBuf, 1, got, out);
189 }
190 fclose(in);
@@ -200,10 +212,19 @@
212 }
213 }
214 #endif /* _WIN32 */
215 return rc;
216 }
217
218 /*
219 ** Delete a file.
220 */
221 void file_delete(const char *zFilename){
222 char *z = fossil_utf8_to_mbcs(zFilename);
223 unlink(z);
224 fossil_mbcs_free(z);
225 }
226
227 /*
228 ** Create the directory named in the argument, if it does not already
229 ** exist. If forceFlag is 1, delete any prior non-directory object
230 ** with the same name.
@@ -212,15 +233,19 @@
233 */
234 int file_mkdir(const char *zName, int forceFlag){
235 int rc = file_isdir(zName);
236 if( rc==2 ){
237 if( !forceFlag ) return 1;
238 file_delete(zName);
239 }
240 if( rc!=1 ){
241 #if defined(_WIN32)
242 int rc;
243 char *zMbcs = fossil_utf8_to_mbcs(zName);
244 rc = mkdir(zMbcs);
245 fossil_mbcs_free(zMbcs);
246 return rc;
247 #else
248 return mkdir(zName, 0755);
249 #endif
250 }
251 return 0;
@@ -350,16 +375,47 @@
375 void cmd_test_simplify_name(void){
376 int i;
377 char *z;
378 for(i=2; i<g.argc; i++){
379 z = mprintf("%s", g.argv[i]);
380 fossil_print("[%s] -> ", z);
381 file_simplify_name(z, -1);
382 fossil_print("[%s]\n", z);
383 fossil_free(z);
384 }
385 }
386
387 /*
388 ** Get the current working directory.
389 **
390 ** On windows, the name is converted from MBCS to UTF8 and all '\\'
391 ** characters are converted to '/'. No conversions are needed on
392 ** unix.
393 */
394 void file_getcwd(char *zBuf, int nBuf){
395 #ifdef _WIN32
396 char *zPwdUtf8;
397 int nPwd;
398 int i;
399 char zPwd[2000];
400 if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
401 fossil_fatal("pwd too big: max %d\n", (int)sizeof(zPwd)-1);
402 }
403 zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
404 nPwd = strlen(zPwdUtf8);
405 if( nPwd > nBuf-1 ){
406 fossil_fatal("pwd too big: max %d\n", nBuf-1);
407 }
408 for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
409 memcpy(zBuf, zPwdUtf8, nPwd+1);
410 fossil_mbcs_free(zPwdUtf8);
411 #else
412 if( getcwd(zBuf, nBuf-1)==0 ){
413 fossil_fatal("pwd too big: max %d\n", nBuf-1);
414 }
415 #endif
416 }
417
418 /*
419 ** Compute a canonical pathname for a file or directory.
420 ** Make the name absolute if it is relative.
421 ** Remove redundant / characters
@@ -376,14 +432,11 @@
432 ){
433 blob_set(pOut, zOrigName);
434 blob_materialize(pOut);
435 }else{
436 char zPwd[2000];
437 file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
 
 
 
438 blob_zero(pOut);
439 blob_appendf(pOut, "%//%/", zPwd, zOrigName);
440 }
441 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
442 }
@@ -401,19 +454,19 @@
454 blob_zero(&x);
455 for(i=2; i<g.argc; i++){
456 char zBuf[100];
457 const char *zName = g.argv[i];
458 file_canonical_name(zName, &x);
459 fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
460 blob_reset(&x);
461 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName));
462 fossil_print(" file_size = %s\n", zBuf);
463 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName));
464 fossil_print(" file_mtime = %s\n", zBuf);
465 fossil_print(" file_isfile = %d\n", file_isfile(zName));
466 fossil_print(" file_isexe = %d\n", file_isexe(zName));
467 fossil_print(" file_isdir = %d\n", file_isdir(zName));
468 }
469 }
470
471 /*
472 ** Return TRUE if the given filename is canonical.
@@ -452,14 +505,11 @@
505 zPath = blob_buffer(pOut);
506 if( zPath[0]=='/' ){
507 int i, j;
508 Blob tmp;
509 char zPwd[2000];
510 file_getcwd(zPwd, sizeof(zPwd)-20);
 
 
 
511 for(i=1; zPath[i] && zPwd[i]==zPath[i]; i++){}
512 if( zPath[i]==0 ){
513 blob_reset(pOut);
514 if( zPwd[i]==0 ){
515 blob_append(pOut, ".", 1);
@@ -502,11 +552,11 @@
552 int i;
553 Blob x;
554 blob_zero(&x);
555 for(i=2; i<g.argc; i++){
556 file_relative_name(g.argv[i], &x);
557 fossil_print("%s\n", blob_buffer(&x));
558 blob_reset(&x);
559 }
560 }
561
562 /*
@@ -557,11 +607,11 @@
607 int i;
608 Blob x;
609 blob_zero(&x);
610 for(i=2; i<g.argc; i++){
611 if( file_tree_name(g.argv[i], &x, 1) ){
612 fossil_print("%s\n", blob_buffer(&x));
613 blob_reset(&x);
614 }
615 }
616 }
617
@@ -620,17 +670,14 @@
670 static const unsigned char zChars[] =
671 "abcdefghijklmnopqrstuvwxyz"
672 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
673 "0123456789";
674 unsigned int i, j;
 
675 const char *zDir = ".";
676
677 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
678 if( !file_isdir(azDirs[i]) ) continue;
 
 
679 zDir = azDirs[i];
680 break;
681 }
682
683 /* Check that the output buffer is large enough for the temporary file
@@ -646,11 +693,11 @@
693 sqlite3_randomness(15, &zBuf[j]);
694 for(i=0; i<15; i++, j++){
695 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
696 }
697 zBuf[j] = 0;
698 }while( file_size(zBuf)<0 );
699 }
700
701
702 /*
703 ** Return true if a file named zName exists and has identical content
@@ -668,5 +715,106 @@
715 blob_read_from_file(&onDisk, zName);
716 rc = blob_compare(&onDisk, pContent);
717 blob_reset(&onDisk);
718 return rc==0;
719 }
720
721
722 /**************************************************************************
723 ** The following routines translate between MBCS and UTF8 on windows.
724 ** Since everything is always UTF8 on unix, these routines are no-ops
725 ** there.
726 */
727 #ifdef _WIN32
728 # include <windows.h>
729 #endif
730
731 /*
732 ** Translate MBCS to UTF8. Return a pointer to the translated text.
733 ** Call fossil_mbcs_free() to deallocate any memory used to store the
734 ** returned pointer when done.
735 */
736 char *fossil_mbcs_to_utf8(const char *zMbcs){
737 #ifdef _WIN32
738 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
739 return sqlite3_win32_mbcs_to_utf8(zMbcs);
740 #else
741 return (char*)zMbcs; /* No-op on unix */
742 #endif
743 }
744
745 /*
746 ** Translate UTF8 to MBCS for use in system calls. Return a pointer to the
747 ** translated text.. Call fossil_mbcs_free() to deallocate any memory
748 ** used to store the returned pointer when done.
749 */
750 char *fossil_utf8_to_mbcs(const char *zUtf8){
751 #ifdef _WIN32
752 extern char *sqlite3_win32_utf8_to_mbcs(const char*);
753 return sqlite3_win32_utf8_to_mbcs(zUtf8);
754 #else
755 return (char*)zUtf8; /* No-op on unix */
756 #endif
757 }
758
759 /*
760 ** Translate UTF8 to MBCS for display on the console. Return a pointer to the
761 ** translated text.. Call fossil_mbcs_free() to deallocate any memory
762 ** used to store the returned pointer when done.
763 */
764 char *fossil_utf8_to_console(const char *zUtf8){
765 #ifdef _WIN32
766 int nChar, nByte;
767 WCHAR *zUnicode; /* Unicode version of zUtf8 */
768 char *zConsole; /* Console version of zUtf8 */
769 int codepage; /* Console code page */
770
771 nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, NULL, 0);
772 zUnicode = malloc( nChar*sizeof(zUnicode[0]) );
773 if( zUnicode==0 ){
774 return 0;
775 }
776 nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
777 if( nChar==0 ){
778 free(zUnicode);
779 return 0;
780 }
781 codepage = GetConsoleCP();
782 nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, 0, 0, 0, 0);
783 zConsole = malloc( nByte );
784 if( zConsole==0 ){
785 free(zUnicode);
786 return 0;
787 }
788 nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, zConsole, nByte, 0, 0);
789 free(zUnicode);
790 if( nByte == 0 ){
791 free(zConsole);
792 zConsole = 0;
793 }
794 return zConsole;
795 #else
796 return (char*)zUtf8; /* No-op on unix */
797 #endif
798 }
799
800 /*
801 ** Translate MBCS to UTF8. Return a pointer. Call fossil_mbcs_free()
802 ** to deallocate any memory used to store the returned pointer when done.
803 */
804 void fossil_mbcs_free(char *zOld){
805 #ifdef _WIN32
806 free(zOld);
807 #else
808 /* No-op on unix */
809 #endif
810 }
811
812 /*
813 ** Like fopen() but always takes a UTF8 argument.
814 */
815 FILE *fossil_fopen(const char *zName, const char *zMode){
816 char *zMbcs = fossil_utf8_to_mbcs(zName);
817 FILE *f = fopen(zMbcs, zMode);
818 fossil_mbcs_free(zMbcs);
819 return f;
820 }
821
+34 -11
--- src/finfo.c
+++ src/finfo.c
@@ -89,11 +89,11 @@
8989
blob_reset(&uuid);
9090
}else{
9191
blob_appendf(&line, "unknown 0000000000");
9292
}
9393
db_finalize(&q);
94
- printf("%s\n", blob_str(&line));
94
+ fossil_print("%s\n", blob_str(&line));
9595
blob_reset(&fname);
9696
blob_reset(&line);
9797
}else if( find_option("print","p",0) ){
9898
Blob record;
9999
Blob fname;
@@ -152,21 +152,21 @@
152152
" ORDER BY event.mtime DESC LIMIT %d OFFSET %d",
153153
zFilename, iLimit, iOffset
154154
);
155155
blob_zero(&line);
156156
if( iBrief ){
157
- printf("History of %s\n", blob_str(&fname));
157
+ fossil_print("History of %s\n", blob_str(&fname));
158158
}
159159
while( db_step(&q)==SQLITE_ROW ){
160160
const char *zFileUuid = db_column_text(&q, 0);
161161
const char *zCiUuid = db_column_text(&q,1);
162162
const char *zDate = db_column_text(&q, 2);
163163
const char *zCom = db_column_text(&q, 3);
164164
const char *zUser = db_column_text(&q, 4);
165165
char *zOut;
166166
if( iBrief ){
167
- printf("%s ", zDate);
167
+ fossil_print("%s ", zDate);
168168
zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])",
169169
zCiUuid, zCom, zUser, zFileUuid);
170170
comment_print(zOut, 11, 79);
171171
sqlite3_free(zOut);
172172
}else{
@@ -186,27 +186,38 @@
186186
187187
/*
188188
** WEBPAGE: finfo
189189
** URL: /finfo?name=FILENAME
190190
**
191
-** Show the complete change history for a single file.
191
+** Show the change history for a single file.
192
+**
193
+** Additional query parameters:
194
+**
195
+** a=DATE Only show changes after DATE
196
+** b=DATE Only show changes before DATE
197
+** n=NUM Show the first NUM changes only
192198
*/
193199
void finfo_page(void){
194200
Stmt q;
195201
const char *zFilename;
196202
char zPrevDate[20];
203
+ const char *zA;
204
+ const char *zB;
205
+ int n;
197206
Blob title;
207
+ Blob sql;
198208
GraphContext *pGraph;
199209
200210
login_check_credentials();
201211
if( !g.okRead ){ login_needed(); return; }
202212
style_header("File History");
203213
login_anonymous_available();
204214
205215
zPrevDate[0] = 0;
206216
zFilename = PD("name","");
207
- db_prepare(&q,
217
+ blob_zero(&sql);
218
+ blob_appendf(&sql,
208219
"SELECT"
209220
" datetime(event.mtime,'localtime')," /* Date of change */
210221
" coalesce(event.ecomment, event.comment)," /* Check-in comment */
211222
" coalesce(event.euser, event.user)," /* User who made chng */
212223
" mlink.pid," /* Parent rid */
@@ -217,15 +228,26 @@
217228
" event.bgcolor," /* Background color */
218229
" (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
219230
" AND tagxref.rid=mlink.mid)" /* Tags */
220231
" FROM mlink, event"
221232
" WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
222
- " AND event.objid=mlink.mid"
223
- " ORDER BY event.mtime DESC /*sort*/",
233
+ " AND event.objid=mlink.mid",
224234
TAG_BRANCH,
225235
zFilename
226236
);
237
+ if( (zA = P("a"))!=0 ){
238
+ blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA);
239
+ }
240
+ if( (zB = P("b"))!=0 ){
241
+ blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zB);
242
+ }
243
+ blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/");
244
+ if( (n = atoi(PD("n","0")))>0 ){
245
+ blob_appendf(&sql, " LIMIT %d", n);
246
+ }
247
+ db_prepare(&q, blob_str(&sql));
248
+ blob_reset(&sql);
227249
blob_zero(&title);
228250
blob_appendf(&title, "History of ");
229251
hyperlinked_path(zFilename, &title, 0);
230252
@ <h2>%b(&title)</h2>
231253
blob_reset(&title);
@@ -246,11 +268,11 @@
246268
int gidx;
247269
char zTime[10];
248270
char zShort[20];
249271
char zShortCkin[20];
250272
if( zBr==0 ) zBr = "trunk";
251
- gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 1);
273
+ gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0);
252274
if( memcmp(zDate, zPrevDate, 10) ){
253275
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
254276
@ <tr><td>
255277
@ <div class="divider">%s(zPrevDate)</div>
256278
@ </td></tr>
@@ -291,18 +313,19 @@
291313
}
292314
@ </td></tr>
293315
}
294316
db_finalize(&q);
295317
if( pGraph ){
296
- graph_finish(pGraph, 1);
318
+ graph_finish(pGraph, 0);
297319
if( pGraph->nErr ){
298320
graph_free(pGraph);
299321
pGraph = 0;
300322
}else{
301
- @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
323
+ @ <tr><td></td><td>
324
+ @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
302325
@ </td></tr>
303326
}
304327
}
305328
@ </table>
306
- timeline_output_graph_javascript(pGraph, 1);
329
+ timeline_output_graph_javascript(pGraph, 0);
307330
style_footer();
308331
}
309332
310333
ADDED src/glob.c
--- src/finfo.c
+++ src/finfo.c
@@ -89,11 +89,11 @@
89 blob_reset(&uuid);
90 }else{
91 blob_appendf(&line, "unknown 0000000000");
92 }
93 db_finalize(&q);
94 printf("%s\n", blob_str(&line));
95 blob_reset(&fname);
96 blob_reset(&line);
97 }else if( find_option("print","p",0) ){
98 Blob record;
99 Blob fname;
@@ -152,21 +152,21 @@
152 " ORDER BY event.mtime DESC LIMIT %d OFFSET %d",
153 zFilename, iLimit, iOffset
154 );
155 blob_zero(&line);
156 if( iBrief ){
157 printf("History of %s\n", blob_str(&fname));
158 }
159 while( db_step(&q)==SQLITE_ROW ){
160 const char *zFileUuid = db_column_text(&q, 0);
161 const char *zCiUuid = db_column_text(&q,1);
162 const char *zDate = db_column_text(&q, 2);
163 const char *zCom = db_column_text(&q, 3);
164 const char *zUser = db_column_text(&q, 4);
165 char *zOut;
166 if( iBrief ){
167 printf("%s ", zDate);
168 zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])",
169 zCiUuid, zCom, zUser, zFileUuid);
170 comment_print(zOut, 11, 79);
171 sqlite3_free(zOut);
172 }else{
@@ -186,27 +186,38 @@
186
187 /*
188 ** WEBPAGE: finfo
189 ** URL: /finfo?name=FILENAME
190 **
191 ** Show the complete change history for a single file.
 
 
 
 
 
 
192 */
193 void finfo_page(void){
194 Stmt q;
195 const char *zFilename;
196 char zPrevDate[20];
 
 
 
197 Blob title;
 
198 GraphContext *pGraph;
199
200 login_check_credentials();
201 if( !g.okRead ){ login_needed(); return; }
202 style_header("File History");
203 login_anonymous_available();
204
205 zPrevDate[0] = 0;
206 zFilename = PD("name","");
207 db_prepare(&q,
 
208 "SELECT"
209 " datetime(event.mtime,'localtime')," /* Date of change */
210 " coalesce(event.ecomment, event.comment)," /* Check-in comment */
211 " coalesce(event.euser, event.user)," /* User who made chng */
212 " mlink.pid," /* Parent rid */
@@ -217,15 +228,26 @@
217 " event.bgcolor," /* Background color */
218 " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
219 " AND tagxref.rid=mlink.mid)" /* Tags */
220 " FROM mlink, event"
221 " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
222 " AND event.objid=mlink.mid"
223 " ORDER BY event.mtime DESC /*sort*/",
224 TAG_BRANCH,
225 zFilename
226 );
 
 
 
 
 
 
 
 
 
 
 
 
227 blob_zero(&title);
228 blob_appendf(&title, "History of ");
229 hyperlinked_path(zFilename, &title, 0);
230 @ <h2>%b(&title)</h2>
231 blob_reset(&title);
@@ -246,11 +268,11 @@
246 int gidx;
247 char zTime[10];
248 char zShort[20];
249 char zShortCkin[20];
250 if( zBr==0 ) zBr = "trunk";
251 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 1);
252 if( memcmp(zDate, zPrevDate, 10) ){
253 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
254 @ <tr><td>
255 @ <div class="divider">%s(zPrevDate)</div>
256 @ </td></tr>
@@ -291,18 +313,19 @@
291 }
292 @ </td></tr>
293 }
294 db_finalize(&q);
295 if( pGraph ){
296 graph_finish(pGraph, 1);
297 if( pGraph->nErr ){
298 graph_free(pGraph);
299 pGraph = 0;
300 }else{
301 @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
 
302 @ </td></tr>
303 }
304 }
305 @ </table>
306 timeline_output_graph_javascript(pGraph, 1);
307 style_footer();
308 }
309
310 DDED src/glob.c
--- src/finfo.c
+++ src/finfo.c
@@ -89,11 +89,11 @@
89 blob_reset(&uuid);
90 }else{
91 blob_appendf(&line, "unknown 0000000000");
92 }
93 db_finalize(&q);
94 fossil_print("%s\n", blob_str(&line));
95 blob_reset(&fname);
96 blob_reset(&line);
97 }else if( find_option("print","p",0) ){
98 Blob record;
99 Blob fname;
@@ -152,21 +152,21 @@
152 " ORDER BY event.mtime DESC LIMIT %d OFFSET %d",
153 zFilename, iLimit, iOffset
154 );
155 blob_zero(&line);
156 if( iBrief ){
157 fossil_print("History of %s\n", blob_str(&fname));
158 }
159 while( db_step(&q)==SQLITE_ROW ){
160 const char *zFileUuid = db_column_text(&q, 0);
161 const char *zCiUuid = db_column_text(&q,1);
162 const char *zDate = db_column_text(&q, 2);
163 const char *zCom = db_column_text(&q, 3);
164 const char *zUser = db_column_text(&q, 4);
165 char *zOut;
166 if( iBrief ){
167 fossil_print("%s ", zDate);
168 zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])",
169 zCiUuid, zCom, zUser, zFileUuid);
170 comment_print(zOut, 11, 79);
171 sqlite3_free(zOut);
172 }else{
@@ -186,27 +186,38 @@
186
187 /*
188 ** WEBPAGE: finfo
189 ** URL: /finfo?name=FILENAME
190 **
191 ** Show the change history for a single file.
192 **
193 ** Additional query parameters:
194 **
195 ** a=DATE Only show changes after DATE
196 ** b=DATE Only show changes before DATE
197 ** n=NUM Show the first NUM changes only
198 */
199 void finfo_page(void){
200 Stmt q;
201 const char *zFilename;
202 char zPrevDate[20];
203 const char *zA;
204 const char *zB;
205 int n;
206 Blob title;
207 Blob sql;
208 GraphContext *pGraph;
209
210 login_check_credentials();
211 if( !g.okRead ){ login_needed(); return; }
212 style_header("File History");
213 login_anonymous_available();
214
215 zPrevDate[0] = 0;
216 zFilename = PD("name","");
217 blob_zero(&sql);
218 blob_appendf(&sql,
219 "SELECT"
220 " datetime(event.mtime,'localtime')," /* Date of change */
221 " coalesce(event.ecomment, event.comment)," /* Check-in comment */
222 " coalesce(event.euser, event.user)," /* User who made chng */
223 " mlink.pid," /* Parent rid */
@@ -217,15 +228,26 @@
228 " event.bgcolor," /* Background color */
229 " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
230 " AND tagxref.rid=mlink.mid)" /* Tags */
231 " FROM mlink, event"
232 " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
233 " AND event.objid=mlink.mid",
 
234 TAG_BRANCH,
235 zFilename
236 );
237 if( (zA = P("a"))!=0 ){
238 blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA);
239 }
240 if( (zB = P("b"))!=0 ){
241 blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zB);
242 }
243 blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/");
244 if( (n = atoi(PD("n","0")))>0 ){
245 blob_appendf(&sql, " LIMIT %d", n);
246 }
247 db_prepare(&q, blob_str(&sql));
248 blob_reset(&sql);
249 blob_zero(&title);
250 blob_appendf(&title, "History of ");
251 hyperlinked_path(zFilename, &title, 0);
252 @ <h2>%b(&title)</h2>
253 blob_reset(&title);
@@ -246,11 +268,11 @@
268 int gidx;
269 char zTime[10];
270 char zShort[20];
271 char zShortCkin[20];
272 if( zBr==0 ) zBr = "trunk";
273 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0);
274 if( memcmp(zDate, zPrevDate, 10) ){
275 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
276 @ <tr><td>
277 @ <div class="divider">%s(zPrevDate)</div>
278 @ </td></tr>
@@ -291,18 +313,19 @@
313 }
314 @ </td></tr>
315 }
316 db_finalize(&q);
317 if( pGraph ){
318 graph_finish(pGraph, 0);
319 if( pGraph->nErr ){
320 graph_free(pGraph);
321 pGraph = 0;
322 }else{
323 @ <tr><td></td><td>
324 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
325 @ </td></tr>
326 }
327 }
328 @ </table>
329 timeline_output_graph_javascript(pGraph, 0);
330 style_footer();
331 }
332
333 DDED src/glob.c
+88
--- a/src/glob.c
+++ b/src/glob.c
@@ -0,0 +1,88 @@
1
+/*
2
+** Copyright (c) 2011 D. Richard Hipp
3
+**
4
+** This program is free software; you can redistribute it and/or
5
+** modify it under the terms of the Simplified BSD License (also
6
+** known as the "2-Clause License" or "FreeBSD License".)
7
+
8
+** This program is distributed in the hope that it will be useful,
9
+** but without any warranty; without even the implied warranty of
10
+** merchantability or fitness for a particular purpose.
11
+**
12
+** Author contact information:
13
+** [email protected]
14
+** http://www.hwaci.com/drh/
15
+**
16
+*******************************************************************************
17
+**
18
+** This file contains code used to pattern matching using "glob" syntax.
19
+*/
20
+#include "config.h"
21
+#include "glob.h"
22
+#include <assert.h>
23
+
24
+/*
25
+** Construct and return a string which is an SQL expression that will
26
+** be TRUE if value zVal matches any of the GLOB expressions in the list
27
+** zGlobList. For example:
28
+**
29
+** zVal: "x"
30
+** zGlobList: "*.o,*.obj"
31
+**
32
+** Result: "(x GLOB '*.o'Each the GLOB list may optionally be enclosed in either '...' or
33
+** "...
34
+** oris allows commas ou no effoin the expression. Whitespace at the
35
+** beginning and end of each GLOB pattern is ignored, except when enclosed
36
+** within '...' or "..."rrently consistunquotedpr(const char *zVal, constst){
37
+ Blob expr;
38
+ 011 D. Richard Hipp
39
+**
40
+** This program is free software; you can redistribute it and/or
41
+** modify it under the terms of the Simplified BSD License (also
42
+** known as the "2-Clause License" or "FreeBSD License".)
43
+
44
+** This program is distributed in the hope that it will /*
45
+** Copyrig.*z[j-1]==' 'hard Hipp
46
+**
47
+** This program is free software; you can redistribute it and/or
48
+** modify it under the terms of the Simplified BSD License (also
49
+** known as the "2-Clause License" or "FreeBSD License".)
50
+
51
+** This program is distributed in the hope that it will be useful,
52
+** but without any warranty; without even the implied warranty of
53
+** merchantability or fitness for a particular purpose.
54
+**
55
+** Author contact information:
56
+** [email protected]
57
+** http://www.hwaci.com/drh/
58
+**
59
+*******************************************************************************
60
+**
61
+** This file contains code used to pattern matching using "glob" syntax.
62
+*/
63
+#include "config.h"
64
+#include "glob.h"
65
+#include <assert.h>
66
+
67
+/*
68
+** Construct and return a string which is an SQL expression that will
69
+** be TRUE if value zVal matches any of the GLOB expressions in the list
70
+** zGlobList. For example:
71
+**
72
+** zVal: "x"
73
+** zGlobList: "*.o,*.obj"
74
+**
75
+** Result: "(x GLOB '*.o'Each the GLOB list may optionally be enclosed in either '...' or
76
+** "...
77
+** oris allows commas ou no effoin the expression. Whitespace at the
78
+** beginning and end of each GLOB pattern is ignored, except when enclosed
79
+** within '...' or "..."rrently consistunquotedpr(const char *zVal, constst){
80
+ Blob expr;
81
+ 011 D. Richard Hipp
82
+**
83
+** This program is free software; you can redistribute it and/or
84
+** modify it under the terms of the Simplified BSD License (also
85
+** known as the "2-Clause License" or "FreeBSD License".)
86
+
87
+** This program is distributed in the hope that it will /*
88
+** Copyrig.*
--- a/src/glob.c
+++ b/src/glob.c
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/glob.c
+++ b/src/glob.c
@@ -0,0 +1,88 @@
1 /*
2 ** Copyright (c) 2011 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to pattern matching using "glob" syntax.
19 */
20 #include "config.h"
21 #include "glob.h"
22 #include <assert.h>
23
24 /*
25 ** Construct and return a string which is an SQL expression that will
26 ** be TRUE if value zVal matches any of the GLOB expressions in the list
27 ** zGlobList. For example:
28 **
29 ** zVal: "x"
30 ** zGlobList: "*.o,*.obj"
31 **
32 ** Result: "(x GLOB '*.o'Each the GLOB list may optionally be enclosed in either '...' or
33 ** "...
34 ** oris allows commas ou no effoin the expression. Whitespace at the
35 ** beginning and end of each GLOB pattern is ignored, except when enclosed
36 ** within '...' or "..."rrently consistunquotedpr(const char *zVal, constst){
37 Blob expr;
38 011 D. Richard Hipp
39 **
40 ** This program is free software; you can redistribute it and/or
41 ** modify it under the terms of the Simplified BSD License (also
42 ** known as the "2-Clause License" or "FreeBSD License".)
43
44 ** This program is distributed in the hope that it will /*
45 ** Copyrig.*z[j-1]==' 'hard Hipp
46 **
47 ** This program is free software; you can redistribute it and/or
48 ** modify it under the terms of the Simplified BSD License (also
49 ** known as the "2-Clause License" or "FreeBSD License".)
50
51 ** This program is distributed in the hope that it will be useful,
52 ** but without any warranty; without even the implied warranty of
53 ** merchantability or fitness for a particular purpose.
54 **
55 ** Author contact information:
56 ** [email protected]
57 ** http://www.hwaci.com/drh/
58 **
59 *******************************************************************************
60 **
61 ** This file contains code used to pattern matching using "glob" syntax.
62 */
63 #include "config.h"
64 #include "glob.h"
65 #include <assert.h>
66
67 /*
68 ** Construct and return a string which is an SQL expression that will
69 ** be TRUE if value zVal matches any of the GLOB expressions in the list
70 ** zGlobList. For example:
71 **
72 ** zVal: "x"
73 ** zGlobList: "*.o,*.obj"
74 **
75 ** Result: "(x GLOB '*.o'Each the GLOB list may optionally be enclosed in either '...' or
76 ** "...
77 ** oris allows commas ou no effoin the expression. Whitespace at the
78 ** beginning and end of each GLOB pattern is ignored, except when enclosed
79 ** within '...' or "..."rrently consistunquotedpr(const char *zVal, constst){
80 Blob expr;
81 011 D. Richard Hipp
82 **
83 ** This program is free software; you can redistribute it and/or
84 ** modify it under the terms of the Simplified BSD License (also
85 ** known as the "2-Clause License" or "FreeBSD License".)
86
87 ** This program is distributed in the hope that it will /*
88 ** Copyrig.*
+35 -15
--- src/graph.c
+++ src/graph.c
@@ -306,20 +306,35 @@
306306
}
307307
}
308308
pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1;
309309
}
310310
311
+/*
312
+** Compute the maximum rail number.
313
+*/
314
+static void find_max_rail(GraphContext *p){
315
+ GraphRow *pRow;
316
+ p->mxRail = 0;
317
+ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
318
+ if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail;
319
+ if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4;
320
+ while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){
321
+ p->mxRail++;
322
+ }
323
+ }
324
+}
325
+
311326
312327
/*
313328
** Compute the complete graph
314329
*/
315330
void graph_finish(GraphContext *p, int omitDescenders){
316331
GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
317332
int i;
318333
u32 mask;
319334
u32 inUse;
320
- int hasDup = 0; /* True if one or more isDup entries */
335
+ int hasDup = 0; /* True if one or more isDup entries */
321336
const char *zTrunk;
322337
323338
if( p==0 || p->pFirst==0 || p->nErr ) return;
324339
p->nErr = 1; /* Assume an error until proven otherwise */
325340
@@ -390,10 +405,11 @@
390405
** Strive to put the "trunk" branch on far left.
391406
*/
392407
zTrunk = persistBranchName(p, "trunk");
393408
for(i=0; i<2; i++){
394409
for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
410
+ if( pRow->isDup ) continue;
395411
if( i==0 ){
396412
if( pRow->zBranch!=zTrunk ) continue;
397413
}else {
398414
if( pRow->iRail>=0 ) continue;
399415
}
@@ -422,11 +438,11 @@
422438
for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
423439
int parentRid;
424440
425441
if( pRow->iRail>=0 ){
426442
if( pRow->pChild==0 && !pRow->timeWarp ){
427
- if( pRow->isLeaf || omitDescenders ){
443
+ if( omitDescenders || count_nonbranch_children(pRow->rid)==0 ){
428444
inUse &= ~(1<<pRow->iRail);
429445
}else{
430446
pRow->aiRiser[pRow->iRail] = 0;
431447
mask = 1<<pRow->iRail;
432448
for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){
@@ -435,14 +451,11 @@
435451
}
436452
}
437453
continue;
438454
}
439455
if( pRow->isDup ){
440
- pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0);
441
- if( p->mxRail>=GR_MAX_RAIL ) return;
442
- pDesc = pRow;
443
- pParent = 0;
456
+ continue;
444457
}else{
445458
assert( pRow->nParent>0 );
446459
parentRid = pRow->aParent[0];
447460
pParent = hashFind(p, parentRid);
448461
if( pParent==0 ){
@@ -515,27 +528,34 @@
515528
516529
/*
517530
** Insert merge rails from primaries to duplicates.
518531
*/
519532
if( hasDup ){
533
+ int dupRail;
534
+ int mxRail;
535
+ find_max_rail(p);
536
+ mxRail = p->mxRail;
537
+ dupRail = mxRail+1;
538
+ if( p->mxRail>=GR_MAX_RAIL ) return;
520539
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
521540
if( !pRow->isDup ) continue;
541
+ pRow->iRail = dupRail;
522542
pDesc = hashFind(p, pRow->rid);
523543
assert( pDesc!=0 && pDesc!=pRow );
524544
createMergeRiser(p, pDesc, pRow);
545
+ if( pDesc->mergeOut/4>mxRail ) mxRail = pDesc->mergeOut/4;
546
+ }
547
+ if( dupRail<=mxRail ){
548
+ dupRail = mxRail+1;
549
+ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
550
+ if( pRow->isDup ) pRow->iRail = dupRail;
551
+ }
525552
}
526
- if( p->mxRail>=GR_MAX_RAIL ) return;
553
+ if( mxRail>=GR_MAX_RAIL ) return;
527554
}
528555
529556
/*
530557
** Find the maximum rail number.
531558
*/
532
- p->mxRail = 0;
533
- for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
534
- if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail;
535
- if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4;
536
- while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){
537
- p->mxRail++;
538
- }
539
- }
559
+ find_max_rail(p);
540560
p->nErr = 0;
541561
}
542562
--- src/graph.c
+++ src/graph.c
@@ -306,20 +306,35 @@
306 }
307 }
308 pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1;
309 }
310
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
312 /*
313 ** Compute the complete graph
314 */
315 void graph_finish(GraphContext *p, int omitDescenders){
316 GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
317 int i;
318 u32 mask;
319 u32 inUse;
320 int hasDup = 0; /* True if one or more isDup entries */
321 const char *zTrunk;
322
323 if( p==0 || p->pFirst==0 || p->nErr ) return;
324 p->nErr = 1; /* Assume an error until proven otherwise */
325
@@ -390,10 +405,11 @@
390 ** Strive to put the "trunk" branch on far left.
391 */
392 zTrunk = persistBranchName(p, "trunk");
393 for(i=0; i<2; i++){
394 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
 
395 if( i==0 ){
396 if( pRow->zBranch!=zTrunk ) continue;
397 }else {
398 if( pRow->iRail>=0 ) continue;
399 }
@@ -422,11 +438,11 @@
422 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
423 int parentRid;
424
425 if( pRow->iRail>=0 ){
426 if( pRow->pChild==0 && !pRow->timeWarp ){
427 if( pRow->isLeaf || omitDescenders ){
428 inUse &= ~(1<<pRow->iRail);
429 }else{
430 pRow->aiRiser[pRow->iRail] = 0;
431 mask = 1<<pRow->iRail;
432 for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){
@@ -435,14 +451,11 @@
435 }
436 }
437 continue;
438 }
439 if( pRow->isDup ){
440 pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0);
441 if( p->mxRail>=GR_MAX_RAIL ) return;
442 pDesc = pRow;
443 pParent = 0;
444 }else{
445 assert( pRow->nParent>0 );
446 parentRid = pRow->aParent[0];
447 pParent = hashFind(p, parentRid);
448 if( pParent==0 ){
@@ -515,27 +528,34 @@
515
516 /*
517 ** Insert merge rails from primaries to duplicates.
518 */
519 if( hasDup ){
 
 
 
 
 
 
520 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
521 if( !pRow->isDup ) continue;
 
522 pDesc = hashFind(p, pRow->rid);
523 assert( pDesc!=0 && pDesc!=pRow );
524 createMergeRiser(p, pDesc, pRow);
 
 
 
 
 
 
 
525 }
526 if( p->mxRail>=GR_MAX_RAIL ) return;
527 }
528
529 /*
530 ** Find the maximum rail number.
531 */
532 p->mxRail = 0;
533 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
534 if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail;
535 if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4;
536 while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){
537 p->mxRail++;
538 }
539 }
540 p->nErr = 0;
541 }
542
--- src/graph.c
+++ src/graph.c
@@ -306,20 +306,35 @@
306 }
307 }
308 pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1;
309 }
310
311 /*
312 ** Compute the maximum rail number.
313 */
314 static void find_max_rail(GraphContext *p){
315 GraphRow *pRow;
316 p->mxRail = 0;
317 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
318 if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail;
319 if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4;
320 while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){
321 p->mxRail++;
322 }
323 }
324 }
325
326
327 /*
328 ** Compute the complete graph
329 */
330 void graph_finish(GraphContext *p, int omitDescenders){
331 GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
332 int i;
333 u32 mask;
334 u32 inUse;
335 int hasDup = 0; /* True if one or more isDup entries */
336 const char *zTrunk;
337
338 if( p==0 || p->pFirst==0 || p->nErr ) return;
339 p->nErr = 1; /* Assume an error until proven otherwise */
340
@@ -390,10 +405,11 @@
405 ** Strive to put the "trunk" branch on far left.
406 */
407 zTrunk = persistBranchName(p, "trunk");
408 for(i=0; i<2; i++){
409 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
410 if( pRow->isDup ) continue;
411 if( i==0 ){
412 if( pRow->zBranch!=zTrunk ) continue;
413 }else {
414 if( pRow->iRail>=0 ) continue;
415 }
@@ -422,11 +438,11 @@
438 for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
439 int parentRid;
440
441 if( pRow->iRail>=0 ){
442 if( pRow->pChild==0 && !pRow->timeWarp ){
443 if( omitDescenders || count_nonbranch_children(pRow->rid)==0 ){
444 inUse &= ~(1<<pRow->iRail);
445 }else{
446 pRow->aiRiser[pRow->iRail] = 0;
447 mask = 1<<pRow->iRail;
448 for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){
@@ -435,14 +451,11 @@
451 }
452 }
453 continue;
454 }
455 if( pRow->isDup ){
456 continue;
 
 
 
457 }else{
458 assert( pRow->nParent>0 );
459 parentRid = pRow->aParent[0];
460 pParent = hashFind(p, parentRid);
461 if( pParent==0 ){
@@ -515,27 +528,34 @@
528
529 /*
530 ** Insert merge rails from primaries to duplicates.
531 */
532 if( hasDup ){
533 int dupRail;
534 int mxRail;
535 find_max_rail(p);
536 mxRail = p->mxRail;
537 dupRail = mxRail+1;
538 if( p->mxRail>=GR_MAX_RAIL ) return;
539 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
540 if( !pRow->isDup ) continue;
541 pRow->iRail = dupRail;
542 pDesc = hashFind(p, pRow->rid);
543 assert( pDesc!=0 && pDesc!=pRow );
544 createMergeRiser(p, pDesc, pRow);
545 if( pDesc->mergeOut/4>mxRail ) mxRail = pDesc->mergeOut/4;
546 }
547 if( dupRail<=mxRail ){
548 dupRail = mxRail+1;
549 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
550 if( pRow->isDup ) pRow->iRail = dupRail;
551 }
552 }
553 if( mxRail>=GR_MAX_RAIL ) return;
554 }
555
556 /*
557 ** Find the maximum rail number.
558 */
559 find_max_rail(p);
 
 
 
 
 
 
 
560 p->nErr = 0;
561 }
562
+15 -13
--- src/http.c
+++ src/http.c
@@ -62,26 +62,21 @@
6262
/* Password failure while doing a sync from the command-line interface */
6363
url_prompt_for_password();
6464
zPw = g.urlPasswd;
6565
if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0);
6666
}
67
+
68
+ /* If the first character of the password is "#", then that character is
69
+ ** not really part of the password - it is an indicator that we should
70
+ ** use Basic Authentication. So skip that character.
71
+ */
72
+ if( zPw && zPw[0]=='#' ) zPw++;
6773
6874
/* The login card wants the SHA1 hash of the password, so convert the
6975
** password to its SHA1 hash it it isn't already a SHA1 hash.
70
- **
71
- ** Except, if the password begins with "*" then use the characters
72
- ** after the "*" as a cleartext password. Put an "*" at the beginning
73
- ** of the password to trick a newer client to use the cleartext password
74
- ** protocol required by legacy servers.
7576
*/
76
- if( zPw && zPw[0] ){
77
- if( zPw[0]=='*' ){
78
- zPw++;
79
- }else{
80
- zPw = sha1_shared_secret(zPw, zLogin, 0);
81
- }
82
- }
77
+ if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
8378
8479
blob_append(&pw, zPw, -1);
8580
sha1sum_blob(&pw, &sig);
8681
blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
8782
blob_reset(&pw);
@@ -105,11 +100,18 @@
105100
}else{
106101
zSep = "/";
107102
}
108103
blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep);
109104
if( g.urlProxyAuth ){
110
- blob_appendf(pHdr, "Proxy-Authorization: %s\n", g.urlProxyAuth);
105
+ blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth);
106
+ }
107
+ if( g.urlPasswd && g.urlUser && g.urlPasswd[0]=='#' ){
108
+ char *zCredentials = mprintf("%s:%s", g.urlUser, &g.urlPasswd[1]);
109
+ char *zEncoded = encode64(zCredentials, -1);
110
+ blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
111
+ fossil_free(zEncoded);
112
+ fossil_free(zCredentials);
111113
}
112114
blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
113115
blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
114116
if( g.fHttpTrace ){
115117
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
116118
--- src/http.c
+++ src/http.c
@@ -62,26 +62,21 @@
62 /* Password failure while doing a sync from the command-line interface */
63 url_prompt_for_password();
64 zPw = g.urlPasswd;
65 if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0);
66 }
 
 
 
 
 
 
67
68 /* The login card wants the SHA1 hash of the password, so convert the
69 ** password to its SHA1 hash it it isn't already a SHA1 hash.
70 **
71 ** Except, if the password begins with "*" then use the characters
72 ** after the "*" as a cleartext password. Put an "*" at the beginning
73 ** of the password to trick a newer client to use the cleartext password
74 ** protocol required by legacy servers.
75 */
76 if( zPw && zPw[0] ){
77 if( zPw[0]=='*' ){
78 zPw++;
79 }else{
80 zPw = sha1_shared_secret(zPw, zLogin, 0);
81 }
82 }
83
84 blob_append(&pw, zPw, -1);
85 sha1sum_blob(&pw, &sig);
86 blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
87 blob_reset(&pw);
@@ -105,11 +100,18 @@
105 }else{
106 zSep = "/";
107 }
108 blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep);
109 if( g.urlProxyAuth ){
110 blob_appendf(pHdr, "Proxy-Authorization: %s\n", g.urlProxyAuth);
 
 
 
 
 
 
 
111 }
112 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
113 blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
114 if( g.fHttpTrace ){
115 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
116
--- src/http.c
+++ src/http.c
@@ -62,26 +62,21 @@
62 /* Password failure while doing a sync from the command-line interface */
63 url_prompt_for_password();
64 zPw = g.urlPasswd;
65 if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0);
66 }
67
68 /* If the first character of the password is "#", then that character is
69 ** not really part of the password - it is an indicator that we should
70 ** use Basic Authentication. So skip that character.
71 */
72 if( zPw && zPw[0]=='#' ) zPw++;
73
74 /* The login card wants the SHA1 hash of the password, so convert the
75 ** password to its SHA1 hash it it isn't already a SHA1 hash.
 
 
 
 
 
76 */
77 if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
 
 
 
 
 
 
78
79 blob_append(&pw, zPw, -1);
80 sha1sum_blob(&pw, &sig);
81 blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
82 blob_reset(&pw);
@@ -105,11 +100,18 @@
100 }else{
101 zSep = "/";
102 }
103 blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep);
104 if( g.urlProxyAuth ){
105 blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth);
106 }
107 if( g.urlPasswd && g.urlUser && g.urlPasswd[0]=='#' ){
108 char *zCredentials = mprintf("%s:%s", g.urlUser, &g.urlPasswd[1]);
109 char *zEncoded = encode64(zCredentials, -1);
110 blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
111 fossil_free(zEncoded);
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
116 if( g.fHttpTrace ){
117 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
118
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -182,15 +182,24 @@
182182
if( SSL_get_verify_result(ssl) != X509_V_OK ){
183183
char *desc, *prompt;
184184
char *warning = "";
185185
Blob ans;
186186
BIO *mem;
187
+ unsigned char md[32];
188
+ unsigned int mdLength = 31;
187189
188190
mem = BIO_new(BIO_s_mem());
189191
X509_NAME_print_ex(mem, X509_get_subject_name(cert), 2, XN_FLAG_MULTILINE);
190192
BIO_puts(mem, "\n\nIssued By:\n\n");
191193
X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_MULTILINE);
194
+ BIO_puts(mem, "\n\nSHA1 Fingerprint:\n\n ");
195
+ if(X509_digest(cert, EVP_sha1(), md, &mdLength)){
196
+ int j;
197
+ for( j = 0; j < mdLength; ++j ) {
198
+ BIO_printf(mem, " %02x", md[j]);
199
+ }
200
+ }
192201
BIO_write(mem, "", 1); // null-terminate mem buffer
193202
BIO_get_mem_data(mem, &desc);
194203
195204
if( hasSavedCertificate ){
196205
warning = "WARNING: Certificate doesn't match the "
197206
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -182,15 +182,24 @@
182 if( SSL_get_verify_result(ssl) != X509_V_OK ){
183 char *desc, *prompt;
184 char *warning = "";
185 Blob ans;
186 BIO *mem;
 
 
187
188 mem = BIO_new(BIO_s_mem());
189 X509_NAME_print_ex(mem, X509_get_subject_name(cert), 2, XN_FLAG_MULTILINE);
190 BIO_puts(mem, "\n\nIssued By:\n\n");
191 X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_MULTILINE);
 
 
 
 
 
 
 
192 BIO_write(mem, "", 1); // null-terminate mem buffer
193 BIO_get_mem_data(mem, &desc);
194
195 if( hasSavedCertificate ){
196 warning = "WARNING: Certificate doesn't match the "
197
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -182,15 +182,24 @@
182 if( SSL_get_verify_result(ssl) != X509_V_OK ){
183 char *desc, *prompt;
184 char *warning = "";
185 Blob ans;
186 BIO *mem;
187 unsigned char md[32];
188 unsigned int mdLength = 31;
189
190 mem = BIO_new(BIO_s_mem());
191 X509_NAME_print_ex(mem, X509_get_subject_name(cert), 2, XN_FLAG_MULTILINE);
192 BIO_puts(mem, "\n\nIssued By:\n\n");
193 X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 2, XN_FLAG_MULTILINE);
194 BIO_puts(mem, "\n\nSHA1 Fingerprint:\n\n ");
195 if(X509_digest(cert, EVP_sha1(), md, &mdLength)){
196 int j;
197 for( j = 0; j < mdLength; ++j ) {
198 BIO_printf(mem, " %02x", md[j]);
199 }
200 }
201 BIO_write(mem, "", 1); // null-terminate mem buffer
202 BIO_get_mem_data(mem, &desc);
203
204 if( hasSavedCertificate ){
205 warning = "WARNING: Certificate doesn't match the "
206
--- src/http_transport.c
+++ src/http_transport.c
@@ -120,11 +120,11 @@
120120
blob_appendf(&zCmd, " -P %d", g.urlPort);
121121
#else
122122
blob_appendf(&zCmd, " -p %d", g.urlPort);
123123
#endif
124124
}
125
- printf("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
125
+ fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
126126
if( g.urlUser && g.urlUser[0] ){
127127
zHost = mprintf("%s@%s", g.urlUser, g.urlName);
128128
#ifdef __MINGW32__
129129
/* Only win32 (and specifically PLINK.EXE) support the -pw option */
130130
if( g.urlPasswd && g.urlPasswd[0] ){
@@ -139,19 +139,19 @@
139139
blob_init(&pw, g.urlPasswd, -1);
140140
}
141141
blob_append(&zCmd, " -pw ", -1);
142142
shell_escape(&zCmd, blob_str(&pw));
143143
blob_reset(&pw);
144
- printf(" -pw ********"); /* Do not show the password text */
144
+ fossil_print(" -pw ********"); /* Do not show the password text */
145145
}
146146
#endif
147147
}else{
148148
zHost = mprintf("%s", g.urlName);
149149
}
150150
blob_append(&zCmd, " ", 1);
151151
shell_escape(&zCmd, zHost);
152
- printf(" %s\n", zHost); /* Show the conclusion of the SSH command */
152
+ fossil_print(" %s\n", zHost); /* Show the conclusion of the SSH command */
153153
free(zHost);
154154
popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
155155
if( sshPid==0 ){
156156
fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
157157
}
@@ -246,12 +246,12 @@
246246
}else if( g.urlIsFile ){
247247
if( transport.pFile ){
248248
fclose(transport.pFile);
249249
transport.pFile = 0;
250250
}
251
- unlink(transport.zInFile);
252
- unlink(transport.zOutFile);
251
+ file_delete(transport.zInFile);
252
+ file_delete(transport.zOutFile);
253253
free(transport.zInFile);
254254
free(transport.zOutFile);
255255
}else{
256256
socket_close();
257257
}
@@ -432,10 +432,11 @@
432432
transport.pBuf = pNew;
433433
}
434434
if( N>0 ){
435435
i = transport_fetch(&transport.pBuf[transport.nUsed], N);
436436
if( i>0 ){
437
+ transport.nRcvd += i;
437438
transport.nUsed += i;
438439
}
439440
}
440441
}
441442
442443
--- src/http_transport.c
+++ src/http_transport.c
@@ -120,11 +120,11 @@
120 blob_appendf(&zCmd, " -P %d", g.urlPort);
121 #else
122 blob_appendf(&zCmd, " -p %d", g.urlPort);
123 #endif
124 }
125 printf("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
126 if( g.urlUser && g.urlUser[0] ){
127 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
128 #ifdef __MINGW32__
129 /* Only win32 (and specifically PLINK.EXE) support the -pw option */
130 if( g.urlPasswd && g.urlPasswd[0] ){
@@ -139,19 +139,19 @@
139 blob_init(&pw, g.urlPasswd, -1);
140 }
141 blob_append(&zCmd, " -pw ", -1);
142 shell_escape(&zCmd, blob_str(&pw));
143 blob_reset(&pw);
144 printf(" -pw ********"); /* Do not show the password text */
145 }
146 #endif
147 }else{
148 zHost = mprintf("%s", g.urlName);
149 }
150 blob_append(&zCmd, " ", 1);
151 shell_escape(&zCmd, zHost);
152 printf(" %s\n", zHost); /* Show the conclusion of the SSH command */
153 free(zHost);
154 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
155 if( sshPid==0 ){
156 fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
157 }
@@ -246,12 +246,12 @@
246 }else if( g.urlIsFile ){
247 if( transport.pFile ){
248 fclose(transport.pFile);
249 transport.pFile = 0;
250 }
251 unlink(transport.zInFile);
252 unlink(transport.zOutFile);
253 free(transport.zInFile);
254 free(transport.zOutFile);
255 }else{
256 socket_close();
257 }
@@ -432,10 +432,11 @@
432 transport.pBuf = pNew;
433 }
434 if( N>0 ){
435 i = transport_fetch(&transport.pBuf[transport.nUsed], N);
436 if( i>0 ){
 
437 transport.nUsed += i;
438 }
439 }
440 }
441
442
--- src/http_transport.c
+++ src/http_transport.c
@@ -120,11 +120,11 @@
120 blob_appendf(&zCmd, " -P %d", g.urlPort);
121 #else
122 blob_appendf(&zCmd, " -p %d", g.urlPort);
123 #endif
124 }
125 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
126 if( g.urlUser && g.urlUser[0] ){
127 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
128 #ifdef __MINGW32__
129 /* Only win32 (and specifically PLINK.EXE) support the -pw option */
130 if( g.urlPasswd && g.urlPasswd[0] ){
@@ -139,19 +139,19 @@
139 blob_init(&pw, g.urlPasswd, -1);
140 }
141 blob_append(&zCmd, " -pw ", -1);
142 shell_escape(&zCmd, blob_str(&pw));
143 blob_reset(&pw);
144 fossil_print(" -pw ********"); /* Do not show the password text */
145 }
146 #endif
147 }else{
148 zHost = mprintf("%s", g.urlName);
149 }
150 blob_append(&zCmd, " ", 1);
151 shell_escape(&zCmd, zHost);
152 fossil_print(" %s\n", zHost); /* Show the conclusion of the SSH command */
153 free(zHost);
154 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
155 if( sshPid==0 ){
156 fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
157 }
@@ -246,12 +246,12 @@
246 }else if( g.urlIsFile ){
247 if( transport.pFile ){
248 fclose(transport.pFile);
249 transport.pFile = 0;
250 }
251 file_delete(transport.zInFile);
252 file_delete(transport.zOutFile);
253 free(transport.zInFile);
254 free(transport.zOutFile);
255 }else{
256 socket_close();
257 }
@@ -432,10 +432,11 @@
432 transport.pBuf = pNew;
433 }
434 if( N>0 ){
435 i = transport_fetch(&transport.pBuf[transport.nUsed], N);
436 if( i>0 ){
437 transport.nRcvd += i;
438 transport.nUsed += i;
439 }
440 }
441 }
442
443
+8 -8
--- src/import.c
+++ src/import.c
@@ -497,11 +497,11 @@
497497
gg.xFinish();
498498
}else
499499
if( memcmp(zLine, "progress ", 9)==0 ){
500500
gg.xFinish();
501501
trim_newline(&zLine[9]);
502
- printf("%s\n", &zLine[9]);
502
+ fossil_print("%s\n", &zLine[9]);
503503
fflush(stdout);
504504
}else
505505
if( memcmp(zLine, "data ", 5)==0 ){
506506
fossil_free(gg.aData); gg.aData = 0;
507507
gg.nData = atoi(&zLine[5]);
@@ -697,11 +697,11 @@
697697
}else{
698698
pIn = stdin;
699699
fossil_binary_mode(pIn);
700700
}
701701
if( !incrFlag ){
702
- if( forceFlag ) unlink(g.argv[2]);
702
+ if( forceFlag ) file_delete(g.argv[2]);
703703
db_create_repository(g.argv[2]);
704704
}
705705
db_open_repository(g.argv[2]);
706706
db_open_config(0);
707707
@@ -742,19 +742,19 @@
742742
import_reset(0);
743743
}
744744
db_finalize(&q);
745745
db_end_transaction(0);
746746
db_begin_transaction();
747
- printf("Rebuilding repository meta-data...\n");
747
+ fossil_print("Rebuilding repository meta-data...\n");
748748
rebuild_db(0, 1, !incrFlag);
749749
verify_cancel();
750750
db_end_transaction(0);
751
- printf("Vacuuming..."); fflush(stdout);
751
+ fossil_print("Vacuuming..."); fflush(stdout);
752752
db_multi_exec("VACUUM");
753
- printf(" ok\n");
753
+ fossil_print(" ok\n");
754754
if( !incrFlag ){
755
- printf("project-id: %s\n", db_get("project-code", 0));
756
- printf("server-id: %s\n", db_get("server-code", 0));
755
+ fossil_print("project-id: %s\n", db_get("project-code", 0));
756
+ fossil_print("server-id: %s\n", db_get("server-code", 0));
757757
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
758
- printf("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
758
+ fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
759759
}
760760
}
761761
--- src/import.c
+++ src/import.c
@@ -497,11 +497,11 @@
497 gg.xFinish();
498 }else
499 if( memcmp(zLine, "progress ", 9)==0 ){
500 gg.xFinish();
501 trim_newline(&zLine[9]);
502 printf("%s\n", &zLine[9]);
503 fflush(stdout);
504 }else
505 if( memcmp(zLine, "data ", 5)==0 ){
506 fossil_free(gg.aData); gg.aData = 0;
507 gg.nData = atoi(&zLine[5]);
@@ -697,11 +697,11 @@
697 }else{
698 pIn = stdin;
699 fossil_binary_mode(pIn);
700 }
701 if( !incrFlag ){
702 if( forceFlag ) unlink(g.argv[2]);
703 db_create_repository(g.argv[2]);
704 }
705 db_open_repository(g.argv[2]);
706 db_open_config(0);
707
@@ -742,19 +742,19 @@
742 import_reset(0);
743 }
744 db_finalize(&q);
745 db_end_transaction(0);
746 db_begin_transaction();
747 printf("Rebuilding repository meta-data...\n");
748 rebuild_db(0, 1, !incrFlag);
749 verify_cancel();
750 db_end_transaction(0);
751 printf("Vacuuming..."); fflush(stdout);
752 db_multi_exec("VACUUM");
753 printf(" ok\n");
754 if( !incrFlag ){
755 printf("project-id: %s\n", db_get("project-code", 0));
756 printf("server-id: %s\n", db_get("server-code", 0));
757 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
758 printf("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
759 }
760 }
761
--- src/import.c
+++ src/import.c
@@ -497,11 +497,11 @@
497 gg.xFinish();
498 }else
499 if( memcmp(zLine, "progress ", 9)==0 ){
500 gg.xFinish();
501 trim_newline(&zLine[9]);
502 fossil_print("%s\n", &zLine[9]);
503 fflush(stdout);
504 }else
505 if( memcmp(zLine, "data ", 5)==0 ){
506 fossil_free(gg.aData); gg.aData = 0;
507 gg.nData = atoi(&zLine[5]);
@@ -697,11 +697,11 @@
697 }else{
698 pIn = stdin;
699 fossil_binary_mode(pIn);
700 }
701 if( !incrFlag ){
702 if( forceFlag ) file_delete(g.argv[2]);
703 db_create_repository(g.argv[2]);
704 }
705 db_open_repository(g.argv[2]);
706 db_open_config(0);
707
@@ -742,19 +742,19 @@
742 import_reset(0);
743 }
744 db_finalize(&q);
745 db_end_transaction(0);
746 db_begin_transaction();
747 fossil_print("Rebuilding repository meta-data...\n");
748 rebuild_db(0, 1, !incrFlag);
749 verify_cancel();
750 db_end_transaction(0);
751 fossil_print("Vacuuming..."); fflush(stdout);
752 db_multi_exec("VACUUM");
753 fossil_print(" ok\n");
754 if( !incrFlag ){
755 fossil_print("project-id: %s\n", db_get("project-code", 0));
756 fossil_print("server-id: %s\n", db_get("server-code", 0));
757 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
758 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
759 }
760 }
761
+35 -26
--- src/info.c
+++ src/info.c
@@ -67,11 +67,11 @@
6767
zDate = db_text(0,
6868
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
6969
rid
7070
);
7171
/* 01234567890123 */
72
- printf("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : "");
72
+ fossil_print("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : "");
7373
free(zUuid);
7474
free(zDate);
7575
}
7676
if( zUuid && showComment ){
7777
zComment = db_text(0,
@@ -88,11 +88,11 @@
8888
const char *zUuid = db_column_text(&q, 0);
8989
zDate = db_text("",
9090
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
9191
db_column_int(&q, 1)
9292
);
93
- printf("parent: %s %s\n", zUuid, zDate);
93
+ fossil_print("parent: %s %s\n", zUuid, zDate);
9494
free(zDate);
9595
}
9696
db_finalize(&q);
9797
db_prepare(&q, "SELECT uuid, cid FROM plink JOIN blob ON cid=rid "
9898
" WHERE pid=%d", rid);
@@ -100,22 +100,22 @@
100100
const char *zUuid = db_column_text(&q, 0);
101101
zDate = db_text("",
102102
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
103103
db_column_int(&q, 1)
104104
);
105
- printf("child: %s %s\n", zUuid, zDate);
105
+ fossil_print("child: %s %s\n", zUuid, zDate);
106106
free(zDate);
107107
}
108108
db_finalize(&q);
109109
}
110110
zTags = info_tags_of_checkin(rid, 0);
111111
if( zTags && zTags[0] ){
112
- printf("tags: %s\n", zTags);
112
+ fossil_print("tags: %s\n", zTags);
113113
}
114114
free(zTags);
115115
if( zComment ){
116
- printf("comment: ");
116
+ fossil_print("comment: ");
117117
comment_print(zComment, 14, 79);
118118
free(zComment);
119119
}
120120
}
121121
@@ -141,33 +141,33 @@
141141
}
142142
if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
143143
db_open_config(0);
144144
db_record_repository_filename(g.argv[2]);
145145
db_open_repository(g.argv[2]);
146
- printf("project-name: %s\n", db_get("project-name", "<unnamed>"));
147
- printf("project-code: %s\n", db_get("project-code", "<none>"));
148
- printf("server-code: %s\n", db_get("server-code", "<none>"));
146
+ fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
147
+ fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
148
+ fossil_print("server-code: %s\n", db_get("server-code", "<none>"));
149149
return;
150150
}
151151
db_must_be_within_tree();
152152
if( g.argc==2 ){
153153
int vid;
154154
/* 012345678901234 */
155155
db_record_repository_filename(0);
156
- printf("project-name: %s\n", db_get("project-name", "<unnamed>"));
157
- printf("repository: %s\n", db_lget("repository", ""));
158
- printf("local-root: %s\n", g.zLocalRoot);
156
+ fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
157
+ fossil_print("repository: %s\n", db_lget("repository", ""));
158
+ fossil_print("local-root: %s\n", g.zLocalRoot);
159159
#if defined(_WIN32)
160160
if( g.zHome ){
161
- printf("user-home: %s\n", g.zHome);
161
+ fossil_print("user-home: %s\n", g.zHome);
162162
}
163163
#endif
164
- printf("project-code: %s\n", db_get("project-code", ""));
165
- printf("server-code: %s\n", db_get("server-code", ""));
164
+ fossil_print("project-code: %s\n", db_get("project-code", ""));
165
+ fossil_print("server-code: %s\n", db_get("server-code", ""));
166166
vid = db_lget_int("checkout", 0);
167167
if( vid==0 ){
168
- printf("checkout: nil\n");
168
+ fossil_print("checkout: nil\n");
169169
}else{
170170
show_common_info(vid, "checkout:", 1, 1);
171171
}
172172
}else{
173173
int rid;
@@ -368,11 +368,11 @@
368368
zParent = db_text(0,
369369
"SELECT uuid FROM plink, blob"
370370
" WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
371371
rid
372372
);
373
- isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid);
373
+ isLeaf = is_a_leaf(rid);
374374
db_prepare(&q,
375375
"SELECT uuid, datetime(mtime, 'localtime'), user, comment,"
376376
" datetime(omtime, 'localtime')"
377377
" FROM blob, event"
378378
" WHERE blob.rid=%d"
@@ -800,10 +800,14 @@
800800
@ part of check-in
801801
hyperlink_to_uuid(zVers);
802802
@ - %w(zCom) by
803803
hyperlink_to_user(zUser,zDate," on");
804804
hyperlink_to_date(zDate,".");
805
+ if( g.okHistory ){
806
+ @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)">
807
+ @ [annotate]</a>
808
+ }
805809
cnt++;
806810
if( pDownloadName && blob_size(pDownloadName)==0 ){
807811
blob_append(pDownloadName, zName, -1);
808812
}
809813
}
@@ -945,16 +949,20 @@
945949
*/
946950
void diff_page(void){
947951
int v1, v2;
948952
int isPatch;
949953
Blob c1, c2, diff, *pOut;
954
+ char *zV1;
955
+ char *zV2;
950956
951957
login_check_credentials();
952958
if( !g.okRead ){ login_needed(); return; }
953959
v1 = name_to_rid_www("v1");
954960
v2 = name_to_rid_www("v2");
955961
if( v1==0 || v2==0 ) fossil_redirect_home();
962
+ zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
963
+ zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
956964
isPatch = P("patch")!=0;
957965
if( isPatch ){
958966
pOut = cgi_output_blob();
959967
cgi_set_content_type("text/plain");
960968
}else{
@@ -968,15 +976,16 @@
968976
blob_reset(&c2);
969977
if( !isPatch ){
970978
style_header("Diff");
971979
style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
972980
g.zTop, P("v1"), P("v2"));
973
- @ <h2>Differences From:</h2>
981
+ @ <h2>Differences From
982
+ @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
974983
@ <blockquote><p>
975984
object_description(v1, 1, 0);
976985
@ </p></blockquote>
977
- @ <h2>To:</h2>
986
+ @ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
978987
@ <blockquote><p>
979988
object_description(v2, 1, 0);
980989
@ </p></blockquote>
981990
@ <hr />
982991
@ <blockquote><pre>
@@ -1579,29 +1588,29 @@
15791588
}
15801589
zNewComment = PD("c",zComment);
15811590
zUser = db_text(0, "SELECT coalesce(euser,user)"
15821591
" FROM event WHERE objid=%d", rid);
15831592
if( zUser==0 ) fossil_redirect_home();
1584
- zNewUser = PD("u",zUser);
1593
+ zNewUser = PDT("u",zUser);
15851594
zDate = db_text(0, "SELECT datetime(mtime)"
15861595
" FROM event WHERE objid=%d", rid);
15871596
if( zDate==0 ) fossil_redirect_home();
1588
- zNewDate = PD("dt",zDate);
1597
+ zNewDate = PDT("dt",zDate);
15891598
zColor = db_text("", "SELECT bgcolor"
15901599
" FROM event WHERE objid=%d", rid);
1591
- zNewColor = PD("clr",zColor);
1600
+ zNewColor = PDT("clr",zColor);
15921601
if( fossil_strcmp(zNewColor,"##")==0 ){
1593
- zNewColor = P("clrcust");
1602
+ zNewColor = PT("clrcust");
15941603
}
15951604
fPropagateColor = db_int(0, "SELECT tagtype FROM tagxref"
15961605
" WHERE rid=%d AND tagid=%d",
15971606
rid, TAG_BGCOLOR)==2;
15981607
fNewPropagateColor = P("clr")!=0 ? P("pclr")!=0 : fPropagateColor;
15991608
zNewTagFlag = P("newtag") ? " checked" : "";
1600
- zNewTag = PD("tagname","");
1609
+ zNewTag = PDT("tagname","");
16011610
zNewBrFlag = P("newbr") ? " checked" : "";
1602
- zNewBranch = PD("brname","");
1611
+ zNewBranch = PDT("brname","");
16031612
zCloseFlag = P("close") ? " checked" : "";
16041613
if( P("apply") ){
16051614
Blob ctrl;
16061615
char *zNow;
16071616
int nChng = 0;
@@ -1651,14 +1660,14 @@
16511660
}
16521661
db_finalize(&q);
16531662
if( zCloseFlag[0] ){
16541663
db_multi_exec("REPLACE INTO newtags VALUES('closed','+',NULL)");
16551664
}
1656
- if( zNewTagFlag[0] ){
1665
+ if( zNewTagFlag[0] && zNewTag[0] ){
16571666
db_multi_exec("REPLACE INTO newtags VALUES('sym-%q','+',NULL)", zNewTag);
16581667
}
1659
- if( zNewBrFlag[0] ){
1668
+ if( zNewBrFlag[0] && zNewBranch[0] ){
16601669
db_multi_exec(
16611670
"REPLACE INTO newtags "
16621671
" SELECT tagname, '-', NULL FROM tagxref, tag"
16631672
" WHERE tagxref.rid=%d AND tagtype==2"
16641673
" AND tagname GLOB 'sym-*'"
16651674
--- src/info.c
+++ src/info.c
@@ -67,11 +67,11 @@
67 zDate = db_text(0,
68 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
69 rid
70 );
71 /* 01234567890123 */
72 printf("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : "");
73 free(zUuid);
74 free(zDate);
75 }
76 if( zUuid && showComment ){
77 zComment = db_text(0,
@@ -88,11 +88,11 @@
88 const char *zUuid = db_column_text(&q, 0);
89 zDate = db_text("",
90 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
91 db_column_int(&q, 1)
92 );
93 printf("parent: %s %s\n", zUuid, zDate);
94 free(zDate);
95 }
96 db_finalize(&q);
97 db_prepare(&q, "SELECT uuid, cid FROM plink JOIN blob ON cid=rid "
98 " WHERE pid=%d", rid);
@@ -100,22 +100,22 @@
100 const char *zUuid = db_column_text(&q, 0);
101 zDate = db_text("",
102 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
103 db_column_int(&q, 1)
104 );
105 printf("child: %s %s\n", zUuid, zDate);
106 free(zDate);
107 }
108 db_finalize(&q);
109 }
110 zTags = info_tags_of_checkin(rid, 0);
111 if( zTags && zTags[0] ){
112 printf("tags: %s\n", zTags);
113 }
114 free(zTags);
115 if( zComment ){
116 printf("comment: ");
117 comment_print(zComment, 14, 79);
118 free(zComment);
119 }
120 }
121
@@ -141,33 +141,33 @@
141 }
142 if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
143 db_open_config(0);
144 db_record_repository_filename(g.argv[2]);
145 db_open_repository(g.argv[2]);
146 printf("project-name: %s\n", db_get("project-name", "<unnamed>"));
147 printf("project-code: %s\n", db_get("project-code", "<none>"));
148 printf("server-code: %s\n", db_get("server-code", "<none>"));
149 return;
150 }
151 db_must_be_within_tree();
152 if( g.argc==2 ){
153 int vid;
154 /* 012345678901234 */
155 db_record_repository_filename(0);
156 printf("project-name: %s\n", db_get("project-name", "<unnamed>"));
157 printf("repository: %s\n", db_lget("repository", ""));
158 printf("local-root: %s\n", g.zLocalRoot);
159 #if defined(_WIN32)
160 if( g.zHome ){
161 printf("user-home: %s\n", g.zHome);
162 }
163 #endif
164 printf("project-code: %s\n", db_get("project-code", ""));
165 printf("server-code: %s\n", db_get("server-code", ""));
166 vid = db_lget_int("checkout", 0);
167 if( vid==0 ){
168 printf("checkout: nil\n");
169 }else{
170 show_common_info(vid, "checkout:", 1, 1);
171 }
172 }else{
173 int rid;
@@ -368,11 +368,11 @@
368 zParent = db_text(0,
369 "SELECT uuid FROM plink, blob"
370 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
371 rid
372 );
373 isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid);
374 db_prepare(&q,
375 "SELECT uuid, datetime(mtime, 'localtime'), user, comment,"
376 " datetime(omtime, 'localtime')"
377 " FROM blob, event"
378 " WHERE blob.rid=%d"
@@ -800,10 +800,14 @@
800 @ part of check-in
801 hyperlink_to_uuid(zVers);
802 @ - %w(zCom) by
803 hyperlink_to_user(zUser,zDate," on");
804 hyperlink_to_date(zDate,".");
 
 
 
 
805 cnt++;
806 if( pDownloadName && blob_size(pDownloadName)==0 ){
807 blob_append(pDownloadName, zName, -1);
808 }
809 }
@@ -945,16 +949,20 @@
945 */
946 void diff_page(void){
947 int v1, v2;
948 int isPatch;
949 Blob c1, c2, diff, *pOut;
 
 
950
951 login_check_credentials();
952 if( !g.okRead ){ login_needed(); return; }
953 v1 = name_to_rid_www("v1");
954 v2 = name_to_rid_www("v2");
955 if( v1==0 || v2==0 ) fossil_redirect_home();
 
 
956 isPatch = P("patch")!=0;
957 if( isPatch ){
958 pOut = cgi_output_blob();
959 cgi_set_content_type("text/plain");
960 }else{
@@ -968,15 +976,16 @@
968 blob_reset(&c2);
969 if( !isPatch ){
970 style_header("Diff");
971 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
972 g.zTop, P("v1"), P("v2"));
973 @ <h2>Differences From:</h2>
 
974 @ <blockquote><p>
975 object_description(v1, 1, 0);
976 @ </p></blockquote>
977 @ <h2>To:</h2>
978 @ <blockquote><p>
979 object_description(v2, 1, 0);
980 @ </p></blockquote>
981 @ <hr />
982 @ <blockquote><pre>
@@ -1579,29 +1588,29 @@
1579 }
1580 zNewComment = PD("c",zComment);
1581 zUser = db_text(0, "SELECT coalesce(euser,user)"
1582 " FROM event WHERE objid=%d", rid);
1583 if( zUser==0 ) fossil_redirect_home();
1584 zNewUser = PD("u",zUser);
1585 zDate = db_text(0, "SELECT datetime(mtime)"
1586 " FROM event WHERE objid=%d", rid);
1587 if( zDate==0 ) fossil_redirect_home();
1588 zNewDate = PD("dt",zDate);
1589 zColor = db_text("", "SELECT bgcolor"
1590 " FROM event WHERE objid=%d", rid);
1591 zNewColor = PD("clr",zColor);
1592 if( fossil_strcmp(zNewColor,"##")==0 ){
1593 zNewColor = P("clrcust");
1594 }
1595 fPropagateColor = db_int(0, "SELECT tagtype FROM tagxref"
1596 " WHERE rid=%d AND tagid=%d",
1597 rid, TAG_BGCOLOR)==2;
1598 fNewPropagateColor = P("clr")!=0 ? P("pclr")!=0 : fPropagateColor;
1599 zNewTagFlag = P("newtag") ? " checked" : "";
1600 zNewTag = PD("tagname","");
1601 zNewBrFlag = P("newbr") ? " checked" : "";
1602 zNewBranch = PD("brname","");
1603 zCloseFlag = P("close") ? " checked" : "";
1604 if( P("apply") ){
1605 Blob ctrl;
1606 char *zNow;
1607 int nChng = 0;
@@ -1651,14 +1660,14 @@
1651 }
1652 db_finalize(&q);
1653 if( zCloseFlag[0] ){
1654 db_multi_exec("REPLACE INTO newtags VALUES('closed','+',NULL)");
1655 }
1656 if( zNewTagFlag[0] ){
1657 db_multi_exec("REPLACE INTO newtags VALUES('sym-%q','+',NULL)", zNewTag);
1658 }
1659 if( zNewBrFlag[0] ){
1660 db_multi_exec(
1661 "REPLACE INTO newtags "
1662 " SELECT tagname, '-', NULL FROM tagxref, tag"
1663 " WHERE tagxref.rid=%d AND tagtype==2"
1664 " AND tagname GLOB 'sym-*'"
1665
--- src/info.c
+++ src/info.c
@@ -67,11 +67,11 @@
67 zDate = db_text(0,
68 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
69 rid
70 );
71 /* 01234567890123 */
72 fossil_print("%-13s %s %s\n", zUuidName, zUuid, zDate ? zDate : "");
73 free(zUuid);
74 free(zDate);
75 }
76 if( zUuid && showComment ){
77 zComment = db_text(0,
@@ -88,11 +88,11 @@
88 const char *zUuid = db_column_text(&q, 0);
89 zDate = db_text("",
90 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
91 db_column_int(&q, 1)
92 );
93 fossil_print("parent: %s %s\n", zUuid, zDate);
94 free(zDate);
95 }
96 db_finalize(&q);
97 db_prepare(&q, "SELECT uuid, cid FROM plink JOIN blob ON cid=rid "
98 " WHERE pid=%d", rid);
@@ -100,22 +100,22 @@
100 const char *zUuid = db_column_text(&q, 0);
101 zDate = db_text("",
102 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
103 db_column_int(&q, 1)
104 );
105 fossil_print("child: %s %s\n", zUuid, zDate);
106 free(zDate);
107 }
108 db_finalize(&q);
109 }
110 zTags = info_tags_of_checkin(rid, 0);
111 if( zTags && zTags[0] ){
112 fossil_print("tags: %s\n", zTags);
113 }
114 free(zTags);
115 if( zComment ){
116 fossil_print("comment: ");
117 comment_print(zComment, 14, 79);
118 free(zComment);
119 }
120 }
121
@@ -141,33 +141,33 @@
141 }
142 if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
143 db_open_config(0);
144 db_record_repository_filename(g.argv[2]);
145 db_open_repository(g.argv[2]);
146 fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
147 fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
148 fossil_print("server-code: %s\n", db_get("server-code", "<none>"));
149 return;
150 }
151 db_must_be_within_tree();
152 if( g.argc==2 ){
153 int vid;
154 /* 012345678901234 */
155 db_record_repository_filename(0);
156 fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
157 fossil_print("repository: %s\n", db_lget("repository", ""));
158 fossil_print("local-root: %s\n", g.zLocalRoot);
159 #if defined(_WIN32)
160 if( g.zHome ){
161 fossil_print("user-home: %s\n", g.zHome);
162 }
163 #endif
164 fossil_print("project-code: %s\n", db_get("project-code", ""));
165 fossil_print("server-code: %s\n", db_get("server-code", ""));
166 vid = db_lget_int("checkout", 0);
167 if( vid==0 ){
168 fossil_print("checkout: nil\n");
169 }else{
170 show_common_info(vid, "checkout:", 1, 1);
171 }
172 }else{
173 int rid;
@@ -368,11 +368,11 @@
368 zParent = db_text(0,
369 "SELECT uuid FROM plink, blob"
370 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
371 rid
372 );
373 isLeaf = is_a_leaf(rid);
374 db_prepare(&q,
375 "SELECT uuid, datetime(mtime, 'localtime'), user, comment,"
376 " datetime(omtime, 'localtime')"
377 " FROM blob, event"
378 " WHERE blob.rid=%d"
@@ -800,10 +800,14 @@
800 @ part of check-in
801 hyperlink_to_uuid(zVers);
802 @ - %w(zCom) by
803 hyperlink_to_user(zUser,zDate," on");
804 hyperlink_to_date(zDate,".");
805 if( g.okHistory ){
806 @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)">
807 @ [annotate]</a>
808 }
809 cnt++;
810 if( pDownloadName && blob_size(pDownloadName)==0 ){
811 blob_append(pDownloadName, zName, -1);
812 }
813 }
@@ -945,16 +949,20 @@
949 */
950 void diff_page(void){
951 int v1, v2;
952 int isPatch;
953 Blob c1, c2, diff, *pOut;
954 char *zV1;
955 char *zV2;
956
957 login_check_credentials();
958 if( !g.okRead ){ login_needed(); return; }
959 v1 = name_to_rid_www("v1");
960 v2 = name_to_rid_www("v2");
961 if( v1==0 || v2==0 ) fossil_redirect_home();
962 zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
963 zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
964 isPatch = P("patch")!=0;
965 if( isPatch ){
966 pOut = cgi_output_blob();
967 cgi_set_content_type("text/plain");
968 }else{
@@ -968,15 +976,16 @@
976 blob_reset(&c2);
977 if( !isPatch ){
978 style_header("Diff");
979 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
980 g.zTop, P("v1"), P("v2"));
981 @ <h2>Differences From
982 @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
983 @ <blockquote><p>
984 object_description(v1, 1, 0);
985 @ </p></blockquote>
986 @ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
987 @ <blockquote><p>
988 object_description(v2, 1, 0);
989 @ </p></blockquote>
990 @ <hr />
991 @ <blockquote><pre>
@@ -1579,29 +1588,29 @@
1588 }
1589 zNewComment = PD("c",zComment);
1590 zUser = db_text(0, "SELECT coalesce(euser,user)"
1591 " FROM event WHERE objid=%d", rid);
1592 if( zUser==0 ) fossil_redirect_home();
1593 zNewUser = PDT("u",zUser);
1594 zDate = db_text(0, "SELECT datetime(mtime)"
1595 " FROM event WHERE objid=%d", rid);
1596 if( zDate==0 ) fossil_redirect_home();
1597 zNewDate = PDT("dt",zDate);
1598 zColor = db_text("", "SELECT bgcolor"
1599 " FROM event WHERE objid=%d", rid);
1600 zNewColor = PDT("clr",zColor);
1601 if( fossil_strcmp(zNewColor,"##")==0 ){
1602 zNewColor = PT("clrcust");
1603 }
1604 fPropagateColor = db_int(0, "SELECT tagtype FROM tagxref"
1605 " WHERE rid=%d AND tagid=%d",
1606 rid, TAG_BGCOLOR)==2;
1607 fNewPropagateColor = P("clr")!=0 ? P("pclr")!=0 : fPropagateColor;
1608 zNewTagFlag = P("newtag") ? " checked" : "";
1609 zNewTag = PDT("tagname","");
1610 zNewBrFlag = P("newbr") ? " checked" : "";
1611 zNewBranch = PDT("brname","");
1612 zCloseFlag = P("close") ? " checked" : "";
1613 if( P("apply") ){
1614 Blob ctrl;
1615 char *zNow;
1616 int nChng = 0;
@@ -1651,14 +1660,14 @@
1660 }
1661 db_finalize(&q);
1662 if( zCloseFlag[0] ){
1663 db_multi_exec("REPLACE INTO newtags VALUES('closed','+',NULL)");
1664 }
1665 if( zNewTagFlag[0] && zNewTag[0] ){
1666 db_multi_exec("REPLACE INTO newtags VALUES('sym-%q','+',NULL)", zNewTag);
1667 }
1668 if( zNewBrFlag[0] && zNewBranch[0] ){
1669 db_multi_exec(
1670 "REPLACE INTO newtags "
1671 " SELECT tagname, '-', NULL FROM tagxref, tag"
1672 " WHERE tagxref.rid=%d AND tagtype==2"
1673 " AND tagname GLOB 'sym-*'"
1674
+51 -3
--- src/leaf.c
+++ src/leaf.c
@@ -23,10 +23,59 @@
2323
*/
2424
#include "config.h"
2525
#include "leaf.h"
2626
#include <assert.h>
2727
28
+
29
+/*
30
+** Return true if the check-in with RID=rid is a leaf.
31
+**
32
+** A leaf has no children in the same branch.
33
+*/
34
+int is_a_leaf(int rid){
35
+ int rc;
36
+ static const char zSql[] =
37
+ @ SELECT 1 FROM plink
38
+ @ WHERE pid=%d
39
+ @ AND coalesce((SELECT value FROM tagxref
40
+ @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
41
+ @ =coalesce((SELECT value FROM tagxref
42
+ @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
43
+ ;
44
+ rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH);
45
+ return rc==0;
46
+}
47
+
48
+/*
49
+** Count the number of primary non-branch children for the given check-in.
50
+**
51
+** A primary child is one where the parent is the primary parent, not
52
+** a merge parent. A "leaf" is a node that has zero children of any
53
+** kind. This routine counts only primary children.
54
+**
55
+** A non-branch child is one which is on the same branch as the parent.
56
+*/
57
+int count_nonbranch_children(int pid){
58
+ int nNonBranch = 0;
59
+ static Stmt q;
60
+ static const char zSql[] =
61
+ @ SELECT count(*) FROM plink
62
+ @ WHERE pid=:pid AND isprim
63
+ @ AND coalesce((SELECT value FROM tagxref
64
+ @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
65
+ @ =coalesce((SELECT value FROM tagxref
66
+ @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
67
+ ;
68
+ db_static_prepare(&q, zSql, TAG_BRANCH, TAG_BRANCH);
69
+ db_bind_int(&q, ":pid", pid);
70
+ if( db_step(&q)==SQLITE_ROW ){
71
+ nNonBranch = db_column_int(&q, 0);
72
+ }
73
+ db_reset(&q);
74
+ return nNonBranch;
75
+}
76
+
2877
2978
/*
3079
** Recompute the entire LEAF table.
3180
**
3281
** This can be expensive (5 seconds or so) for a really large repository.
@@ -40,12 +89,11 @@
4089
" EXCEPT"
4190
" SELECT pid FROM plink"
4291
" WHERE coalesce((SELECT value FROM tagxref"
4392
" WHERE tagid=%d AND rid=plink.pid),'trunk')"
4493
" == coalesce((SELECT value FROM tagxref"
45
- " WHERE tagid=%d AND rid=plink.cid),'trunk')"
46
- " AND isprim",
94
+ " WHERE tagid=%d AND rid=plink.cid),'trunk')",
4795
TAG_BRANCH, TAG_BRANCH
4896
);
4997
}
5098
5199
/*
@@ -63,11 +111,11 @@
63111
static Stmt removeLeaf;
64112
int rc;
65113
66114
db_static_prepare(&checkIfLeaf,
67115
"SELECT 1 FROM plink"
68
- " WHERE pid=:rid AND isprim"
116
+ " WHERE pid=:rid"
69117
" AND coalesce((SELECT value FROM tagxref"
70118
" WHERE tagid=%d AND rid=:rid),'trunk')"
71119
" == coalesce((SELECT value FROM tagxref"
72120
" WHERE tagid=%d AND rid=plink.cid),'trunk');",
73121
TAG_BRANCH, TAG_BRANCH
74122
--- src/leaf.c
+++ src/leaf.c
@@ -23,10 +23,59 @@
23 */
24 #include "config.h"
25 #include "leaf.h"
26 #include <assert.h>
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
29 /*
30 ** Recompute the entire LEAF table.
31 **
32 ** This can be expensive (5 seconds or so) for a really large repository.
@@ -40,12 +89,11 @@
40 " EXCEPT"
41 " SELECT pid FROM plink"
42 " WHERE coalesce((SELECT value FROM tagxref"
43 " WHERE tagid=%d AND rid=plink.pid),'trunk')"
44 " == coalesce((SELECT value FROM tagxref"
45 " WHERE tagid=%d AND rid=plink.cid),'trunk')"
46 " AND isprim",
47 TAG_BRANCH, TAG_BRANCH
48 );
49 }
50
51 /*
@@ -63,11 +111,11 @@
63 static Stmt removeLeaf;
64 int rc;
65
66 db_static_prepare(&checkIfLeaf,
67 "SELECT 1 FROM plink"
68 " WHERE pid=:rid AND isprim"
69 " AND coalesce((SELECT value FROM tagxref"
70 " WHERE tagid=%d AND rid=:rid),'trunk')"
71 " == coalesce((SELECT value FROM tagxref"
72 " WHERE tagid=%d AND rid=plink.cid),'trunk');",
73 TAG_BRANCH, TAG_BRANCH
74
--- src/leaf.c
+++ src/leaf.c
@@ -23,10 +23,59 @@
23 */
24 #include "config.h"
25 #include "leaf.h"
26 #include <assert.h>
27
28
29 /*
30 ** Return true if the check-in with RID=rid is a leaf.
31 **
32 ** A leaf has no children in the same branch.
33 */
34 int is_a_leaf(int rid){
35 int rc;
36 static const char zSql[] =
37 @ SELECT 1 FROM plink
38 @ WHERE pid=%d
39 @ AND coalesce((SELECT value FROM tagxref
40 @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
41 @ =coalesce((SELECT value FROM tagxref
42 @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
43 ;
44 rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH);
45 return rc==0;
46 }
47
48 /*
49 ** Count the number of primary non-branch children for the given check-in.
50 **
51 ** A primary child is one where the parent is the primary parent, not
52 ** a merge parent. A "leaf" is a node that has zero children of any
53 ** kind. This routine counts only primary children.
54 **
55 ** A non-branch child is one which is on the same branch as the parent.
56 */
57 int count_nonbranch_children(int pid){
58 int nNonBranch = 0;
59 static Stmt q;
60 static const char zSql[] =
61 @ SELECT count(*) FROM plink
62 @ WHERE pid=:pid AND isprim
63 @ AND coalesce((SELECT value FROM tagxref
64 @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
65 @ =coalesce((SELECT value FROM tagxref
66 @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
67 ;
68 db_static_prepare(&q, zSql, TAG_BRANCH, TAG_BRANCH);
69 db_bind_int(&q, ":pid", pid);
70 if( db_step(&q)==SQLITE_ROW ){
71 nNonBranch = db_column_int(&q, 0);
72 }
73 db_reset(&q);
74 return nNonBranch;
75 }
76
77
78 /*
79 ** Recompute the entire LEAF table.
80 **
81 ** This can be expensive (5 seconds or so) for a really large repository.
@@ -40,12 +89,11 @@
89 " EXCEPT"
90 " SELECT pid FROM plink"
91 " WHERE coalesce((SELECT value FROM tagxref"
92 " WHERE tagid=%d AND rid=plink.pid),'trunk')"
93 " == coalesce((SELECT value FROM tagxref"
94 " WHERE tagid=%d AND rid=plink.cid),'trunk')",
 
95 TAG_BRANCH, TAG_BRANCH
96 );
97 }
98
99 /*
@@ -63,11 +111,11 @@
111 static Stmt removeLeaf;
112 int rc;
113
114 db_static_prepare(&checkIfLeaf,
115 "SELECT 1 FROM plink"
116 " WHERE pid=:rid"
117 " AND coalesce((SELECT value FROM tagxref"
118 " WHERE tagid=%d AND rid=:rid),'trunk')"
119 " == coalesce((SELECT value FROM tagxref"
120 " WHERE tagid=%d AND rid=plink.cid),'trunk');",
121 TAG_BRANCH, TAG_BRANCH
122
+26 -16
--- src/login.c
+++ src/login.c
@@ -546,11 +546,12 @@
546546
**
547547
*/
548548
void login_check_credentials(void){
549549
int uid = 0; /* User id */
550550
const char *zCookie; /* Text of the login cookie */
551
- char *zRemoteAddr; /* IP address of the requestor */
551
+ const char *zIpAddr; /* Raw IP address of the requestor */
552
+ char *zRemoteAddr; /* Abbreviated IP address of the requestor */
552553
const char *zCap = 0; /* Capability string */
553554
554555
/* Only run this check once. */
555556
if( g.userUid!=0 ) return;
556557
@@ -559,12 +560,12 @@
559560
** then there is no need to check user credentials.
560561
**
561562
** This feature allows the "fossil ui" command to give the user
562563
** full access rights without having to log in.
563564
*/
564
- zRemoteAddr = ipPrefix(PD("REMOTE_ADDR","nil"));
565
- if( strcmp(zRemoteAddr, "127.0.0.1")==0
565
+ zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
566
+ if( strcmp(zIpAddr, "127.0.0.1")==0
566567
&& g.useLocalauth
567568
&& db_get_int("localauth",0)==0
568569
&& P("HTTPS")==0
569570
){
570571
uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
@@ -622,10 +623,11 @@
622623
** are part of a login-group.
623624
*/
624625
uid = login_find_user(zUser, zHash, zRemoteAddr);
625626
if( uid==0 && login_transfer_credentials(zUser,zArg,zHash,zRemoteAddr) ){
626627
uid = login_find_user(zUser, zHash, zRemoteAddr);
628
+ if( uid ) record_login_attempt(zUser, zIpAddr, 1);
627629
}
628630
}
629631
sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zHash);
630632
}
631633
@@ -678,11 +680,11 @@
678680
if( fossil_strcmp(g.zLogin,"nobody")==0 ){
679681
g.zLogin = 0;
680682
}
681683
682684
/* Set the capabilities */
683
- login_set_capabilities(zCap);
685
+ login_set_capabilities(zCap, 0);
684686
login_set_anon_nobody_capabilities();
685687
}
686688
687689
/*
688690
** Memory of settings
@@ -696,26 +698,32 @@
696698
void login_set_anon_nobody_capabilities(void){
697699
if( g.zLogin && login_anon_once ){
698700
const char *zCap;
699701
/* All logged-in users inherit privileges from "nobody" */
700702
zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
701
- login_set_capabilities(zCap);
703
+ login_set_capabilities(zCap, 0);
702704
if( fossil_strcmp(g.zLogin, "nobody")!=0 ){
703705
/* All logged-in users inherit privileges from "anonymous" */
704706
zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
705
- login_set_capabilities(zCap);
707
+ login_set_capabilities(zCap, 0);
706708
}
707709
login_anon_once = 0;
708710
}
709711
}
710712
713
+/*
714
+** Flags passed into the 2nd argument of login_set_capabilities().
715
+*/
716
+#if INTERFACE
717
+#define LOGIN_IGNORE_U 0x01 /* Ignore "u" */
718
+#define LOGIN_IGNORE_V 0x01 /* Ignore "v" */
719
+#endif
720
+
711721
/*
712722
** Set the global capability flags based on a capability string.
713723
*/
714
-void login_set_capabilities(const char *zCap){
715
- static char *zDev = 0;
716
- static char *zUser = 0;
724
+void login_set_capabilities(const char *zCap, unsigned flags){
717725
int i;
718726
for(i=0; zCap[i]; i++){
719727
switch( zCap[i] ){
720728
case 's': g.okSetup = 1; /* Fall thru into Admin */
721729
case 'a': g.okAdmin = g.okRdTkt = g.okWrTkt = g.okZip =
@@ -749,23 +757,25 @@
749757
case 'x': g.okPrivate = 1; break;
750758
751759
/* The "u" privileges is a little different. It recursively
752760
** inherits all privileges of the user named "reader" */
753761
case 'u': {
754
- if( zUser==0 ){
762
+ if( (flags & LOGIN_IGNORE_U)==0 ){
763
+ const char *zUser;
755764
zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
756
- login_set_capabilities(zUser);
765
+ login_set_capabilities(zUser, flags | LOGIN_IGNORE_U);
757766
}
758767
break;
759768
}
760769
761770
/* The "v" privileges is a little different. It recursively
762771
** inherits all privileges of the user named "developer" */
763772
case 'v': {
764
- if( zDev==0 ){
773
+ if( (flags & LOGIN_IGNORE_V)==0 ){
774
+ const char *zDev;
765775
zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
766
- login_set_capabilities(zDev);
776
+ login_set_capabilities(zDev, flags | LOGIN_IGNORE_V);
767777
}
768778
break;
769779
}
770780
}
771781
}
@@ -857,11 +867,11 @@
857867
}
858868
if( fossil_strcmp(zUser,"nobody")==0 ) zUser = 0;
859869
g.zLogin = fossil_strdup(zUser);
860870
861871
/* Set the capabilities */
862
- login_set_capabilities(zCap);
872
+ login_set_capabilities(zCap, 0);
863873
login_anon_once = 1;
864874
login_set_anon_nobody_capabilities();
865875
}
866876
867877
/*
@@ -1255,12 +1265,12 @@
12551265
db_multi_exec("DETACH other");
12561266
12571267
/* Propagate the changes to all other members of the login-group */
12581268
zSql = mprintf(
12591269
"BEGIN;"
1260
- "REPLACE INTO config(name, value) VALUES('peer-name-%q', %Q);"
1261
- "REPLACE INTO config(name, value) VALUES('peer-repo-%q', %Q);"
1270
+ "REPLACE INTO config(name,value,mtime) VALUES('peer-name-%q',%Q,now());"
1271
+ "REPLACE INTO config(name,value,mtime) VALUES('peer-repo-%q',%Q,now());"
12621272
"COMMIT;",
12631273
zSelfProjCode, zSelfLabel, zSelfProjCode, zSelfRepo
12641274
);
12651275
login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
12661276
fossil_free(zSql);
12671277
--- src/login.c
+++ src/login.c
@@ -546,11 +546,12 @@
546 **
547 */
548 void login_check_credentials(void){
549 int uid = 0; /* User id */
550 const char *zCookie; /* Text of the login cookie */
551 char *zRemoteAddr; /* IP address of the requestor */
 
552 const char *zCap = 0; /* Capability string */
553
554 /* Only run this check once. */
555 if( g.userUid!=0 ) return;
556
@@ -559,12 +560,12 @@
559 ** then there is no need to check user credentials.
560 **
561 ** This feature allows the "fossil ui" command to give the user
562 ** full access rights without having to log in.
563 */
564 zRemoteAddr = ipPrefix(PD("REMOTE_ADDR","nil"));
565 if( strcmp(zRemoteAddr, "127.0.0.1")==0
566 && g.useLocalauth
567 && db_get_int("localauth",0)==0
568 && P("HTTPS")==0
569 ){
570 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
@@ -622,10 +623,11 @@
622 ** are part of a login-group.
623 */
624 uid = login_find_user(zUser, zHash, zRemoteAddr);
625 if( uid==0 && login_transfer_credentials(zUser,zArg,zHash,zRemoteAddr) ){
626 uid = login_find_user(zUser, zHash, zRemoteAddr);
 
627 }
628 }
629 sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zHash);
630 }
631
@@ -678,11 +680,11 @@
678 if( fossil_strcmp(g.zLogin,"nobody")==0 ){
679 g.zLogin = 0;
680 }
681
682 /* Set the capabilities */
683 login_set_capabilities(zCap);
684 login_set_anon_nobody_capabilities();
685 }
686
687 /*
688 ** Memory of settings
@@ -696,26 +698,32 @@
696 void login_set_anon_nobody_capabilities(void){
697 if( g.zLogin && login_anon_once ){
698 const char *zCap;
699 /* All logged-in users inherit privileges from "nobody" */
700 zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
701 login_set_capabilities(zCap);
702 if( fossil_strcmp(g.zLogin, "nobody")!=0 ){
703 /* All logged-in users inherit privileges from "anonymous" */
704 zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
705 login_set_capabilities(zCap);
706 }
707 login_anon_once = 0;
708 }
709 }
710
 
 
 
 
 
 
 
 
711 /*
712 ** Set the global capability flags based on a capability string.
713 */
714 void login_set_capabilities(const char *zCap){
715 static char *zDev = 0;
716 static char *zUser = 0;
717 int i;
718 for(i=0; zCap[i]; i++){
719 switch( zCap[i] ){
720 case 's': g.okSetup = 1; /* Fall thru into Admin */
721 case 'a': g.okAdmin = g.okRdTkt = g.okWrTkt = g.okZip =
@@ -749,23 +757,25 @@
749 case 'x': g.okPrivate = 1; break;
750
751 /* The "u" privileges is a little different. It recursively
752 ** inherits all privileges of the user named "reader" */
753 case 'u': {
754 if( zUser==0 ){
 
755 zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
756 login_set_capabilities(zUser);
757 }
758 break;
759 }
760
761 /* The "v" privileges is a little different. It recursively
762 ** inherits all privileges of the user named "developer" */
763 case 'v': {
764 if( zDev==0 ){
 
765 zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
766 login_set_capabilities(zDev);
767 }
768 break;
769 }
770 }
771 }
@@ -857,11 +867,11 @@
857 }
858 if( fossil_strcmp(zUser,"nobody")==0 ) zUser = 0;
859 g.zLogin = fossil_strdup(zUser);
860
861 /* Set the capabilities */
862 login_set_capabilities(zCap);
863 login_anon_once = 1;
864 login_set_anon_nobody_capabilities();
865 }
866
867 /*
@@ -1255,12 +1265,12 @@
1255 db_multi_exec("DETACH other");
1256
1257 /* Propagate the changes to all other members of the login-group */
1258 zSql = mprintf(
1259 "BEGIN;"
1260 "REPLACE INTO config(name, value) VALUES('peer-name-%q', %Q);"
1261 "REPLACE INTO config(name, value) VALUES('peer-repo-%q', %Q);"
1262 "COMMIT;",
1263 zSelfProjCode, zSelfLabel, zSelfProjCode, zSelfRepo
1264 );
1265 login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
1266 fossil_free(zSql);
1267
--- src/login.c
+++ src/login.c
@@ -546,11 +546,12 @@
546 **
547 */
548 void login_check_credentials(void){
549 int uid = 0; /* User id */
550 const char *zCookie; /* Text of the login cookie */
551 const char *zIpAddr; /* Raw IP address of the requestor */
552 char *zRemoteAddr; /* Abbreviated IP address of the requestor */
553 const char *zCap = 0; /* Capability string */
554
555 /* Only run this check once. */
556 if( g.userUid!=0 ) return;
557
@@ -559,12 +560,12 @@
560 ** then there is no need to check user credentials.
561 **
562 ** This feature allows the "fossil ui" command to give the user
563 ** full access rights without having to log in.
564 */
565 zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
566 if( strcmp(zIpAddr, "127.0.0.1")==0
567 && g.useLocalauth
568 && db_get_int("localauth",0)==0
569 && P("HTTPS")==0
570 ){
571 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
@@ -622,10 +623,11 @@
623 ** are part of a login-group.
624 */
625 uid = login_find_user(zUser, zHash, zRemoteAddr);
626 if( uid==0 && login_transfer_credentials(zUser,zArg,zHash,zRemoteAddr) ){
627 uid = login_find_user(zUser, zHash, zRemoteAddr);
628 if( uid ) record_login_attempt(zUser, zIpAddr, 1);
629 }
630 }
631 sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zHash);
632 }
633
@@ -678,11 +680,11 @@
680 if( fossil_strcmp(g.zLogin,"nobody")==0 ){
681 g.zLogin = 0;
682 }
683
684 /* Set the capabilities */
685 login_set_capabilities(zCap, 0);
686 login_set_anon_nobody_capabilities();
687 }
688
689 /*
690 ** Memory of settings
@@ -696,26 +698,32 @@
698 void login_set_anon_nobody_capabilities(void){
699 if( g.zLogin && login_anon_once ){
700 const char *zCap;
701 /* All logged-in users inherit privileges from "nobody" */
702 zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
703 login_set_capabilities(zCap, 0);
704 if( fossil_strcmp(g.zLogin, "nobody")!=0 ){
705 /* All logged-in users inherit privileges from "anonymous" */
706 zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
707 login_set_capabilities(zCap, 0);
708 }
709 login_anon_once = 0;
710 }
711 }
712
713 /*
714 ** Flags passed into the 2nd argument of login_set_capabilities().
715 */
716 #if INTERFACE
717 #define LOGIN_IGNORE_U 0x01 /* Ignore "u" */
718 #define LOGIN_IGNORE_V 0x01 /* Ignore "v" */
719 #endif
720
721 /*
722 ** Set the global capability flags based on a capability string.
723 */
724 void login_set_capabilities(const char *zCap, unsigned flags){
 
 
725 int i;
726 for(i=0; zCap[i]; i++){
727 switch( zCap[i] ){
728 case 's': g.okSetup = 1; /* Fall thru into Admin */
729 case 'a': g.okAdmin = g.okRdTkt = g.okWrTkt = g.okZip =
@@ -749,23 +757,25 @@
757 case 'x': g.okPrivate = 1; break;
758
759 /* The "u" privileges is a little different. It recursively
760 ** inherits all privileges of the user named "reader" */
761 case 'u': {
762 if( (flags & LOGIN_IGNORE_U)==0 ){
763 const char *zUser;
764 zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
765 login_set_capabilities(zUser, flags | LOGIN_IGNORE_U);
766 }
767 break;
768 }
769
770 /* The "v" privileges is a little different. It recursively
771 ** inherits all privileges of the user named "developer" */
772 case 'v': {
773 if( (flags & LOGIN_IGNORE_V)==0 ){
774 const char *zDev;
775 zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
776 login_set_capabilities(zDev, flags | LOGIN_IGNORE_V);
777 }
778 break;
779 }
780 }
781 }
@@ -857,11 +867,11 @@
867 }
868 if( fossil_strcmp(zUser,"nobody")==0 ) zUser = 0;
869 g.zLogin = fossil_strdup(zUser);
870
871 /* Set the capabilities */
872 login_set_capabilities(zCap, 0);
873 login_anon_once = 1;
874 login_set_anon_nobody_capabilities();
875 }
876
877 /*
@@ -1255,12 +1265,12 @@
1265 db_multi_exec("DETACH other");
1266
1267 /* Propagate the changes to all other members of the login-group */
1268 zSql = mprintf(
1269 "BEGIN;"
1270 "REPLACE INTO config(name,value,mtime) VALUES('peer-name-%q',%Q,now());"
1271 "REPLACE INTO config(name,value,mtime) VALUES('peer-repo-%q',%Q,now());"
1272 "COMMIT;",
1273 zSelfProjCode, zSelfLabel, zSelfProjCode, zSelfRepo
1274 );
1275 login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
1276 fossil_free(zSql);
1277
+42 -35
--- src/main.c
+++ src/main.c
@@ -227,23 +227,24 @@
227227
*/
228228
int main(int argc, char **argv){
229229
const char *zCmdName = "unknown";
230230
int idx;
231231
int rc;
232
+ int i;
232233
233234
sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
234235
g.now = time(0);
235236
g.argc = argc;
236237
g.argv = argv;
238
+ for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]);
237239
if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
238240
zCmdName = "cgi";
239241
}else if( argc<2 ){
240
- fprintf(stderr, "Usage: %s COMMAND ...\n"
241
- "\"%s help\" for a list of available commands\n"
242
- "\"%s help COMMAND\" for specific details\n",
243
- argv[0], argv[0], argv[0]);
244
- fossil_exit(1);
242
+ fossil_fatal("Usage: %s COMMAND ...\n"
243
+ "\"%s help\" for a list of available commands\n"
244
+ "\"%s help COMMAND\" for specific details\n",
245
+ argv[0], argv[0], argv[0]);
245246
}else{
246247
g.fQuiet = find_option("quiet", 0, 0)!=0;
247248
g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
248249
g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
249250
if( g.fSqlTrace ) g.fSqlStats = 1;
@@ -264,14 +265,13 @@
264265
}
265266
zCmdName = g.argv[1];
266267
}
267268
rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
268269
if( rc==1 ){
269
- fprintf(stderr,"%s: unknown command: %s\n"
270
- "%s: use \"help\" for more information\n",
270
+ fossil_fatal("%s: unknown command: %s\n"
271
+ "%s: use \"help\" for more information\n",
271272
argv[0], zCmdName, argv[0]);
272
- fossil_exit(1);
273273
}else if( rc==2 ){
274274
int i, n;
275275
Blob couldbe;
276276
blob_zero(&couldbe);
277277
n = strlen(zCmdName);
@@ -278,15 +278,14 @@
278278
for(i=0; i<count(aCommand); i++){
279279
if( memcmp(zCmdName, aCommand[i].zName, n)==0 ){
280280
blob_appendf(&couldbe, " %s", aCommand[i].zName);
281281
}
282282
}
283
- fprintf(stderr,"%s: ambiguous command prefix: %s\n"
284
- "%s: could be any of:%s\n"
285
- "%s: use \"help\" for more information\n",
286
- argv[0], zCmdName, argv[0], blob_str(&couldbe), argv[0]);
287
- fossil_exit(1);
283
+ fossil_fatal("%s: ambiguous command prefix: %s\n"
284
+ "%s: could be any of:%s\n"
285
+ "%s: use \"help\" for more information\n",
286
+ argv[0], zCmdName, argv[0], blob_str(&couldbe), argv[0]);
288287
}
289288
aCommand[idx].xFunc();
290289
fossil_exit(0);
291290
/*NOT_REACHED*/
292291
return 0;
@@ -333,11 +332,12 @@
333332
if( g.cgiOutput && once ){
334333
once = 0;
335334
cgi_printf("<p class=\"generalError\">%h</p>", z);
336335
cgi_reply();
337336
}else{
338
- fprintf(stderr, "%s: %s\n", fossil_nameofexe(), z);
337
+ char *zOut = mprintf("%s: %s\n", fossil_nameofexe(), z);
338
+ fossil_puts(zOut, 1);
339339
}
340340
db_force_rollback();
341341
fossil_exit(1);
342342
}
343343
void fossil_fatal(const char *zFormat, ...){
@@ -350,11 +350,12 @@
350350
if( g.cgiOutput ){
351351
g.cgiOutput = 0;
352352
cgi_printf("<p class=\"generalError\">%h</p>", z);
353353
cgi_reply();
354354
}else{
355
- fprintf(stderr, "\r%s: %s\n", fossil_nameofexe(), z);
355
+ char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z);
356
+ fossil_puts(zOut, 1);
356357
}
357358
db_force_rollback();
358359
fossil_exit(1);
359360
}
360361
@@ -378,11 +379,12 @@
378379
if( g.cgiOutput ){
379380
g.cgiOutput = 0;
380381
cgi_printf("<p class=\"generalError\">%h</p>", z);
381382
cgi_reply();
382383
}else{
383
- fprintf(stderr, "\r%s: %s\n", fossil_nameofexe(), z);
384
+ char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z);
385
+ fossil_puts(zOut, 1);
384386
}
385387
db_force_rollback();
386388
fossil_exit(1);
387389
}
388390
@@ -395,19 +397,21 @@
395397
z = vmprintf(zFormat, ap);
396398
va_end(ap);
397399
if( g.cgiOutput ){
398400
cgi_printf("<p class=\"generalError\">%h</p>", z);
399401
}else{
400
- fprintf(stderr, "\r%s: %s\n", fossil_nameofexe(), z);
402
+ char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z);
403
+ fossil_puts(zOut, 1);
404
+ free(zOut);
401405
}
402406
}
403407
404408
/*
405409
** Malloc and free routines that cannot fail
406410
*/
407411
void *fossil_malloc(size_t n){
408
- void *p = malloc(n);
412
+ void *p = malloc(n==0 ? 1 : n);
409413
if( p==0 ) fossil_panic("out of memory");
410414
return p;
411415
}
412416
void fossil_free(void *p){
413417
free(p);
@@ -426,11 +430,13 @@
426430
#if defined(_WIN32)
427431
/* On windows, we have to put double-quotes around the entire command.
428432
** Who knows why - this is just the way windows works.
429433
*/
430434
char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
431
- rc = system(zNewCmd);
435
+ char *zMbcs = fossil_utf8_to_mbcs(zNewCmd);
436
+ rc = system(zMbcs);
437
+ fossil_mbcs_free(zMbcs);
432438
free(zNewCmd);
433439
#else
434440
/* On unix, evaluate the command directly.
435441
*/
436442
rc = system(zOrigCmd);
@@ -507,12 +513,11 @@
507513
508514
/*
509515
** Print a usage comment and quit
510516
*/
511517
void usage(const char *zFormat){
512
- fprintf(stderr, "Usage: %s %s %s\n", fossil_nameofexe(), g.argv[1], zFormat);
513
- fossil_exit(1);
518
+ fossil_fatal("Usage: %s %s %s\n", fossil_nameofexe(), g.argv[1], zFormat);
514519
}
515520
516521
/*
517522
** Remove n elements from g.argv beginning with the i-th element.
518523
*/
@@ -601,14 +606,14 @@
601606
if( nCol==0 ) nCol = 1;
602607
nRow = (nWord + nCol - 1)/nCol;
603608
for(i=0; i<nRow; i++){
604609
const char *zSpacer = "";
605610
for(j=i; j<nWord; j+=nRow){
606
- printf("%s%-*s", zSpacer, mxLen, azWord[j]);
611
+ fossil_print("%s%-*s", zSpacer, mxLen, azWord[j]);
607612
zSpacer = " ";
608613
}
609
- printf("\n");
614
+ fossil_print("\n");
610615
}
611616
}
612617
613618
/*
614619
** List of commands starting with zPrefix, or all commands if zPrefix is NULL.
@@ -650,11 +655,12 @@
650655
** Usage: %fossil version
651656
**
652657
** Print the source code version number for the fossil executable.
653658
*/
654659
void version_cmd(void){
655
- printf("This is fossil version " MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
660
+ fossil_print("This is fossil version "
661
+ MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
656662
}
657663
658664
659665
/*
660666
** COMMAND: help
@@ -665,12 +671,12 @@
665671
*/
666672
void help_cmd(void){
667673
int rc, idx;
668674
const char *z;
669675
if( g.argc<3 ){
670
- printf("Usage: %s help COMMAND.\nAvailable COMMANDs:\n",
671
- fossil_nameofexe());
676
+ fossil_print("Usage: %s help COMMAND.\nAvailable COMMANDs:\n",
677
+ fossil_nameofexe());
672678
cmd_cmd_list(0);
673679
version_cmd();
674680
return;
675681
}
676682
rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
@@ -689,11 +695,11 @@
689695
fossil_fatal("no help available for the %s command",
690696
aCommand[idx].zName);
691697
}
692698
while( *z ){
693699
if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
694
- printf("%s", fossil_nameofexe());
700
+ fossil_print("%s", fossil_nameofexe());
695701
z += 7;
696702
}else{
697703
putchar(*z);
698704
z++;
699705
}
@@ -806,11 +812,11 @@
806812
zHost = PD("HTTP_HOST","");
807813
zMode = PD("HTTPS","off");
808814
zCur = PD("SCRIPT_NAME","/");
809815
i = strlen(zCur);
810816
while( i>0 && zCur[i-1]=='/' ) i--;
811
- if( strcmp(zMode,"on")==0 ){
817
+ if( fossil_stricmp(zMode,"on")==0 ){
812818
g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
813819
g.zTop = &g.zBaseURL[8+strlen(zHost)];
814820
}else{
815821
g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
816822
g.zTop = &g.zBaseURL[7+strlen(zHost)];
@@ -901,19 +907,19 @@
901907
const char *zOldScript = PD("SCRIPT_NAME", "");
902908
char *zNewScript;
903909
int j, k;
904910
i64 szFile;
905911
906
- i = 1;
912
+ i = zPathInfo[0]!=0;
907913
while( 1 ){
908914
while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
909915
zRepo = zToFree = mprintf("%s%.*s.fossil",g.zRepositoryName,i,zPathInfo);
910916
911917
/* To avoid mischief, make sure the repository basename contains no
912918
** characters other than alphanumerics, "-", "/", and "_".
913919
*/
914
- for(j=strlen(g.zRepositoryName)+1, k=0; k<i-1; j++, k++){
920
+ for(j=strlen(g.zRepositoryName)+1, k=0; zRepo[j] && k<i-1; j++, k++){
915921
if( !fossil_isalnum(zRepo[j]) && zRepo[j]!='-' && zRepo[j]!='/' ){
916922
zRepo[j] = '_';
917923
}
918924
}
919925
if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
@@ -1001,10 +1007,11 @@
10011007
zAltRepo[jj] = 0;
10021008
zAltRepo += jj+1;
10031009
}else{
10041010
zUser = "nobody";
10051011
}
1012
+ if( g.zLogin==0 ) zUser = "nobody";
10061013
if( zAltRepo[0]!='/' ){
10071014
zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
10081015
file_simplify_name(zAltRepo, -1);
10091016
}
10101017
db_close(1);
@@ -1280,12 +1287,12 @@
12801287
if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
12811288
fossil_fatal("no repository specified");
12821289
}
12831290
g.fullHttpReply = 1;
12841291
if( g.argc==6 ){
1285
- g.httpIn = fopen(g.argv[3], "rb");
1286
- g.httpOut = fopen(g.argv[4], "wb");
1292
+ g.httpIn = fossil_fopen(g.argv[3], "rb");
1293
+ g.httpOut = fossil_fopen(g.argv[4], "wb");
12871294
zIpAddr = g.argv[5];
12881295
}else{
12891296
g.httpIn = stdin;
12901297
g.httpOut = stdout;
12911298
zIpAddr = 0;
@@ -1301,11 +1308,11 @@
13011308
**
13021309
** COMMAND: test-http
13031310
** Works like the http command but gives setup permission to all users.
13041311
*/
13051312
void cmd_test_http(void){
1306
- login_set_capabilities("s");
1313
+ login_set_capabilities("s", 0);
13071314
g.httpIn = stdin;
13081315
g.httpOut = stdout;
13091316
find_server_repository(0);
13101317
g.cgiOutput = 1;
13111318
g.fullHttpReply = 1;
@@ -1326,11 +1333,11 @@
13261333
int bExists;
13271334
while( zPath && zPath[0] ){
13281335
while( zPath[0]==':' ) zPath++;
13291336
for(i=0; zPath[i] && zPath[i]!=':'; i++){}
13301337
zFull = mprintf("%.*s/%s", i, zPath, zBinary);
1331
- bExists = access(zFull, X_OK);
1338
+ bExists = file_access(zFull, X_OK);
13321339
free(zFull);
13331340
if( bExists==0 ) return 1;
13341341
zPath += i;
13351342
}
13361343
return 0;
@@ -1454,8 +1461,8 @@
14541461
** wildcard expansion behavior of the host shell can be investigated.
14551462
*/
14561463
void test_echo_cmd(void){
14571464
int i;
14581465
for(i=0; i<g.argc; i++){
1459
- printf("argv[%d] = [%s]\n", i, g.argv[i]);
1466
+ fossil_print("argv[%d] = [%s]\n", i, g.argv[i]);
14601467
}
14611468
}
14621469
--- src/main.c
+++ src/main.c
@@ -227,23 +227,24 @@
227 */
228 int main(int argc, char **argv){
229 const char *zCmdName = "unknown";
230 int idx;
231 int rc;
 
232
233 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
234 g.now = time(0);
235 g.argc = argc;
236 g.argv = argv;
 
237 if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
238 zCmdName = "cgi";
239 }else if( argc<2 ){
240 fprintf(stderr, "Usage: %s COMMAND ...\n"
241 "\"%s help\" for a list of available commands\n"
242 "\"%s help COMMAND\" for specific details\n",
243 argv[0], argv[0], argv[0]);
244 fossil_exit(1);
245 }else{
246 g.fQuiet = find_option("quiet", 0, 0)!=0;
247 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
248 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
249 if( g.fSqlTrace ) g.fSqlStats = 1;
@@ -264,14 +265,13 @@
264 }
265 zCmdName = g.argv[1];
266 }
267 rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
268 if( rc==1 ){
269 fprintf(stderr,"%s: unknown command: %s\n"
270 "%s: use \"help\" for more information\n",
271 argv[0], zCmdName, argv[0]);
272 fossil_exit(1);
273 }else if( rc==2 ){
274 int i, n;
275 Blob couldbe;
276 blob_zero(&couldbe);
277 n = strlen(zCmdName);
@@ -278,15 +278,14 @@
278 for(i=0; i<count(aCommand); i++){
279 if( memcmp(zCmdName, aCommand[i].zName, n)==0 ){
280 blob_appendf(&couldbe, " %s", aCommand[i].zName);
281 }
282 }
283 fprintf(stderr,"%s: ambiguous command prefix: %s\n"
284 "%s: could be any of:%s\n"
285 "%s: use \"help\" for more information\n",
286 argv[0], zCmdName, argv[0], blob_str(&couldbe), argv[0]);
287 fossil_exit(1);
288 }
289 aCommand[idx].xFunc();
290 fossil_exit(0);
291 /*NOT_REACHED*/
292 return 0;
@@ -333,11 +332,12 @@
333 if( g.cgiOutput && once ){
334 once = 0;
335 cgi_printf("<p class=\"generalError\">%h</p>", z);
336 cgi_reply();
337 }else{
338 fprintf(stderr, "%s: %s\n", fossil_nameofexe(), z);
 
339 }
340 db_force_rollback();
341 fossil_exit(1);
342 }
343 void fossil_fatal(const char *zFormat, ...){
@@ -350,11 +350,12 @@
350 if( g.cgiOutput ){
351 g.cgiOutput = 0;
352 cgi_printf("<p class=\"generalError\">%h</p>", z);
353 cgi_reply();
354 }else{
355 fprintf(stderr, "\r%s: %s\n", fossil_nameofexe(), z);
 
356 }
357 db_force_rollback();
358 fossil_exit(1);
359 }
360
@@ -378,11 +379,12 @@
378 if( g.cgiOutput ){
379 g.cgiOutput = 0;
380 cgi_printf("<p class=\"generalError\">%h</p>", z);
381 cgi_reply();
382 }else{
383 fprintf(stderr, "\r%s: %s\n", fossil_nameofexe(), z);
 
384 }
385 db_force_rollback();
386 fossil_exit(1);
387 }
388
@@ -395,19 +397,21 @@
395 z = vmprintf(zFormat, ap);
396 va_end(ap);
397 if( g.cgiOutput ){
398 cgi_printf("<p class=\"generalError\">%h</p>", z);
399 }else{
400 fprintf(stderr, "\r%s: %s\n", fossil_nameofexe(), z);
 
 
401 }
402 }
403
404 /*
405 ** Malloc and free routines that cannot fail
406 */
407 void *fossil_malloc(size_t n){
408 void *p = malloc(n);
409 if( p==0 ) fossil_panic("out of memory");
410 return p;
411 }
412 void fossil_free(void *p){
413 free(p);
@@ -426,11 +430,13 @@
426 #if defined(_WIN32)
427 /* On windows, we have to put double-quotes around the entire command.
428 ** Who knows why - this is just the way windows works.
429 */
430 char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
431 rc = system(zNewCmd);
 
 
432 free(zNewCmd);
433 #else
434 /* On unix, evaluate the command directly.
435 */
436 rc = system(zOrigCmd);
@@ -507,12 +513,11 @@
507
508 /*
509 ** Print a usage comment and quit
510 */
511 void usage(const char *zFormat){
512 fprintf(stderr, "Usage: %s %s %s\n", fossil_nameofexe(), g.argv[1], zFormat);
513 fossil_exit(1);
514 }
515
516 /*
517 ** Remove n elements from g.argv beginning with the i-th element.
518 */
@@ -601,14 +606,14 @@
601 if( nCol==0 ) nCol = 1;
602 nRow = (nWord + nCol - 1)/nCol;
603 for(i=0; i<nRow; i++){
604 const char *zSpacer = "";
605 for(j=i; j<nWord; j+=nRow){
606 printf("%s%-*s", zSpacer, mxLen, azWord[j]);
607 zSpacer = " ";
608 }
609 printf("\n");
610 }
611 }
612
613 /*
614 ** List of commands starting with zPrefix, or all commands if zPrefix is NULL.
@@ -650,11 +655,12 @@
650 ** Usage: %fossil version
651 **
652 ** Print the source code version number for the fossil executable.
653 */
654 void version_cmd(void){
655 printf("This is fossil version " MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
 
656 }
657
658
659 /*
660 ** COMMAND: help
@@ -665,12 +671,12 @@
665 */
666 void help_cmd(void){
667 int rc, idx;
668 const char *z;
669 if( g.argc<3 ){
670 printf("Usage: %s help COMMAND.\nAvailable COMMANDs:\n",
671 fossil_nameofexe());
672 cmd_cmd_list(0);
673 version_cmd();
674 return;
675 }
676 rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
@@ -689,11 +695,11 @@
689 fossil_fatal("no help available for the %s command",
690 aCommand[idx].zName);
691 }
692 while( *z ){
693 if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
694 printf("%s", fossil_nameofexe());
695 z += 7;
696 }else{
697 putchar(*z);
698 z++;
699 }
@@ -806,11 +812,11 @@
806 zHost = PD("HTTP_HOST","");
807 zMode = PD("HTTPS","off");
808 zCur = PD("SCRIPT_NAME","/");
809 i = strlen(zCur);
810 while( i>0 && zCur[i-1]=='/' ) i--;
811 if( strcmp(zMode,"on")==0 ){
812 g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
813 g.zTop = &g.zBaseURL[8+strlen(zHost)];
814 }else{
815 g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
816 g.zTop = &g.zBaseURL[7+strlen(zHost)];
@@ -901,19 +907,19 @@
901 const char *zOldScript = PD("SCRIPT_NAME", "");
902 char *zNewScript;
903 int j, k;
904 i64 szFile;
905
906 i = 1;
907 while( 1 ){
908 while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
909 zRepo = zToFree = mprintf("%s%.*s.fossil",g.zRepositoryName,i,zPathInfo);
910
911 /* To avoid mischief, make sure the repository basename contains no
912 ** characters other than alphanumerics, "-", "/", and "_".
913 */
914 for(j=strlen(g.zRepositoryName)+1, k=0; k<i-1; j++, k++){
915 if( !fossil_isalnum(zRepo[j]) && zRepo[j]!='-' && zRepo[j]!='/' ){
916 zRepo[j] = '_';
917 }
918 }
919 if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
@@ -1001,10 +1007,11 @@
1001 zAltRepo[jj] = 0;
1002 zAltRepo += jj+1;
1003 }else{
1004 zUser = "nobody";
1005 }
 
1006 if( zAltRepo[0]!='/' ){
1007 zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
1008 file_simplify_name(zAltRepo, -1);
1009 }
1010 db_close(1);
@@ -1280,12 +1287,12 @@
1280 if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
1281 fossil_fatal("no repository specified");
1282 }
1283 g.fullHttpReply = 1;
1284 if( g.argc==6 ){
1285 g.httpIn = fopen(g.argv[3], "rb");
1286 g.httpOut = fopen(g.argv[4], "wb");
1287 zIpAddr = g.argv[5];
1288 }else{
1289 g.httpIn = stdin;
1290 g.httpOut = stdout;
1291 zIpAddr = 0;
@@ -1301,11 +1308,11 @@
1301 **
1302 ** COMMAND: test-http
1303 ** Works like the http command but gives setup permission to all users.
1304 */
1305 void cmd_test_http(void){
1306 login_set_capabilities("s");
1307 g.httpIn = stdin;
1308 g.httpOut = stdout;
1309 find_server_repository(0);
1310 g.cgiOutput = 1;
1311 g.fullHttpReply = 1;
@@ -1326,11 +1333,11 @@
1326 int bExists;
1327 while( zPath && zPath[0] ){
1328 while( zPath[0]==':' ) zPath++;
1329 for(i=0; zPath[i] && zPath[i]!=':'; i++){}
1330 zFull = mprintf("%.*s/%s", i, zPath, zBinary);
1331 bExists = access(zFull, X_OK);
1332 free(zFull);
1333 if( bExists==0 ) return 1;
1334 zPath += i;
1335 }
1336 return 0;
@@ -1454,8 +1461,8 @@
1454 ** wildcard expansion behavior of the host shell can be investigated.
1455 */
1456 void test_echo_cmd(void){
1457 int i;
1458 for(i=0; i<g.argc; i++){
1459 printf("argv[%d] = [%s]\n", i, g.argv[i]);
1460 }
1461 }
1462
--- src/main.c
+++ src/main.c
@@ -227,23 +227,24 @@
227 */
228 int main(int argc, char **argv){
229 const char *zCmdName = "unknown";
230 int idx;
231 int rc;
232 int i;
233
234 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
235 g.now = time(0);
236 g.argc = argc;
237 g.argv = argv;
238 for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]);
239 if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
240 zCmdName = "cgi";
241 }else if( argc<2 ){
242 fossil_fatal("Usage: %s COMMAND ...\n"
243 "\"%s help\" for a list of available commands\n"
244 "\"%s help COMMAND\" for specific details\n",
245 argv[0], argv[0], argv[0]);
 
246 }else{
247 g.fQuiet = find_option("quiet", 0, 0)!=0;
248 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
249 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
250 if( g.fSqlTrace ) g.fSqlStats = 1;
@@ -264,14 +265,13 @@
265 }
266 zCmdName = g.argv[1];
267 }
268 rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
269 if( rc==1 ){
270 fossil_fatal("%s: unknown command: %s\n"
271 "%s: use \"help\" for more information\n",
272 argv[0], zCmdName, argv[0]);
 
273 }else if( rc==2 ){
274 int i, n;
275 Blob couldbe;
276 blob_zero(&couldbe);
277 n = strlen(zCmdName);
@@ -278,15 +278,14 @@
278 for(i=0; i<count(aCommand); i++){
279 if( memcmp(zCmdName, aCommand[i].zName, n)==0 ){
280 blob_appendf(&couldbe, " %s", aCommand[i].zName);
281 }
282 }
283 fossil_fatal("%s: ambiguous command prefix: %s\n"
284 "%s: could be any of:%s\n"
285 "%s: use \"help\" for more information\n",
286 argv[0], zCmdName, argv[0], blob_str(&couldbe), argv[0]);
 
287 }
288 aCommand[idx].xFunc();
289 fossil_exit(0);
290 /*NOT_REACHED*/
291 return 0;
@@ -333,11 +332,12 @@
332 if( g.cgiOutput && once ){
333 once = 0;
334 cgi_printf("<p class=\"generalError\">%h</p>", z);
335 cgi_reply();
336 }else{
337 char *zOut = mprintf("%s: %s\n", fossil_nameofexe(), z);
338 fossil_puts(zOut, 1);
339 }
340 db_force_rollback();
341 fossil_exit(1);
342 }
343 void fossil_fatal(const char *zFormat, ...){
@@ -350,11 +350,12 @@
350 if( g.cgiOutput ){
351 g.cgiOutput = 0;
352 cgi_printf("<p class=\"generalError\">%h</p>", z);
353 cgi_reply();
354 }else{
355 char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z);
356 fossil_puts(zOut, 1);
357 }
358 db_force_rollback();
359 fossil_exit(1);
360 }
361
@@ -378,11 +379,12 @@
379 if( g.cgiOutput ){
380 g.cgiOutput = 0;
381 cgi_printf("<p class=\"generalError\">%h</p>", z);
382 cgi_reply();
383 }else{
384 char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z);
385 fossil_puts(zOut, 1);
386 }
387 db_force_rollback();
388 fossil_exit(1);
389 }
390
@@ -395,19 +397,21 @@
397 z = vmprintf(zFormat, ap);
398 va_end(ap);
399 if( g.cgiOutput ){
400 cgi_printf("<p class=\"generalError\">%h</p>", z);
401 }else{
402 char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z);
403 fossil_puts(zOut, 1);
404 free(zOut);
405 }
406 }
407
408 /*
409 ** Malloc and free routines that cannot fail
410 */
411 void *fossil_malloc(size_t n){
412 void *p = malloc(n==0 ? 1 : n);
413 if( p==0 ) fossil_panic("out of memory");
414 return p;
415 }
416 void fossil_free(void *p){
417 free(p);
@@ -426,11 +430,13 @@
430 #if defined(_WIN32)
431 /* On windows, we have to put double-quotes around the entire command.
432 ** Who knows why - this is just the way windows works.
433 */
434 char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
435 char *zMbcs = fossil_utf8_to_mbcs(zNewCmd);
436 rc = system(zMbcs);
437 fossil_mbcs_free(zMbcs);
438 free(zNewCmd);
439 #else
440 /* On unix, evaluate the command directly.
441 */
442 rc = system(zOrigCmd);
@@ -507,12 +513,11 @@
513
514 /*
515 ** Print a usage comment and quit
516 */
517 void usage(const char *zFormat){
518 fossil_fatal("Usage: %s %s %s\n", fossil_nameofexe(), g.argv[1], zFormat);
 
519 }
520
521 /*
522 ** Remove n elements from g.argv beginning with the i-th element.
523 */
@@ -601,14 +606,14 @@
606 if( nCol==0 ) nCol = 1;
607 nRow = (nWord + nCol - 1)/nCol;
608 for(i=0; i<nRow; i++){
609 const char *zSpacer = "";
610 for(j=i; j<nWord; j+=nRow){
611 fossil_print("%s%-*s", zSpacer, mxLen, azWord[j]);
612 zSpacer = " ";
613 }
614 fossil_print("\n");
615 }
616 }
617
618 /*
619 ** List of commands starting with zPrefix, or all commands if zPrefix is NULL.
@@ -650,11 +655,12 @@
655 ** Usage: %fossil version
656 **
657 ** Print the source code version number for the fossil executable.
658 */
659 void version_cmd(void){
660 fossil_print("This is fossil version "
661 MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
662 }
663
664
665 /*
666 ** COMMAND: help
@@ -665,12 +671,12 @@
671 */
672 void help_cmd(void){
673 int rc, idx;
674 const char *z;
675 if( g.argc<3 ){
676 fossil_print("Usage: %s help COMMAND.\nAvailable COMMANDs:\n",
677 fossil_nameofexe());
678 cmd_cmd_list(0);
679 version_cmd();
680 return;
681 }
682 rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
@@ -689,11 +695,11 @@
695 fossil_fatal("no help available for the %s command",
696 aCommand[idx].zName);
697 }
698 while( *z ){
699 if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
700 fossil_print("%s", fossil_nameofexe());
701 z += 7;
702 }else{
703 putchar(*z);
704 z++;
705 }
@@ -806,11 +812,11 @@
812 zHost = PD("HTTP_HOST","");
813 zMode = PD("HTTPS","off");
814 zCur = PD("SCRIPT_NAME","/");
815 i = strlen(zCur);
816 while( i>0 && zCur[i-1]=='/' ) i--;
817 if( fossil_stricmp(zMode,"on")==0 ){
818 g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
819 g.zTop = &g.zBaseURL[8+strlen(zHost)];
820 }else{
821 g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
822 g.zTop = &g.zBaseURL[7+strlen(zHost)];
@@ -901,19 +907,19 @@
907 const char *zOldScript = PD("SCRIPT_NAME", "");
908 char *zNewScript;
909 int j, k;
910 i64 szFile;
911
912 i = zPathInfo[0]!=0;
913 while( 1 ){
914 while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
915 zRepo = zToFree = mprintf("%s%.*s.fossil",g.zRepositoryName,i,zPathInfo);
916
917 /* To avoid mischief, make sure the repository basename contains no
918 ** characters other than alphanumerics, "-", "/", and "_".
919 */
920 for(j=strlen(g.zRepositoryName)+1, k=0; zRepo[j] && k<i-1; j++, k++){
921 if( !fossil_isalnum(zRepo[j]) && zRepo[j]!='-' && zRepo[j]!='/' ){
922 zRepo[j] = '_';
923 }
924 }
925 if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
@@ -1001,10 +1007,11 @@
1007 zAltRepo[jj] = 0;
1008 zAltRepo += jj+1;
1009 }else{
1010 zUser = "nobody";
1011 }
1012 if( g.zLogin==0 ) zUser = "nobody";
1013 if( zAltRepo[0]!='/' ){
1014 zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
1015 file_simplify_name(zAltRepo, -1);
1016 }
1017 db_close(1);
@@ -1280,12 +1287,12 @@
1287 if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
1288 fossil_fatal("no repository specified");
1289 }
1290 g.fullHttpReply = 1;
1291 if( g.argc==6 ){
1292 g.httpIn = fossil_fopen(g.argv[3], "rb");
1293 g.httpOut = fossil_fopen(g.argv[4], "wb");
1294 zIpAddr = g.argv[5];
1295 }else{
1296 g.httpIn = stdin;
1297 g.httpOut = stdout;
1298 zIpAddr = 0;
@@ -1301,11 +1308,11 @@
1308 **
1309 ** COMMAND: test-http
1310 ** Works like the http command but gives setup permission to all users.
1311 */
1312 void cmd_test_http(void){
1313 login_set_capabilities("s", 0);
1314 g.httpIn = stdin;
1315 g.httpOut = stdout;
1316 find_server_repository(0);
1317 g.cgiOutput = 1;
1318 g.fullHttpReply = 1;
@@ -1326,11 +1333,11 @@
1333 int bExists;
1334 while( zPath && zPath[0] ){
1335 while( zPath[0]==':' ) zPath++;
1336 for(i=0; zPath[i] && zPath[i]!=':'; i++){}
1337 zFull = mprintf("%.*s/%s", i, zPath, zBinary);
1338 bExists = file_access(zFull, X_OK);
1339 free(zFull);
1340 if( bExists==0 ) return 1;
1341 zPath += i;
1342 }
1343 return 0;
@@ -1454,8 +1461,8 @@
1461 ** wildcard expansion behavior of the host shell can be investigated.
1462 */
1463 void test_echo_cmd(void){
1464 int i;
1465 for(i=0; i<g.argc; i++){
1466 fossil_print("argv[%d] = [%s]\n", i, g.argv[i]);
1467 }
1468 }
1469
+12 -2
--- src/main.mk
+++ src/main.mk
@@ -38,10 +38,11 @@
3838
$(SRCDIR)/encode.c \
3939
$(SRCDIR)/event.c \
4040
$(SRCDIR)/export.c \
4141
$(SRCDIR)/file.c \
4242
$(SRCDIR)/finfo.c \
43
+ $(SRCDIR)/glob.c \
4344
$(SRCDIR)/graph.c \
4445
$(SRCDIR)/gzip.c \
4546
$(SRCDIR)/http.c \
4647
$(SRCDIR)/http_socket.c \
4748
$(SRCDIR)/http_ssl.c \
@@ -121,10 +122,11 @@
121122
$(OBJDIR)/encode_.c \
122123
$(OBJDIR)/event_.c \
123124
$(OBJDIR)/export_.c \
124125
$(OBJDIR)/file_.c \
125126
$(OBJDIR)/finfo_.c \
127
+ $(OBJDIR)/glob_.c \
126128
$(OBJDIR)/graph_.c \
127129
$(OBJDIR)/gzip_.c \
128130
$(OBJDIR)/http_.c \
129131
$(OBJDIR)/http_socket_.c \
130132
$(OBJDIR)/http_ssl_.c \
@@ -204,10 +206,11 @@
204206
$(OBJDIR)/encode.o \
205207
$(OBJDIR)/event.o \
206208
$(OBJDIR)/export.o \
207209
$(OBJDIR)/file.o \
208210
$(OBJDIR)/finfo.o \
211
+ $(OBJDIR)/glob.o \
209212
$(OBJDIR)/graph.o \
210213
$(OBJDIR)/gzip.o \
211214
$(OBJDIR)/http.o \
212215
$(OBJDIR)/http_socket.o \
213216
$(OBJDIR)/http_ssl.o \
@@ -307,11 +310,11 @@
307310
308311
309312
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
310313
$(OBJDIR)/mkindex $(TRANS_SRC) >$@
311314
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
312
- $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
315
+ $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
313316
touch $(OBJDIR)/headers
314317
$(OBJDIR)/headers: Makefile
315318
Makefile:
316319
$(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
317320
$(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
@@ -514,10 +517,17 @@
514517
515518
$(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
516519
$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
517520
518521
$(OBJDIR)/finfo.h: $(OBJDIR)/headers
522
+$(OBJDIR)/glob_.c: $(SRCDIR)/glob.c $(OBJDIR)/translate
523
+ $(OBJDIR)/translate $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c
524
+
525
+$(OBJDIR)/glob.o: $(OBJDIR)/glob_.c $(OBJDIR)/glob.h $(SRCDIR)/config.h
526
+ $(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c
527
+
528
+$(OBJDIR)/glob.h: $(OBJDIR)/headers
519529
$(OBJDIR)/graph_.c: $(SRCDIR)/graph.c $(OBJDIR)/translate
520530
$(OBJDIR)/translate $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c
521531
522532
$(OBJDIR)/graph.o: $(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
523533
$(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c
@@ -882,13 +892,13 @@
882892
$(OBJDIR)/zip.h: $(OBJDIR)/headers
883893
$(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
884894
$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
885895
886896
$(OBJDIR)/shell.o: $(SRCDIR)/shell.c
887
- $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
897
+ $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -Dfopen=fossil_fopen -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
888898
889899
$(OBJDIR)/th.o: $(SRCDIR)/th.c
890900
$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
891901
892902
$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
893903
$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
894904
895905
--- src/main.mk
+++ src/main.mk
@@ -38,10 +38,11 @@
38 $(SRCDIR)/encode.c \
39 $(SRCDIR)/event.c \
40 $(SRCDIR)/export.c \
41 $(SRCDIR)/file.c \
42 $(SRCDIR)/finfo.c \
 
43 $(SRCDIR)/graph.c \
44 $(SRCDIR)/gzip.c \
45 $(SRCDIR)/http.c \
46 $(SRCDIR)/http_socket.c \
47 $(SRCDIR)/http_ssl.c \
@@ -121,10 +122,11 @@
121 $(OBJDIR)/encode_.c \
122 $(OBJDIR)/event_.c \
123 $(OBJDIR)/export_.c \
124 $(OBJDIR)/file_.c \
125 $(OBJDIR)/finfo_.c \
 
126 $(OBJDIR)/graph_.c \
127 $(OBJDIR)/gzip_.c \
128 $(OBJDIR)/http_.c \
129 $(OBJDIR)/http_socket_.c \
130 $(OBJDIR)/http_ssl_.c \
@@ -204,10 +206,11 @@
204 $(OBJDIR)/encode.o \
205 $(OBJDIR)/event.o \
206 $(OBJDIR)/export.o \
207 $(OBJDIR)/file.o \
208 $(OBJDIR)/finfo.o \
 
209 $(OBJDIR)/graph.o \
210 $(OBJDIR)/gzip.o \
211 $(OBJDIR)/http.o \
212 $(OBJDIR)/http_socket.o \
213 $(OBJDIR)/http_ssl.o \
@@ -307,11 +310,11 @@
307
308
309 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
310 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
311 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
312 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
313 touch $(OBJDIR)/headers
314 $(OBJDIR)/headers: Makefile
315 Makefile:
316 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
317 $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
@@ -514,10 +517,17 @@
514
515 $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
516 $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
517
518 $(OBJDIR)/finfo.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
519 $(OBJDIR)/graph_.c: $(SRCDIR)/graph.c $(OBJDIR)/translate
520 $(OBJDIR)/translate $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c
521
522 $(OBJDIR)/graph.o: $(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
523 $(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c
@@ -882,13 +892,13 @@
882 $(OBJDIR)/zip.h: $(OBJDIR)/headers
883 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
884 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
885
886 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c
887 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
888
889 $(OBJDIR)/th.o: $(SRCDIR)/th.c
890 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
891
892 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
893 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
894
895
--- src/main.mk
+++ src/main.mk
@@ -38,10 +38,11 @@
38 $(SRCDIR)/encode.c \
39 $(SRCDIR)/event.c \
40 $(SRCDIR)/export.c \
41 $(SRCDIR)/file.c \
42 $(SRCDIR)/finfo.c \
43 $(SRCDIR)/glob.c \
44 $(SRCDIR)/graph.c \
45 $(SRCDIR)/gzip.c \
46 $(SRCDIR)/http.c \
47 $(SRCDIR)/http_socket.c \
48 $(SRCDIR)/http_ssl.c \
@@ -121,10 +122,11 @@
122 $(OBJDIR)/encode_.c \
123 $(OBJDIR)/event_.c \
124 $(OBJDIR)/export_.c \
125 $(OBJDIR)/file_.c \
126 $(OBJDIR)/finfo_.c \
127 $(OBJDIR)/glob_.c \
128 $(OBJDIR)/graph_.c \
129 $(OBJDIR)/gzip_.c \
130 $(OBJDIR)/http_.c \
131 $(OBJDIR)/http_socket_.c \
132 $(OBJDIR)/http_ssl_.c \
@@ -204,10 +206,11 @@
206 $(OBJDIR)/encode.o \
207 $(OBJDIR)/event.o \
208 $(OBJDIR)/export.o \
209 $(OBJDIR)/file.o \
210 $(OBJDIR)/finfo.o \
211 $(OBJDIR)/glob.o \
212 $(OBJDIR)/graph.o \
213 $(OBJDIR)/gzip.o \
214 $(OBJDIR)/http.o \
215 $(OBJDIR)/http_socket.o \
216 $(OBJDIR)/http_ssl.o \
@@ -307,11 +310,11 @@
310
311
312 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
313 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
314 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
315 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
316 touch $(OBJDIR)/headers
317 $(OBJDIR)/headers: Makefile
318 Makefile:
319 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
320 $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
@@ -514,10 +517,17 @@
517
518 $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
519 $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
520
521 $(OBJDIR)/finfo.h: $(OBJDIR)/headers
522 $(OBJDIR)/glob_.c: $(SRCDIR)/glob.c $(OBJDIR)/translate
523 $(OBJDIR)/translate $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c
524
525 $(OBJDIR)/glob.o: $(OBJDIR)/glob_.c $(OBJDIR)/glob.h $(SRCDIR)/config.h
526 $(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c
527
528 $(OBJDIR)/glob.h: $(OBJDIR)/headers
529 $(OBJDIR)/graph_.c: $(SRCDIR)/graph.c $(OBJDIR)/translate
530 $(OBJDIR)/translate $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c
531
532 $(OBJDIR)/graph.o: $(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
533 $(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c
@@ -882,13 +892,13 @@
892 $(OBJDIR)/zip.h: $(OBJDIR)/headers
893 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
894 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
895
896 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c
897 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -Dfopen=fossil_fopen -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
898
899 $(OBJDIR)/th.o: $(SRCDIR)/th.c
900 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o
901
902 $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
903 $(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o
904
905
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -45,10 +45,11 @@
4545
encode
4646
event
4747
export
4848
file
4949
finfo
50
+ glob
5051
graph
5152
gzip
5253
http
5354
http_socket
5455
http_transport
@@ -249,10 +250,11 @@
249250
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
250251
251252
writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c"
252253
set opt {-Dmain=sqlite3_shell}
253254
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
255
+append opt " -Dfopen=fossil_fopen"
254256
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
255257
256258
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
257259
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"
258260
@@ -306,11 +308,11 @@
306308
# will run on the target platform. This is usually the same
307309
# as BCC, unless you are cross-compiling. This C compiler builds
308310
# the finished binary for fossil. The BCC compiler above is used
309311
# for building intermediate code-generator tools.
310312
#
311
-TCC = gcc -Os -Wall -DFOSSIL_I18N=0 -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include
313
+TCC = gcc -Os -Wall -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include
312314
313315
# With HTTPS support
314316
ifdef FOSSIL_ENABLE_SSL
315317
TCC += -static -DFOSSIL_ENABLE_SSL=1
316318
endif
@@ -501,15 +503,13 @@
501503
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(DMDIR)\extra\include
502504
503505
#SSL = -DFOSSIL_ENABLE_SSL=1
504506
SSL =
505507
506
-I18N = -DFOSSIL_I18N=0
507
-
508508
CFLAGS = -o
509509
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
510
-TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
510
+TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
511511
LIBS = $(DMDIR)\extra\lib\ zlib wsock32
512512
}
513513
writeln "SQLITE_OPTIONS = $SQLITE_OPTIONS\n"
514514
writeln -nonewline "SRC = "
515515
foreach s [lsort $src] {
@@ -644,15 +644,13 @@
644644
ZLIBDIR = $(MSCDIR)\extra\lib
645645
ZLIB = zlib.lib
646646
647647
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
648648
649
-I18N = -DFOSSIL_I18N=0
650
-
651649
CFLAGS = -nologo -MT -O2
652650
BCC = $(CC) $(CFLAGS)
653
-TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(I18N) $(SSL) $(INCL)
651
+TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
654652
LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
655653
LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
656654
}
657655
regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
658656
writeln "SQLITE_OPTIONS = $MSC_SQLITE_OPTIONS\n"
@@ -818,11 +816,11 @@
818816
819817
# define standard C-compiler and flags, used to compile
820818
# the fossil binary. Some special definitions follow for
821819
# special files follow
822820
CC=$(PellesCDir)\bin\pocc.exe
823
-DEFINES=-DFOSSIL_I18N=0 -D_pgmptr=g.argv[0]
821
+DEFINES=-D_pgmptr=g.argv[0]
824822
CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
825823
INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
826824
827825
# define commands for building the windows resource files
828826
RESOURCE=fossil.res
829827
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -45,10 +45,11 @@
45 encode
46 event
47 export
48 file
49 finfo
 
50 graph
51 gzip
52 http
53 http_socket
54 http_transport
@@ -249,10 +250,11 @@
249 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
250
251 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c"
252 set opt {-Dmain=sqlite3_shell}
253 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
 
254 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
255
256 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
257 writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"
258
@@ -306,11 +308,11 @@
306 # will run on the target platform. This is usually the same
307 # as BCC, unless you are cross-compiling. This C compiler builds
308 # the finished binary for fossil. The BCC compiler above is used
309 # for building intermediate code-generator tools.
310 #
311 TCC = gcc -Os -Wall -DFOSSIL_I18N=0 -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include
312
313 # With HTTPS support
314 ifdef FOSSIL_ENABLE_SSL
315 TCC += -static -DFOSSIL_ENABLE_SSL=1
316 endif
@@ -501,15 +503,13 @@
501 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(DMDIR)\extra\include
502
503 #SSL = -DFOSSIL_ENABLE_SSL=1
504 SSL =
505
506 I18N = -DFOSSIL_I18N=0
507
508 CFLAGS = -o
509 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
510 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
511 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
512 }
513 writeln "SQLITE_OPTIONS = $SQLITE_OPTIONS\n"
514 writeln -nonewline "SRC = "
515 foreach s [lsort $src] {
@@ -644,15 +644,13 @@
644 ZLIBDIR = $(MSCDIR)\extra\lib
645 ZLIB = zlib.lib
646
647 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
648
649 I18N = -DFOSSIL_I18N=0
650
651 CFLAGS = -nologo -MT -O2
652 BCC = $(CC) $(CFLAGS)
653 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(I18N) $(SSL) $(INCL)
654 LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
655 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
656 }
657 regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
658 writeln "SQLITE_OPTIONS = $MSC_SQLITE_OPTIONS\n"
@@ -818,11 +816,11 @@
818
819 # define standard C-compiler and flags, used to compile
820 # the fossil binary. Some special definitions follow for
821 # special files follow
822 CC=$(PellesCDir)\bin\pocc.exe
823 DEFINES=-DFOSSIL_I18N=0 -D_pgmptr=g.argv[0]
824 CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
825 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
826
827 # define commands for building the windows resource files
828 RESOURCE=fossil.res
829
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -45,10 +45,11 @@
45 encode
46 event
47 export
48 file
49 finfo
50 glob
51 graph
52 gzip
53 http
54 http_socket
55 http_transport
@@ -249,10 +250,11 @@
250 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
251
252 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c"
253 set opt {-Dmain=sqlite3_shell}
254 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
255 append opt " -Dfopen=fossil_fopen"
256 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
257
258 writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
259 writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"
260
@@ -306,11 +308,11 @@
308 # will run on the target platform. This is usually the same
309 # as BCC, unless you are cross-compiling. This C compiler builds
310 # the finished binary for fossil. The BCC compiler above is used
311 # for building intermediate code-generator tools.
312 #
313 TCC = gcc -Os -Wall -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include
314
315 # With HTTPS support
316 ifdef FOSSIL_ENABLE_SSL
317 TCC += -static -DFOSSIL_ENABLE_SSL=1
318 endif
@@ -501,15 +503,13 @@
503 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(DMDIR)\extra\include
504
505 #SSL = -DFOSSIL_ENABLE_SSL=1
506 SSL =
507
 
 
508 CFLAGS = -o
509 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
510 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
511 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
512 }
513 writeln "SQLITE_OPTIONS = $SQLITE_OPTIONS\n"
514 writeln -nonewline "SRC = "
515 foreach s [lsort $src] {
@@ -644,15 +644,13 @@
644 ZLIBDIR = $(MSCDIR)\extra\lib
645 ZLIB = zlib.lib
646
647 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
648
 
 
649 CFLAGS = -nologo -MT -O2
650 BCC = $(CC) $(CFLAGS)
651 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
652 LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
653 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
654 }
655 regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
656 writeln "SQLITE_OPTIONS = $MSC_SQLITE_OPTIONS\n"
@@ -818,11 +816,11 @@
816
817 # define standard C-compiler and flags, used to compile
818 # the fossil binary. Some special definitions follow for
819 # special files follow
820 CC=$(PellesCDir)\bin\pocc.exe
821 DEFINES=-D_pgmptr=g.argv[0]
822 CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
823 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
824
825 # define commands for building the windows resource files
826 RESOURCE=fossil.res
827
+18 -16
--- src/manifest.c
+++ src/manifest.c
@@ -1706,30 +1706,32 @@
17061706
sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
17071707
tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
17081708
free(zTag);
17091709
prior = db_int(0,
17101710
"SELECT rid FROM tagxref"
1711
- " WHERE tagid=%d AND mtime<%.17g"
1711
+ " WHERE tagid=%d AND mtime<%.17g AND rid!=%d"
17121712
" ORDER BY mtime DESC",
1713
- tagid, p->rDate
1713
+ tagid, p->rDate, rid
1714
+ );
1715
+ subsequent = db_int(0,
1716
+ "SELECT rid FROM tagxref"
1717
+ " WHERE tagid=%d AND mtime>=%.17g AND rid!=%d"
1718
+ " ORDER BY mtime",
1719
+ tagid, p->rDate, rid
17141720
);
17151721
if( prior ){
17161722
content_deltify(prior, rid, 0);
1717
- db_multi_exec(
1718
- "DELETE FROM event"
1719
- " WHERE type='e'"
1720
- " AND tagid=%d"
1721
- " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)",
1722
- tagid, tagid
1723
- );
1724
- }
1725
- subsequent = db_int(0,
1726
- "SELECT rid FROM tagxref"
1727
- " WHERE tagid=%d AND mtime>%.17g"
1728
- " ORDER BY mtime",
1729
- tagid, p->rDate
1730
- );
1723
+ if( !subsequent ){
1724
+ db_multi_exec(
1725
+ "DELETE FROM event"
1726
+ " WHERE type='e'"
1727
+ " AND tagid=%d"
1728
+ " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)",
1729
+ tagid, tagid
1730
+ );
1731
+ }
1732
+ }
17311733
if( subsequent ){
17321734
content_deltify(rid, subsequent, 0);
17331735
}else{
17341736
db_multi_exec(
17351737
"REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
17361738
--- src/manifest.c
+++ src/manifest.c
@@ -1706,30 +1706,32 @@
1706 sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
1707 tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
1708 free(zTag);
1709 prior = db_int(0,
1710 "SELECT rid FROM tagxref"
1711 " WHERE tagid=%d AND mtime<%.17g"
1712 " ORDER BY mtime DESC",
1713 tagid, p->rDate
 
 
 
 
 
 
1714 );
1715 if( prior ){
1716 content_deltify(prior, rid, 0);
1717 db_multi_exec(
1718 "DELETE FROM event"
1719 " WHERE type='e'"
1720 " AND tagid=%d"
1721 " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)",
1722 tagid, tagid
1723 );
1724 }
1725 subsequent = db_int(0,
1726 "SELECT rid FROM tagxref"
1727 " WHERE tagid=%d AND mtime>%.17g"
1728 " ORDER BY mtime",
1729 tagid, p->rDate
1730 );
1731 if( subsequent ){
1732 content_deltify(rid, subsequent, 0);
1733 }else{
1734 db_multi_exec(
1735 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
1736
--- src/manifest.c
+++ src/manifest.c
@@ -1706,30 +1706,32 @@
1706 sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
1707 tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
1708 free(zTag);
1709 prior = db_int(0,
1710 "SELECT rid FROM tagxref"
1711 " WHERE tagid=%d AND mtime<%.17g AND rid!=%d"
1712 " ORDER BY mtime DESC",
1713 tagid, p->rDate, rid
1714 );
1715 subsequent = db_int(0,
1716 "SELECT rid FROM tagxref"
1717 " WHERE tagid=%d AND mtime>=%.17g AND rid!=%d"
1718 " ORDER BY mtime",
1719 tagid, p->rDate, rid
1720 );
1721 if( prior ){
1722 content_deltify(prior, rid, 0);
1723 if( !subsequent ){
1724 db_multi_exec(
1725 "DELETE FROM event"
1726 " WHERE type='e'"
1727 " AND tagid=%d"
1728 " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)",
1729 tagid, tagid
1730 );
1731 }
1732 }
 
 
 
 
1733 if( subsequent ){
1734 content_deltify(rid, subsequent, 0);
1735 }else{
1736 db_multi_exec(
1737 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
1738
+2 -2
--- src/md5.c
+++ src/md5.c
@@ -376,11 +376,11 @@
376376
FILE *in;
377377
MD5Context ctx;
378378
unsigned char zResult[16];
379379
char zBuf[10240];
380380
381
- in = fopen(zFilename,"rb");
381
+ in = fossil_fopen(zFilename,"rb");
382382
if( in==0 ){
383383
return 1;
384384
}
385385
MD5Init(&ctx);
386386
for(;;){
@@ -438,9 +438,9 @@
438438
blob_read_from_channel(&in, stdin, -1);
439439
md5sum_blob(&in, &cksum);
440440
}else{
441441
md5sum_file(g.argv[i], &cksum);
442442
}
443
- printf("%s %s\n", blob_str(&cksum), g.argv[i]);
443
+ fossil_print("%s %s\n", blob_str(&cksum), g.argv[i]);
444444
blob_reset(&cksum);
445445
}
446446
}
447447
--- src/md5.c
+++ src/md5.c
@@ -376,11 +376,11 @@
376 FILE *in;
377 MD5Context ctx;
378 unsigned char zResult[16];
379 char zBuf[10240];
380
381 in = fopen(zFilename,"rb");
382 if( in==0 ){
383 return 1;
384 }
385 MD5Init(&ctx);
386 for(;;){
@@ -438,9 +438,9 @@
438 blob_read_from_channel(&in, stdin, -1);
439 md5sum_blob(&in, &cksum);
440 }else{
441 md5sum_file(g.argv[i], &cksum);
442 }
443 printf("%s %s\n", blob_str(&cksum), g.argv[i]);
444 blob_reset(&cksum);
445 }
446 }
447
--- src/md5.c
+++ src/md5.c
@@ -376,11 +376,11 @@
376 FILE *in;
377 MD5Context ctx;
378 unsigned char zResult[16];
379 char zBuf[10240];
380
381 in = fossil_fopen(zFilename,"rb");
382 if( in==0 ){
383 return 1;
384 }
385 MD5Init(&ctx);
386 for(;;){
@@ -438,9 +438,9 @@
438 blob_read_from_channel(&in, stdin, -1);
439 md5sum_blob(&in, &cksum);
440 }else{
441 md5sum_file(g.argv[i], &cksum);
442 }
443 fossil_print("%s %s\n", blob_str(&cksum), g.argv[i]);
444 blob_reset(&cksum);
445 }
446 }
447
+19 -17
--- src/merge.c
+++ src/merge.c
@@ -249,20 +249,20 @@
249249
if( debugFlag ){
250250
db_prepare(&q,
251251
"SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, isexe FROM fv"
252252
);
253253
while( db_step(&q)==SQLITE_ROW ){
254
- printf("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d\n",
254
+ fossil_print("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d\n",
255255
db_column_int(&q, 0),
256256
db_column_int(&q, 5),
257257
db_column_int(&q, 6),
258258
db_column_int(&q, 7),
259259
db_column_int(&q, 4),
260260
db_column_int(&q, 8));
261
- printf(" fn = [%s]\n", db_column_text(&q, 1));
262
- printf(" fnp = [%s]\n", db_column_text(&q, 2));
263
- printf(" fnm = [%s]\n", db_column_text(&q, 3));
261
+ fossil_print(" fn = [%s]\n", db_column_text(&q, 1));
262
+ fossil_print(" fnp = [%s]\n", db_column_text(&q, 2));
263
+ fossil_print(" fnm = [%s]\n", db_column_text(&q, 3));
264264
}
265265
db_finalize(&q);
266266
}
267267
268268
/*
@@ -274,11 +274,11 @@
274274
"SELECT idm FROM fv WHERE idp=0 AND idv>0 AND idm>0"
275275
);
276276
while( db_step(&q)==SQLITE_ROW ){
277277
int idm = db_column_int(&q, 0);
278278
char *zName = db_text(0, "SELECT pathname FROM vfile WHERE id=%d", idm);
279
- printf("WARNING - no common ancestor: %s\n", zName);
279
+ fossil_warning("WARNING - no common ancestor: %s\n", zName);
280280
free(zName);
281281
db_multi_exec("UPDATE fv SET idm=0 WHERE idm=%d", idm);
282282
}
283283
db_finalize(&q);
284284
@@ -300,11 +300,11 @@
300300
vid, idm
301301
);
302302
idv = db_last_insert_rowid();
303303
db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid);
304304
zName = db_column_text(&q, 2);
305
- printf("ADDED %s\n", zName);
305
+ fossil_print("ADDED %s\n", zName);
306306
if( !nochangeFlag ){
307307
undo_save(zName);
308308
vfile_to_disk(0, idm, 0, 0);
309309
}
310310
}
@@ -322,11 +322,11 @@
322322
while( db_step(&q)==SQLITE_ROW ){
323323
int idv = db_column_int(&q, 0);
324324
int ridm = db_column_int(&q, 1);
325325
const char *zName = db_column_text(&q, 2);
326326
/* Copy content from idm over into idv. Overwrite idv. */
327
- printf("UPDATE %s\n", zName);
327
+ fossil_print("UPDATE %s\n", zName);
328328
if( !nochangeFlag ){
329329
undo_save(zName);
330330
db_multi_exec(
331331
"UPDATE vfile SET mtime=0, mrid=%d, chnged=2 WHERE id=%d", ridm, idv
332332
);
@@ -355,13 +355,14 @@
355355
int rc;
356356
char *zFullPath;
357357
Blob m, p, r;
358358
/* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */
359359
if( detailFlag ){
360
- printf("MERGE %s (pivot=%d v1=%d v2=%d)\n", zName, ridp, ridm, ridv);
360
+ fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n",
361
+ zName, ridp, ridm, ridv);
361362
}else{
362
- printf("MERGE %s\n", zName);
363
+ fossil_print("MERGE %s\n", zName);
363364
}
364365
undo_save(zName);
365366
zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
366367
content_get(ridp, &p);
367368
content_get(ridm, &m);
@@ -376,15 +377,15 @@
376377
blob_write_to_file(&r, zFullPath);
377378
file_setexe(zFullPath, isExe);
378379
}
379380
db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
380381
if( rc>0 ){
381
- printf("***** %d merge conflicts in %s\n", rc, zName);
382
+ fossil_print("***** %d merge conflicts in %s\n", rc, zName);
382383
nConflict++;
383384
}
384385
}else{
385
- printf("***** Cannot merge binary file %s\n", zName);
386
+ fossil_print("***** Cannot merge binary file %s\n", zName);
386387
nConflict++;
387388
}
388389
blob_reset(&p);
389390
blob_reset(&m);
390391
blob_reset(&r);
@@ -403,22 +404,22 @@
403404
while( db_step(&q)==SQLITE_ROW ){
404405
int idv = db_column_int(&q, 0);
405406
const char *zName = db_column_text(&q, 1);
406407
int chnged = db_column_int(&q, 2);
407408
/* Delete the file idv */
408
- printf("DELETE %s\n", zName);
409
+ fossil_print("DELETE %s\n", zName);
409410
if( chnged ){
410
- printf("WARNING: local edits lost for %s\n", zName);
411
+ fossil_warning("WARNING: local edits lost for %s\n", zName);
411412
nConflict++;
412413
}
413414
undo_save(zName);
414415
db_multi_exec(
415416
"UPDATE vfile SET deleted=1 WHERE id=%d", idv
416417
);
417418
if( !nochangeFlag ){
418419
char *zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
419
- unlink(zFullPath);
420
+ file_delete(zFullPath);
420421
free(zFullPath);
421422
}
422423
}
423424
db_finalize(&q);
424425
@@ -433,11 +434,11 @@
433434
);
434435
while( db_step(&q)==SQLITE_ROW ){
435436
int idv = db_column_int(&q, 0);
436437
const char *zOldName = db_column_text(&q, 1);
437438
const char *zNewName = db_column_text(&q, 2);
438
- printf("RENAME %s -> %s\n", zOldName, zNewName);
439
+ fossil_print("RENAME %s -> %s\n", zOldName, zNewName);
439440
undo_save(zOldName);
440441
undo_save(zNewName);
441442
db_multi_exec(
442443
"UPDATE vfile SET pathname=%Q, origname=coalesce(origname,pathname)"
443444
" WHERE id=%d AND vid=%d", zNewName, idv, vid
@@ -444,11 +445,11 @@
444445
);
445446
if( !nochangeFlag ){
446447
char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
447448
char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
448449
file_copy(zFullOldPath, zFullNewPath);
449
- unlink(zFullOldPath);
450
+ file_delete(zFullOldPath);
450451
free(zFullNewPath);
451452
free(zFullOldPath);
452453
}
453454
}
454455
db_finalize(&q);
@@ -455,11 +456,12 @@
455456
456457
457458
/* Report on conflicts
458459
*/
459460
if( nConflict && !nochangeFlag ){
460
- printf("WARNING: merge conflicts - see messages above for details.\n");
461
+ fossil_warning(
462
+ "WARNING: merge conflicts - see messages above for details.\n");
461463
}
462464
463465
/*
464466
** Clean up the mid and pid VFILE entries. Then commit the changes.
465467
*/
466468
--- src/merge.c
+++ src/merge.c
@@ -249,20 +249,20 @@
249 if( debugFlag ){
250 db_prepare(&q,
251 "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, isexe FROM fv"
252 );
253 while( db_step(&q)==SQLITE_ROW ){
254 printf("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d\n",
255 db_column_int(&q, 0),
256 db_column_int(&q, 5),
257 db_column_int(&q, 6),
258 db_column_int(&q, 7),
259 db_column_int(&q, 4),
260 db_column_int(&q, 8));
261 printf(" fn = [%s]\n", db_column_text(&q, 1));
262 printf(" fnp = [%s]\n", db_column_text(&q, 2));
263 printf(" fnm = [%s]\n", db_column_text(&q, 3));
264 }
265 db_finalize(&q);
266 }
267
268 /*
@@ -274,11 +274,11 @@
274 "SELECT idm FROM fv WHERE idp=0 AND idv>0 AND idm>0"
275 );
276 while( db_step(&q)==SQLITE_ROW ){
277 int idm = db_column_int(&q, 0);
278 char *zName = db_text(0, "SELECT pathname FROM vfile WHERE id=%d", idm);
279 printf("WARNING - no common ancestor: %s\n", zName);
280 free(zName);
281 db_multi_exec("UPDATE fv SET idm=0 WHERE idm=%d", idm);
282 }
283 db_finalize(&q);
284
@@ -300,11 +300,11 @@
300 vid, idm
301 );
302 idv = db_last_insert_rowid();
303 db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid);
304 zName = db_column_text(&q, 2);
305 printf("ADDED %s\n", zName);
306 if( !nochangeFlag ){
307 undo_save(zName);
308 vfile_to_disk(0, idm, 0, 0);
309 }
310 }
@@ -322,11 +322,11 @@
322 while( db_step(&q)==SQLITE_ROW ){
323 int idv = db_column_int(&q, 0);
324 int ridm = db_column_int(&q, 1);
325 const char *zName = db_column_text(&q, 2);
326 /* Copy content from idm over into idv. Overwrite idv. */
327 printf("UPDATE %s\n", zName);
328 if( !nochangeFlag ){
329 undo_save(zName);
330 db_multi_exec(
331 "UPDATE vfile SET mtime=0, mrid=%d, chnged=2 WHERE id=%d", ridm, idv
332 );
@@ -355,13 +355,14 @@
355 int rc;
356 char *zFullPath;
357 Blob m, p, r;
358 /* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */
359 if( detailFlag ){
360 printf("MERGE %s (pivot=%d v1=%d v2=%d)\n", zName, ridp, ridm, ridv);
 
361 }else{
362 printf("MERGE %s\n", zName);
363 }
364 undo_save(zName);
365 zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
366 content_get(ridp, &p);
367 content_get(ridm, &m);
@@ -376,15 +377,15 @@
376 blob_write_to_file(&r, zFullPath);
377 file_setexe(zFullPath, isExe);
378 }
379 db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
380 if( rc>0 ){
381 printf("***** %d merge conflicts in %s\n", rc, zName);
382 nConflict++;
383 }
384 }else{
385 printf("***** Cannot merge binary file %s\n", zName);
386 nConflict++;
387 }
388 blob_reset(&p);
389 blob_reset(&m);
390 blob_reset(&r);
@@ -403,22 +404,22 @@
403 while( db_step(&q)==SQLITE_ROW ){
404 int idv = db_column_int(&q, 0);
405 const char *zName = db_column_text(&q, 1);
406 int chnged = db_column_int(&q, 2);
407 /* Delete the file idv */
408 printf("DELETE %s\n", zName);
409 if( chnged ){
410 printf("WARNING: local edits lost for %s\n", zName);
411 nConflict++;
412 }
413 undo_save(zName);
414 db_multi_exec(
415 "UPDATE vfile SET deleted=1 WHERE id=%d", idv
416 );
417 if( !nochangeFlag ){
418 char *zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
419 unlink(zFullPath);
420 free(zFullPath);
421 }
422 }
423 db_finalize(&q);
424
@@ -433,11 +434,11 @@
433 );
434 while( db_step(&q)==SQLITE_ROW ){
435 int idv = db_column_int(&q, 0);
436 const char *zOldName = db_column_text(&q, 1);
437 const char *zNewName = db_column_text(&q, 2);
438 printf("RENAME %s -> %s\n", zOldName, zNewName);
439 undo_save(zOldName);
440 undo_save(zNewName);
441 db_multi_exec(
442 "UPDATE vfile SET pathname=%Q, origname=coalesce(origname,pathname)"
443 " WHERE id=%d AND vid=%d", zNewName, idv, vid
@@ -444,11 +445,11 @@
444 );
445 if( !nochangeFlag ){
446 char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
447 char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
448 file_copy(zFullOldPath, zFullNewPath);
449 unlink(zFullOldPath);
450 free(zFullNewPath);
451 free(zFullOldPath);
452 }
453 }
454 db_finalize(&q);
@@ -455,11 +456,12 @@
455
456
457 /* Report on conflicts
458 */
459 if( nConflict && !nochangeFlag ){
460 printf("WARNING: merge conflicts - see messages above for details.\n");
 
461 }
462
463 /*
464 ** Clean up the mid and pid VFILE entries. Then commit the changes.
465 */
466
--- src/merge.c
+++ src/merge.c
@@ -249,20 +249,20 @@
249 if( debugFlag ){
250 db_prepare(&q,
251 "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, isexe FROM fv"
252 );
253 while( db_step(&q)==SQLITE_ROW ){
254 fossil_print("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d\n",
255 db_column_int(&q, 0),
256 db_column_int(&q, 5),
257 db_column_int(&q, 6),
258 db_column_int(&q, 7),
259 db_column_int(&q, 4),
260 db_column_int(&q, 8));
261 fossil_print(" fn = [%s]\n", db_column_text(&q, 1));
262 fossil_print(" fnp = [%s]\n", db_column_text(&q, 2));
263 fossil_print(" fnm = [%s]\n", db_column_text(&q, 3));
264 }
265 db_finalize(&q);
266 }
267
268 /*
@@ -274,11 +274,11 @@
274 "SELECT idm FROM fv WHERE idp=0 AND idv>0 AND idm>0"
275 );
276 while( db_step(&q)==SQLITE_ROW ){
277 int idm = db_column_int(&q, 0);
278 char *zName = db_text(0, "SELECT pathname FROM vfile WHERE id=%d", idm);
279 fossil_warning("WARNING - no common ancestor: %s\n", zName);
280 free(zName);
281 db_multi_exec("UPDATE fv SET idm=0 WHERE idm=%d", idm);
282 }
283 db_finalize(&q);
284
@@ -300,11 +300,11 @@
300 vid, idm
301 );
302 idv = db_last_insert_rowid();
303 db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid);
304 zName = db_column_text(&q, 2);
305 fossil_print("ADDED %s\n", zName);
306 if( !nochangeFlag ){
307 undo_save(zName);
308 vfile_to_disk(0, idm, 0, 0);
309 }
310 }
@@ -322,11 +322,11 @@
322 while( db_step(&q)==SQLITE_ROW ){
323 int idv = db_column_int(&q, 0);
324 int ridm = db_column_int(&q, 1);
325 const char *zName = db_column_text(&q, 2);
326 /* Copy content from idm over into idv. Overwrite idv. */
327 fossil_print("UPDATE %s\n", zName);
328 if( !nochangeFlag ){
329 undo_save(zName);
330 db_multi_exec(
331 "UPDATE vfile SET mtime=0, mrid=%d, chnged=2 WHERE id=%d", ridm, idv
332 );
@@ -355,13 +355,14 @@
355 int rc;
356 char *zFullPath;
357 Blob m, p, r;
358 /* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */
359 if( detailFlag ){
360 fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n",
361 zName, ridp, ridm, ridv);
362 }else{
363 fossil_print("MERGE %s\n", zName);
364 }
365 undo_save(zName);
366 zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
367 content_get(ridp, &p);
368 content_get(ridm, &m);
@@ -376,15 +377,15 @@
377 blob_write_to_file(&r, zFullPath);
378 file_setexe(zFullPath, isExe);
379 }
380 db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
381 if( rc>0 ){
382 fossil_print("***** %d merge conflicts in %s\n", rc, zName);
383 nConflict++;
384 }
385 }else{
386 fossil_print("***** Cannot merge binary file %s\n", zName);
387 nConflict++;
388 }
389 blob_reset(&p);
390 blob_reset(&m);
391 blob_reset(&r);
@@ -403,22 +404,22 @@
404 while( db_step(&q)==SQLITE_ROW ){
405 int idv = db_column_int(&q, 0);
406 const char *zName = db_column_text(&q, 1);
407 int chnged = db_column_int(&q, 2);
408 /* Delete the file idv */
409 fossil_print("DELETE %s\n", zName);
410 if( chnged ){
411 fossil_warning("WARNING: local edits lost for %s\n", zName);
412 nConflict++;
413 }
414 undo_save(zName);
415 db_multi_exec(
416 "UPDATE vfile SET deleted=1 WHERE id=%d", idv
417 );
418 if( !nochangeFlag ){
419 char *zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
420 file_delete(zFullPath);
421 free(zFullPath);
422 }
423 }
424 db_finalize(&q);
425
@@ -433,11 +434,11 @@
434 );
435 while( db_step(&q)==SQLITE_ROW ){
436 int idv = db_column_int(&q, 0);
437 const char *zOldName = db_column_text(&q, 1);
438 const char *zNewName = db_column_text(&q, 2);
439 fossil_print("RENAME %s -> %s\n", zOldName, zNewName);
440 undo_save(zOldName);
441 undo_save(zNewName);
442 db_multi_exec(
443 "UPDATE vfile SET pathname=%Q, origname=coalesce(origname,pathname)"
444 " WHERE id=%d AND vid=%d", zNewName, idv, vid
@@ -444,11 +445,11 @@
445 );
446 if( !nochangeFlag ){
447 char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
448 char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
449 file_copy(zFullOldPath, zFullNewPath);
450 file_delete(zFullOldPath);
451 free(zFullNewPath);
452 free(zFullOldPath);
453 }
454 }
455 db_finalize(&q);
@@ -455,11 +456,12 @@
456
457
458 /* Report on conflicts
459 */
460 if( nConflict && !nochangeFlag ){
461 fossil_warning(
462 "WARNING: merge conflicts - see messages above for details.\n");
463 }
464
465 /*
466 ** Clean up the mid and pid VFILE entries. Then commit the changes.
467 */
468
+19 -20
--- src/merge3.c
+++ src/merge3.c
@@ -153,15 +153,17 @@
153153
int i1, i2; /* Index into aC1[] and aC2[] */
154154
int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
155155
int limit1, limit2; /* Sizes of aC1[] and aC2[] */
156156
int nConflict = 0; /* Number of merge conflicts seen so far */
157157
static const char zBegin[] =
158
- "<<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<\n";
159
- static const char zMid[] =
160
- "======= original content above; conflict below =============\n";
158
+ "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n";
159
+ static const char zMid1[] =
160
+ "======= COMMON ANCESTOR content follows ============================\n";
161
+ static const char zMid2[] =
162
+ "======= MERGED IN content follows ==================================\n";
161163
static const char zEnd[] =
162
- ">>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>\n";
164
+ ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
163165
164166
blob_zero(pOut); /* Merge results stored in pOut */
165167
166168
/* Compute the edits that occur from pPivot => pV1 (into aC1)
167169
** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -192,11 +194,11 @@
192194
DEBUG(
193195
for(i1=0; i1<limit1; i1+=3){
194196
printf("c1: %4d %4d %4d\n", aC1[i1], aC1[i1+1], aC1[i1+2]);
195197
}
196198
for(i2=0; i2<limit2; i2+=3){
197
- printf("c2: %4d %4d %4d\n", aC2[i2], aC2[i2+1], aC2[i2+2]);
199
+ printf("c2: %4d %4d %4d\n", aC2[i2], aC2[i2+1], aC2[i2+2]);
198200
}
199201
)
200202
201203
/* Loop over the two edit vectors and use them to compute merged text
202204
** which is written into pOut. i1 and i2 are multiples of 3 which are
@@ -264,15 +266,16 @@
264266
sz++;
265267
}
266268
DEBUG( printf("CONFLICT %d\n", sz); )
267269
blob_appendf(pOut, zBegin);
268270
i1 = output_one_side(pOut, pV1, aC1, i1, sz);
269
- blob_appendf(pOut, zMid);
271
+ blob_appendf(pOut, zMid1);
272
+ blob_copy_lines(pOut, pPivot, sz);
273
+ blob_appendf(pOut, zMid2);
270274
i2 = output_one_side(pOut, pV2, aC2, i2, sz);
271275
blob_appendf(pOut, zEnd);
272
- blob_copy_lines(0, pPivot, sz);
273
- }
276
+ }
274277
275278
/* If we are finished with an edit triple, advance to the next
276279
** triple.
277280
*/
278281
if( i1<limit1 && aC1[i1]==0 && aC1[i1+1]==0 && aC1[i1+2]==0 ) i1+=3;
@@ -311,25 +314,21 @@
311314
Blob pivot, v1, v2, merged;
312315
if( g.argc!=6 ){
313316
usage("PIVOT V1 V2 MERGED");
314317
}
315318
if( blob_read_from_file(&pivot, g.argv[2])<0 ){
316
- fprintf(stderr,"cannot read %s\n", g.argv[2]);
317
- fossil_exit(1);
319
+ fossil_fatal("cannot read %s\n", g.argv[2]);
318320
}
319321
if( blob_read_from_file(&v1, g.argv[3])<0 ){
320
- fprintf(stderr,"cannot read %s\n", g.argv[3]);
321
- fossil_exit(1);
322
+ fossil_fatal("cannot read %s\n", g.argv[3]);
322323
}
323324
if( blob_read_from_file(&v2, g.argv[4])<0 ){
324
- fprintf(stderr,"cannot read %s\n", g.argv[4]);
325
- fossil_exit(1);
325
+ fossil_fatal("cannot read %s\n", g.argv[4]);
326326
}
327327
blob_merge(&pivot, &v1, &v2, &merged);
328328
if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){
329
- fprintf(stderr,"cannot write %s\n", g.argv[4]);
330
- fossil_exit(1);
329
+ fossil_fatal("cannot write %s\n", g.argv[4]);
331330
}
332331
blob_reset(&pivot);
333332
blob_reset(&v1);
334333
blob_reset(&v2);
335334
blob_reset(&merged);
@@ -425,14 +424,14 @@
425424
zCmd = string_subst(zGMerge, 8, azSubst);
426425
printf("%s\n", zCmd); fflush(stdout);
427426
fossil_system(zCmd);
428427
if( file_size(zOut)>=0 ){
429428
blob_read_from_file(pOut, zOut);
430
- unlink(zPivot);
431
- unlink(zOrig);
432
- unlink(zOther);
433
- unlink(zOut);
429
+ file_delete(zPivot);
430
+ file_delete(zOrig);
431
+ file_delete(zOther);
432
+ file_delete(zOut);
434433
}
435434
fossil_free(zCmd);
436435
fossil_free(zOut);
437436
}
438437
fossil_free(zPivot);
439438
--- src/merge3.c
+++ src/merge3.c
@@ -153,15 +153,17 @@
153 int i1, i2; /* Index into aC1[] and aC2[] */
154 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
155 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
156 int nConflict = 0; /* Number of merge conflicts seen so far */
157 static const char zBegin[] =
158 "<<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<\n";
159 static const char zMid[] =
160 "======= original content above; conflict below =============\n";
 
 
161 static const char zEnd[] =
162 ">>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>\n";
163
164 blob_zero(pOut); /* Merge results stored in pOut */
165
166 /* Compute the edits that occur from pPivot => pV1 (into aC1)
167 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -192,11 +194,11 @@
192 DEBUG(
193 for(i1=0; i1<limit1; i1+=3){
194 printf("c1: %4d %4d %4d\n", aC1[i1], aC1[i1+1], aC1[i1+2]);
195 }
196 for(i2=0; i2<limit2; i2+=3){
197 printf("c2: %4d %4d %4d\n", aC2[i2], aC2[i2+1], aC2[i2+2]);
198 }
199 )
200
201 /* Loop over the two edit vectors and use them to compute merged text
202 ** which is written into pOut. i1 and i2 are multiples of 3 which are
@@ -264,15 +266,16 @@
264 sz++;
265 }
266 DEBUG( printf("CONFLICT %d\n", sz); )
267 blob_appendf(pOut, zBegin);
268 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
269 blob_appendf(pOut, zMid);
 
 
270 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
271 blob_appendf(pOut, zEnd);
272 blob_copy_lines(0, pPivot, sz);
273 }
274
275 /* If we are finished with an edit triple, advance to the next
276 ** triple.
277 */
278 if( i1<limit1 && aC1[i1]==0 && aC1[i1+1]==0 && aC1[i1+2]==0 ) i1+=3;
@@ -311,25 +314,21 @@
311 Blob pivot, v1, v2, merged;
312 if( g.argc!=6 ){
313 usage("PIVOT V1 V2 MERGED");
314 }
315 if( blob_read_from_file(&pivot, g.argv[2])<0 ){
316 fprintf(stderr,"cannot read %s\n", g.argv[2]);
317 fossil_exit(1);
318 }
319 if( blob_read_from_file(&v1, g.argv[3])<0 ){
320 fprintf(stderr,"cannot read %s\n", g.argv[3]);
321 fossil_exit(1);
322 }
323 if( blob_read_from_file(&v2, g.argv[4])<0 ){
324 fprintf(stderr,"cannot read %s\n", g.argv[4]);
325 fossil_exit(1);
326 }
327 blob_merge(&pivot, &v1, &v2, &merged);
328 if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){
329 fprintf(stderr,"cannot write %s\n", g.argv[4]);
330 fossil_exit(1);
331 }
332 blob_reset(&pivot);
333 blob_reset(&v1);
334 blob_reset(&v2);
335 blob_reset(&merged);
@@ -425,14 +424,14 @@
425 zCmd = string_subst(zGMerge, 8, azSubst);
426 printf("%s\n", zCmd); fflush(stdout);
427 fossil_system(zCmd);
428 if( file_size(zOut)>=0 ){
429 blob_read_from_file(pOut, zOut);
430 unlink(zPivot);
431 unlink(zOrig);
432 unlink(zOther);
433 unlink(zOut);
434 }
435 fossil_free(zCmd);
436 fossil_free(zOut);
437 }
438 fossil_free(zPivot);
439
--- src/merge3.c
+++ src/merge3.c
@@ -153,15 +153,17 @@
153 int i1, i2; /* Index into aC1[] and aC2[] */
154 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
155 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
156 int nConflict = 0; /* Number of merge conflicts seen so far */
157 static const char zBegin[] =
158 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n";
159 static const char zMid1[] =
160 "======= COMMON ANCESTOR content follows ============================\n";
161 static const char zMid2[] =
162 "======= MERGED IN content follows ==================================\n";
163 static const char zEnd[] =
164 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
165
166 blob_zero(pOut); /* Merge results stored in pOut */
167
168 /* Compute the edits that occur from pPivot => pV1 (into aC1)
169 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -192,11 +194,11 @@
194 DEBUG(
195 for(i1=0; i1<limit1; i1+=3){
196 printf("c1: %4d %4d %4d\n", aC1[i1], aC1[i1+1], aC1[i1+2]);
197 }
198 for(i2=0; i2<limit2; i2+=3){
199 printf("c2: %4d %4d %4d\n", aC2[i2], aC2[i2+1], aC2[i2+2]);
200 }
201 )
202
203 /* Loop over the two edit vectors and use them to compute merged text
204 ** which is written into pOut. i1 and i2 are multiples of 3 which are
@@ -264,15 +266,16 @@
266 sz++;
267 }
268 DEBUG( printf("CONFLICT %d\n", sz); )
269 blob_appendf(pOut, zBegin);
270 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
271 blob_appendf(pOut, zMid1);
272 blob_copy_lines(pOut, pPivot, sz);
273 blob_appendf(pOut, zMid2);
274 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
275 blob_appendf(pOut, zEnd);
276 }
 
277
278 /* If we are finished with an edit triple, advance to the next
279 ** triple.
280 */
281 if( i1<limit1 && aC1[i1]==0 && aC1[i1+1]==0 && aC1[i1+2]==0 ) i1+=3;
@@ -311,25 +314,21 @@
314 Blob pivot, v1, v2, merged;
315 if( g.argc!=6 ){
316 usage("PIVOT V1 V2 MERGED");
317 }
318 if( blob_read_from_file(&pivot, g.argv[2])<0 ){
319 fossil_fatal("cannot read %s\n", g.argv[2]);
 
320 }
321 if( blob_read_from_file(&v1, g.argv[3])<0 ){
322 fossil_fatal("cannot read %s\n", g.argv[3]);
 
323 }
324 if( blob_read_from_file(&v2, g.argv[4])<0 ){
325 fossil_fatal("cannot read %s\n", g.argv[4]);
 
326 }
327 blob_merge(&pivot, &v1, &v2, &merged);
328 if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){
329 fossil_fatal("cannot write %s\n", g.argv[4]);
 
330 }
331 blob_reset(&pivot);
332 blob_reset(&v1);
333 blob_reset(&v2);
334 blob_reset(&merged);
@@ -425,14 +424,14 @@
424 zCmd = string_subst(zGMerge, 8, azSubst);
425 printf("%s\n", zCmd); fflush(stdout);
426 fossil_system(zCmd);
427 if( file_size(zOut)>=0 ){
428 blob_read_from_file(pOut, zOut);
429 file_delete(zPivot);
430 file_delete(zOrig);
431 file_delete(zOther);
432 file_delete(zOut);
433 }
434 fossil_free(zCmd);
435 fossil_free(zOut);
436 }
437 fossil_free(zPivot);
438
+5 -5
--- src/name.c
+++ src/name.c
@@ -201,12 +201,12 @@
201201
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
202202
"(SELECT pid FROM plink WHERE cid=%d AND isprim)",
203203
vid);
204204
}else if( fossil_strcmp(zTag, "next")==0 ){
205205
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
206
- "(SELECT cid FROM plink WHERE pid=%d AND isprim"
207
- " ORDER BY mtime DESC)",
206
+ "(SELECT cid FROM plink WHERE pid=%d"
207
+ " ORDER BY isprim DESC, mtime DESC)",
208208
vid);
209209
}
210210
}
211211
}
212212
return zUuid;
@@ -267,16 +267,16 @@
267267
int i;
268268
Blob name;
269269
db_must_be_within_tree();
270270
for(i=2; i<g.argc; i++){
271271
blob_init(&name, g.argv[i], -1);
272
- printf("%s -> ", g.argv[i]);
272
+ fossil_print("%s -> ", g.argv[i]);
273273
if( name_to_uuid(&name, 1) ){
274
- printf("ERROR: %s\n", g.zErrMsg);
274
+ fossil_print("ERROR: %s\n", g.zErrMsg);
275275
fossil_error_reset();
276276
}else{
277
- printf("%s\n", blob_buffer(&name));
277
+ fossil_print("%s\n", blob_buffer(&name));
278278
}
279279
blob_reset(&name);
280280
}
281281
}
282282
283283
--- src/name.c
+++ src/name.c
@@ -201,12 +201,12 @@
201 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
202 "(SELECT pid FROM plink WHERE cid=%d AND isprim)",
203 vid);
204 }else if( fossil_strcmp(zTag, "next")==0 ){
205 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
206 "(SELECT cid FROM plink WHERE pid=%d AND isprim"
207 " ORDER BY mtime DESC)",
208 vid);
209 }
210 }
211 }
212 return zUuid;
@@ -267,16 +267,16 @@
267 int i;
268 Blob name;
269 db_must_be_within_tree();
270 for(i=2; i<g.argc; i++){
271 blob_init(&name, g.argv[i], -1);
272 printf("%s -> ", g.argv[i]);
273 if( name_to_uuid(&name, 1) ){
274 printf("ERROR: %s\n", g.zErrMsg);
275 fossil_error_reset();
276 }else{
277 printf("%s\n", blob_buffer(&name));
278 }
279 blob_reset(&name);
280 }
281 }
282
283
--- src/name.c
+++ src/name.c
@@ -201,12 +201,12 @@
201 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
202 "(SELECT pid FROM plink WHERE cid=%d AND isprim)",
203 vid);
204 }else if( fossil_strcmp(zTag, "next")==0 ){
205 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
206 "(SELECT cid FROM plink WHERE pid=%d"
207 " ORDER BY isprim DESC, mtime DESC)",
208 vid);
209 }
210 }
211 }
212 return zUuid;
@@ -267,16 +267,16 @@
267 int i;
268 Blob name;
269 db_must_be_within_tree();
270 for(i=2; i<g.argc; i++){
271 blob_init(&name, g.argv[i], -1);
272 fossil_print("%s -> ", g.argv[i]);
273 if( name_to_uuid(&name, 1) ){
274 fossil_print("ERROR: %s\n", g.zErrMsg);
275 fossil_error_reset();
276 }else{
277 fossil_print("%s\n", blob_buffer(&name));
278 }
279 blob_reset(&name);
280 }
281 }
282
283
+10 -9
--- src/path.c
+++ src/path.c
@@ -213,16 +213,17 @@
213213
z = db_text(0,
214214
"SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
215215
" FROM blob, event"
216216
" WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
217217
p->rid, p->rid);
218
- printf("%4d: %s", n, z);
218
+ fossil_print("%4d: %s", n, z);
219219
fossil_free(z);
220220
if( p->u.pTo ){
221
- printf(" is a %s of\n", p->u.pTo->fromIsParent ? "parent" : "child");
221
+ fossil_print(" is a %s of\n",
222
+ p->u.pTo->fromIsParent ? "parent" : "child");
222223
}else{
223
- printf("\n");
224
+ fossil_print("\n");
224225
}
225226
}
226227
}
227228
228229
/*
@@ -312,16 +313,16 @@
312313
z = db_text(0,
313314
"SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
314315
" FROM blob, event"
315316
" WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
316317
p->rid, p->rid);
317
- printf("%4d: %s", n, z);
318
+ fossil_print("%4d: %s", n, z);
318319
fossil_free(z);
319
- if( p->rid==iFrom ) printf(" VERSION1");
320
- if( p->rid==iTo ) printf(" VERSION2");
321
- if( p->rid==iPivot ) printf(" PIVOT");
322
- printf("\n");
320
+ if( p->rid==iFrom ) fossil_print(" VERSION1");
321
+ if( p->rid==iTo ) fossil_print(" VERSION2");
322
+ if( p->rid==iPivot ) fossil_print(" PIVOT");
323
+ fossil_print("\n");
323324
}
324325
}
325326
326327
327328
/*
@@ -445,11 +446,11 @@
445446
for(i=0; i<nChng; i++){
446447
char *zFrom, *zTo;
447448
448449
zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
449450
zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
450
- printf("[%s] -> [%s]\n", zFrom, zTo);
451
+ fossil_print("[%s] -> [%s]\n", zFrom, zTo);
451452
fossil_free(zFrom);
452453
fossil_free(zTo);
453454
}
454455
fossil_free(aChng);
455456
}
456457
--- src/path.c
+++ src/path.c
@@ -213,16 +213,17 @@
213 z = db_text(0,
214 "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
215 " FROM blob, event"
216 " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
217 p->rid, p->rid);
218 printf("%4d: %s", n, z);
219 fossil_free(z);
220 if( p->u.pTo ){
221 printf(" is a %s of\n", p->u.pTo->fromIsParent ? "parent" : "child");
 
222 }else{
223 printf("\n");
224 }
225 }
226 }
227
228 /*
@@ -312,16 +313,16 @@
312 z = db_text(0,
313 "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
314 " FROM blob, event"
315 " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
316 p->rid, p->rid);
317 printf("%4d: %s", n, z);
318 fossil_free(z);
319 if( p->rid==iFrom ) printf(" VERSION1");
320 if( p->rid==iTo ) printf(" VERSION2");
321 if( p->rid==iPivot ) printf(" PIVOT");
322 printf("\n");
323 }
324 }
325
326
327 /*
@@ -445,11 +446,11 @@
445 for(i=0; i<nChng; i++){
446 char *zFrom, *zTo;
447
448 zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
449 zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
450 printf("[%s] -> [%s]\n", zFrom, zTo);
451 fossil_free(zFrom);
452 fossil_free(zTo);
453 }
454 fossil_free(aChng);
455 }
456
--- src/path.c
+++ src/path.c
@@ -213,16 +213,17 @@
213 z = db_text(0,
214 "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
215 " FROM blob, event"
216 " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
217 p->rid, p->rid);
218 fossil_print("%4d: %s", n, z);
219 fossil_free(z);
220 if( p->u.pTo ){
221 fossil_print(" is a %s of\n",
222 p->u.pTo->fromIsParent ? "parent" : "child");
223 }else{
224 fossil_print("\n");
225 }
226 }
227 }
228
229 /*
@@ -312,16 +313,16 @@
313 z = db_text(0,
314 "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
315 " FROM blob, event"
316 " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
317 p->rid, p->rid);
318 fossil_print("%4d: %s", n, z);
319 fossil_free(z);
320 if( p->rid==iFrom ) fossil_print(" VERSION1");
321 if( p->rid==iTo ) fossil_print(" VERSION2");
322 if( p->rid==iPivot ) fossil_print(" PIVOT");
323 fossil_print("\n");
324 }
325 }
326
327
328 /*
@@ -445,11 +446,11 @@
446 for(i=0; i<nChng; i++){
447 char *zFrom, *zTo;
448
449 zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
450 zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
451 fossil_print("[%s] -> [%s]\n", zFrom, zTo);
452 fossil_free(zFrom);
453 fossil_free(zTo);
454 }
455 fossil_free(aChng);
456 }
457
+27 -1
--- src/printf.c
+++ src/printf.c
@@ -797,10 +797,36 @@
797797
void fossil_error_reset(void){
798798
free(g.zErrMsg);
799799
g.zErrMsg = 0;
800800
g.iErrPriority = 0;
801801
}
802
+
803
+/*
804
+** Write to standard output or standard error.
805
+**
806
+** On windows, transform the output into the current terminal encoding
807
+** if the output is going to the screen. If output is redirected into
808
+** a file, no translation occurs. No translation ever occurs on unix.
809
+*/
810
+void fossil_puts(const char *z, int toStdErr){
811
+#if defined(_WIN32)
812
+ static int once = 1;
813
+ static int istty[2];
814
+ char *zToFree = 0;
815
+ if( once ){
816
+ istty[0] = _isatty(fileno(stdout));
817
+ istty[1] = _isatty(fileno(stderr));
818
+ once = 0;
819
+ }
820
+ assert( toStdErr==0 || toStdErr==1 );
821
+ if( istty[toStdErr] ) z = zToFree = fossil_utf8_to_console(z);
822
+ fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
823
+ free(zToFree);
824
+#else
825
+ fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
826
+#endif
827
+}
802828
803829
/*
804830
** Write output for user consumption. If g.cgiOutput is enabled, then
805831
** send the output as part of the CGI reply. If g.cgiOutput is false,
806832
** then write on standard output.
@@ -811,11 +837,11 @@
811837
if( g.cgiOutput ){
812838
cgi_vprintf(zFormat, ap);
813839
}else{
814840
Blob b = empty_blob;
815841
vxprintf(&b, zFormat, ap);
816
- fwrite(blob_buffer(&b), 1, blob_size(&b), stdout);
842
+ fossil_puts(blob_str(&b), 0);
817843
blob_reset(&b);
818844
}
819845
}
820846
821847
/*
822848
--- src/printf.c
+++ src/printf.c
@@ -797,10 +797,36 @@
797 void fossil_error_reset(void){
798 free(g.zErrMsg);
799 g.zErrMsg = 0;
800 g.iErrPriority = 0;
801 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
802
803 /*
804 ** Write output for user consumption. If g.cgiOutput is enabled, then
805 ** send the output as part of the CGI reply. If g.cgiOutput is false,
806 ** then write on standard output.
@@ -811,11 +837,11 @@
811 if( g.cgiOutput ){
812 cgi_vprintf(zFormat, ap);
813 }else{
814 Blob b = empty_blob;
815 vxprintf(&b, zFormat, ap);
816 fwrite(blob_buffer(&b), 1, blob_size(&b), stdout);
817 blob_reset(&b);
818 }
819 }
820
821 /*
822
--- src/printf.c
+++ src/printf.c
@@ -797,10 +797,36 @@
797 void fossil_error_reset(void){
798 free(g.zErrMsg);
799 g.zErrMsg = 0;
800 g.iErrPriority = 0;
801 }
802
803 /*
804 ** Write to standard output or standard error.
805 **
806 ** On windows, transform the output into the current terminal encoding
807 ** if the output is going to the screen. If output is redirected into
808 ** a file, no translation occurs. No translation ever occurs on unix.
809 */
810 void fossil_puts(const char *z, int toStdErr){
811 #if defined(_WIN32)
812 static int once = 1;
813 static int istty[2];
814 char *zToFree = 0;
815 if( once ){
816 istty[0] = _isatty(fileno(stdout));
817 istty[1] = _isatty(fileno(stderr));
818 once = 0;
819 }
820 assert( toStdErr==0 || toStdErr==1 );
821 if( istty[toStdErr] ) z = zToFree = fossil_utf8_to_console(z);
822 fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
823 free(zToFree);
824 #else
825 fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
826 #endif
827 }
828
829 /*
830 ** Write output for user consumption. If g.cgiOutput is enabled, then
831 ** send the output as part of the CGI reply. If g.cgiOutput is false,
832 ** then write on standard output.
@@ -811,11 +837,11 @@
837 if( g.cgiOutput ){
838 cgi_vprintf(zFormat, ap);
839 }else{
840 Blob b = empty_blob;
841 vxprintf(&b, zFormat, ap);
842 fossil_puts(blob_str(&b), 0);
843 blob_reset(&b);
844 }
845 }
846
847 /*
848
+127 -40
--- src/rebuild.c
+++ src/rebuild.c
@@ -22,13 +22,15 @@
2222
#include <assert.h>
2323
#include <dirent.h>
2424
#include <errno.h>
2525
2626
/*
27
-** Schema changes
27
+** Make changes to the stable part of the schema (the part that is not
28
+** simply deleted and reconstructed on a rebuild) to bring the schema
29
+** up to the latest.
2830
*/
29
-static const char zSchemaUpdates[] =
31
+static const char zSchemaUpdates1[] =
3032
@ -- Index on the delta table
3133
@ --
3234
@ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid);
3335
@
3436
@ -- Artifacts that should not be processed are identified in the
@@ -39,41 +41,124 @@
3941
@ --
4042
@ -- Shunned artifacts do not exist in the blob table. Hence they
4143
@ -- have not artifact ID (rid) and we thus must store their full
4244
@ -- UUID.
4345
@ --
44
-@ CREATE TABLE IF NOT EXISTS shun(uuid UNIQUE);
46
+@ CREATE TABLE IF NOT EXISTS shun(
47
+@ uuid UNIQUE, -- UUID of artifact to be shunned. Canonical form
48
+@ mtime INTEGER, -- When added. Seconds since 1970
49
+@ scom TEXT -- Optional text explaining why the shun occurred
50
+@ );
4551
@
4652
@ -- Artifacts that should not be pushed are stored in the "private"
4753
@ -- table.
4854
@ --
4955
@ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
5056
@
51
-@ -- An entry in this table describes a database query that generates a
52
-@ -- table of tickets.
53
-@ --
54
-@ CREATE TABLE IF NOT EXISTS reportfmt(
55
-@ rn integer primary key, -- Report number
56
-@ owner text, -- Owner of this report format (not used)
57
-@ title text, -- Title of this report
58
-@ cols text, -- A color-key specification
59
-@ sqlcode text -- An SQL SELECT statement for this report
60
-@ );
61
-@
6257
@ -- Some ticket content (such as the originators email address or contact
6358
@ -- information) needs to be obscured to protect privacy. This is achieved
6459
@ -- by storing an SHA1 hash of the content. For display, the hash is
6560
@ -- mapped back into the original text using this table.
6661
@ --
6762
@ -- This table contains sensitive information and should not be shared
6863
@ -- with unauthorized users.
6964
@ --
7065
@ CREATE TABLE IF NOT EXISTS concealed(
71
-@ hash TEXT PRIMARY KEY,
72
-@ content TEXT
66
+@ hash TEXT PRIMARY KEY, -- The SHA1 hash of content
67
+@ mtime INTEGER, -- Time created. Seconds since 1970
68
+@ content TEXT -- Content intended to be concealed
69
+@ );
70
+;
71
+static const char zSchemaUpdates2[] =
72
+@ -- An entry in this table describes a database query that generates a
73
+@ -- table of tickets.
74
+@ --
75
+@ CREATE TABLE IF NOT EXISTS reportfmt(
76
+@ rn INTEGER PRIMARY KEY, -- Report number
77
+@ owner TEXT, -- Owner of this report format (not used)
78
+@ title TEXT UNIQUE, -- Title of this report
79
+@ mtime INTEGER, -- Time last modified. Seconds since 1970
80
+@ cols TEXT, -- A color-key specification
81
+@ sqlcode TEXT -- An SQL SELECT statement for this report
7382
@ );
7483
;
84
+
85
+static void rebuild_update_schema(void){
86
+ int rc;
87
+ db_multi_exec(zSchemaUpdates1);
88
+ db_multi_exec(zSchemaUpdates2);
89
+
90
+ rc = db_exists("SELECT 1 FROM sqlite_master"
91
+ " WHERE name='user' AND sql GLOB '* mtime *'");
92
+ if( rc==0 ){
93
+ db_multi_exec(
94
+ "CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
95
+ "DROP TABLE user;"
96
+ "CREATE TABLE user(\n"
97
+ " uid INTEGER PRIMARY KEY,\n"
98
+ " login TEXT UNIQUE,\n"
99
+ " pw TEXT,\n"
100
+ " cap TEXT,\n"
101
+ " cookie TEXT,\n"
102
+ " ipaddr TEXT,\n"
103
+ " cexpire DATETIME,\n"
104
+ " info TEXT,\n"
105
+ " mtime DATE,\n"
106
+ " photo BLOB\n"
107
+ ");"
108
+ "INSERT OR IGNORE INTO user"
109
+ " SELECT uid, login, pw, cap, cookie,"
110
+ " ipaddr, cexpire, info, now(), photo FROM temp_user;"
111
+ "DROP TABLE temp_user;"
112
+ );
113
+ }
114
+
115
+ rc = db_exists("SELECT 1 FROM sqlite_master"
116
+ " WHERE name='config' AND sql GLOB '* mtime *'");
117
+ if( rc==0 ){
118
+ db_multi_exec(
119
+ "ALTER TABLE config ADD COLUMN mtime INTEGER;"
120
+ "UPDATE config SET mtime=now();"
121
+ );
122
+ }
123
+
124
+ rc = db_exists("SELECT 1 FROM sqlite_master"
125
+ " WHERE name='shun' AND sql GLOB '* mtime *'");
126
+ if( rc==0 ){
127
+ db_multi_exec(
128
+ "ALTER TABLE shun ADD COLUMN mtime INTEGER;"
129
+ "ALTER TABLE shun ADD COLUMN scom TEXT;"
130
+ "UPDATE shun SET mtime=now();"
131
+ );
132
+ }
133
+
134
+ rc = db_exists("SELECT 1 FROM sqlite_master"
135
+ " WHERE name='reportfmt' AND sql GLOB '* mtime *'");
136
+ if( rc==0 ){
137
+ db_multi_exec(
138
+ "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
139
+ "DROP TABLE reportfmt;"
140
+ );
141
+ db_multi_exec(zSchemaUpdates2);
142
+ db_multi_exec(
143
+ "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
144
+ " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;"
145
+ "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
146
+ " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()"
147
+ " FROM old_fmt;"
148
+ );
149
+ }
150
+
151
+ rc = db_exists("SELECT 1 FROM sqlite_master"
152
+ " WHERE name='concealed' AND sql GLOB '* mtime *'");
153
+ if( rc==0 ){
154
+ db_multi_exec(
155
+ "ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
156
+ "UPDATE concealed SET mtime=now();"
157
+ );
158
+ }
159
+}
75160
76161
/*
77162
** Variables used to store state information about an on-going "rebuild"
78163
** or "deconstruct".
79164
*/
@@ -91,11 +176,11 @@
91176
** The input is actually the permill complete.
92177
*/
93178
static void percent_complete(int permill){
94179
static int lastOutput = -1;
95180
if( permill>lastOutput ){
96
- printf(" %d.%d%% complete...\r", permill/10, permill%10);
181
+ fossil_print(" %d.%d%% complete...\r", permill/10, permill%10);
97182
fflush(stdout);
98183
lastOutput = permill;
99184
}
100185
}
101186
@@ -256,11 +341,11 @@
256341
ttyOutput = doOut;
257342
processCnt = 0;
258343
if (!g.fQuiet) {
259344
percent_complete(0);
260345
}
261
- db_multi_exec(zSchemaUpdates);
346
+ rebuild_update_schema();
262347
for(;;){
263348
zTable = db_text(0,
264349
"SELECT name FROM sqlite_master /*scan*/"
265350
" WHERE type='table'"
266351
" AND name NOT IN ('blob','delta','rcvfrom','user',"
@@ -335,11 +420,11 @@
335420
if( !g.fQuiet && totalSize>0 ){
336421
processCnt += incrSize;
337422
percent_complete((processCnt*1000)/totalSize);
338423
}
339424
if(!g.fQuiet && ttyOutput ){
340
- printf("\n");
425
+ fossil_print("\n");
341426
}
342427
return errCnt;
343428
}
344429
345430
/*
@@ -459,37 +544,39 @@
459544
}
460545
db_begin_transaction();
461546
ttyOutput = 1;
462547
errCnt = rebuild_db(randomizeFlag, 1, doClustering);
463548
db_multi_exec(
464
- "REPLACE INTO config(name,value) VALUES('content-schema','%s');"
465
- "REPLACE INTO config(name,value) VALUES('aux-schema','%s');",
549
+ "REPLACE INTO config(name,value,mtime) VALUES('content-schema','%s',now());"
550
+ "REPLACE INTO config(name,value,mtime) VALUES('aux-schema','%s',now());",
466551
CONTENT_SCHEMA, AUX_SCHEMA
467552
);
468553
if( errCnt && !forceFlag ){
469
- printf("%d errors. Rolling back changes. Use --force to force a commit.\n",
470
- errCnt);
554
+ fossil_print(
555
+ "%d errors. Rolling back changes. Use --force to force a commit.\n",
556
+ errCnt
557
+ );
471558
db_end_transaction(1);
472559
}else{
473560
if( runCompress ){
474
- printf("Extra delta compression... "); fflush(stdout);
561
+ fossil_print("Extra delta compression... "); fflush(stdout);
475562
extra_deltification();
476563
runVacuum = 1;
477564
}
478565
if( omitVerify ) verify_cancel();
479566
db_end_transaction(0);
480
- if( runCompress ) printf("done\n");
567
+ if( runCompress ) fossil_print("done\n");
481568
db_close(0);
482569
db_open_repository(g.zRepositoryName);
483570
if( newPagesize ){
484571
db_multi_exec("PRAGMA page_size=%d", newPagesize);
485572
runVacuum = 1;
486573
}
487574
if( runVacuum ){
488
- printf("Vacuuming the database... "); fflush(stdout);
575
+ fossil_print("Vacuuming the database... "); fflush(stdout);
489576
db_multi_exec("VACUUM");
490
- printf("done\n");
577
+ fossil_print("done\n");
491578
}
492579
if( activateWal ){
493580
db_multi_exec("PRAGMA journal_mode=WAL;");
494581
}
495582
}
@@ -593,16 +680,16 @@
593680
manifest_destroy(p);
594681
}
595682
n = db_int(0, "SELECT count(*) FROM /*scan*/"
596683
" (SELECT rid FROM blob EXCEPT SELECT x FROM xdone)");
597684
if( n==0 ){
598
- printf("all artifacts reachable through clusters\n");
685
+ fossil_print("all artifacts reachable through clusters\n");
599686
}else{
600
- printf("%d unreachable artifacts:\n", n);
687
+ fossil_print("%d unreachable artifacts:\n", n);
601688
db_prepare(&q, "SELECT rid, uuid FROM blob WHERE rid NOT IN xdone");
602689
while( db_step(&q)==SQLITE_ROW ){
603
- printf(" %3d %s\n", db_column_int(&q,0), db_column_text(&q,1));
690
+ fossil_print(" %3d %s\n", db_column_int(&q,0), db_column_text(&q,1));
604691
}
605692
db_finalize(&q);
606693
}
607694
}
608695
@@ -712,11 +799,11 @@
712799
}
713800
content_put(&aContent);
714801
blob_reset(&path);
715802
blob_reset(&aContent);
716803
free(zSubpath);
717
- printf("\r%d", ++nFileRead);
804
+ fossil_print("\r%d", ++nFileRead);
718805
fflush(stdout);
719806
}
720807
closedir(d);
721808
}else {
722809
fossil_panic("encountered error %d while trying to open \"%s\".",
@@ -739,22 +826,22 @@
739826
char *zPassword;
740827
if( g.argc!=4 ){
741828
usage("FILENAME DIRECTORY");
742829
}
743830
if( file_isdir(g.argv[3])!=1 ){
744
- printf("\"%s\" is not a directory\n\n", g.argv[3]);
831
+ fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
745832
usage("FILENAME DIRECTORY");
746833
}
747834
db_create_repository(g.argv[2]);
748835
db_open_repository(g.argv[2]);
749836
db_open_config(0);
750837
db_begin_transaction();
751838
db_initial_setup(0, 0, 1);
752839
753
- printf("Reading files from directory \"%s\"...\n", g.argv[3]);
840
+ fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
754841
recon_read_dir(g.argv[3]);
755
- printf("\nBuilding the Fossil repository...\n");
842
+ fossil_print("\nBuilding the Fossil repository...\n");
756843
757844
rebuild_db(0, 1, 1);
758845
759846
/* Reconstruct the private table. The private table contains the rid
760847
** of every manifest that is tagged with "private" and every file that
@@ -776,14 +863,14 @@
776863
** long time.
777864
*/
778865
verify_cancel();
779866
780867
db_end_transaction(0);
781
- printf("project-id: %s\n", db_get("project-code", 0));
782
- printf("server-id: %s\n", db_get("server-code", 0));
868
+ fossil_print("project-id: %s\n", db_get("project-code", 0));
869
+ fossil_print("server-id: %s\n", db_get("server-code", 0));
783870
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
784
- printf("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
871
+ fossil_print("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
785872
}
786873
787874
/*
788875
** COMMAND: deconstruct
789876
**
@@ -824,11 +911,11 @@
824911
}else{
825912
fossil_fatal("N(%s) is not a a valid prefix length!",zPrefixOpt);
826913
}
827914
}
828915
#ifndef _WIN32
829
- if( access(zDestDir, W_OK) ){
916
+ if( file_access(zDestDir, W_OK) ){
830917
fossil_fatal("DESTINATION(%s) is not writeable!",zDestDir);
831918
}
832919
#else
833920
/* write access on windows is not checked, errors will be
834921
** dected on blob_write_to_file
@@ -843,11 +930,11 @@
843930
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
844931
bag_init(&bagDone);
845932
ttyOutput = 1;
846933
processCnt = 0;
847934
if (!g.fQuiet) {
848
- printf("0 (0%%)...\r");
935
+ fossil_print("0 (0%%)...\r");
849936
fflush(stdout);
850937
}
851938
totalSize = db_int(0, "SELECT count(*) FROM blob");
852939
db_prepare(&s,
853940
"SELECT rid, size FROM blob /*scan*/"
@@ -879,12 +966,12 @@
879966
}
880967
}
881968
}
882969
db_finalize(&s);
883970
if(!g.fQuiet && ttyOutput ){
884
- printf("\n");
971
+ fossil_print("\n");
885972
}
886973
887974
/* free filename format string */
888975
free(zFNameFormat);
889976
zFNameFormat = 0;
890977
}
891978
--- src/rebuild.c
+++ src/rebuild.c
@@ -22,13 +22,15 @@
22 #include <assert.h>
23 #include <dirent.h>
24 #include <errno.h>
25
26 /*
27 ** Schema changes
 
 
28 */
29 static const char zSchemaUpdates[] =
30 @ -- Index on the delta table
31 @ --
32 @ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid);
33 @
34 @ -- Artifacts that should not be processed are identified in the
@@ -39,41 +41,124 @@
39 @ --
40 @ -- Shunned artifacts do not exist in the blob table. Hence they
41 @ -- have not artifact ID (rid) and we thus must store their full
42 @ -- UUID.
43 @ --
44 @ CREATE TABLE IF NOT EXISTS shun(uuid UNIQUE);
 
 
 
 
45 @
46 @ -- Artifacts that should not be pushed are stored in the "private"
47 @ -- table.
48 @ --
49 @ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
50 @
51 @ -- An entry in this table describes a database query that generates a
52 @ -- table of tickets.
53 @ --
54 @ CREATE TABLE IF NOT EXISTS reportfmt(
55 @ rn integer primary key, -- Report number
56 @ owner text, -- Owner of this report format (not used)
57 @ title text, -- Title of this report
58 @ cols text, -- A color-key specification
59 @ sqlcode text -- An SQL SELECT statement for this report
60 @ );
61 @
62 @ -- Some ticket content (such as the originators email address or contact
63 @ -- information) needs to be obscured to protect privacy. This is achieved
64 @ -- by storing an SHA1 hash of the content. For display, the hash is
65 @ -- mapped back into the original text using this table.
66 @ --
67 @ -- This table contains sensitive information and should not be shared
68 @ -- with unauthorized users.
69 @ --
70 @ CREATE TABLE IF NOT EXISTS concealed(
71 @ hash TEXT PRIMARY KEY,
72 @ content TEXT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73 @ );
74 ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
76 /*
77 ** Variables used to store state information about an on-going "rebuild"
78 ** or "deconstruct".
79 */
@@ -91,11 +176,11 @@
91 ** The input is actually the permill complete.
92 */
93 static void percent_complete(int permill){
94 static int lastOutput = -1;
95 if( permill>lastOutput ){
96 printf(" %d.%d%% complete...\r", permill/10, permill%10);
97 fflush(stdout);
98 lastOutput = permill;
99 }
100 }
101
@@ -256,11 +341,11 @@
256 ttyOutput = doOut;
257 processCnt = 0;
258 if (!g.fQuiet) {
259 percent_complete(0);
260 }
261 db_multi_exec(zSchemaUpdates);
262 for(;;){
263 zTable = db_text(0,
264 "SELECT name FROM sqlite_master /*scan*/"
265 " WHERE type='table'"
266 " AND name NOT IN ('blob','delta','rcvfrom','user',"
@@ -335,11 +420,11 @@
335 if( !g.fQuiet && totalSize>0 ){
336 processCnt += incrSize;
337 percent_complete((processCnt*1000)/totalSize);
338 }
339 if(!g.fQuiet && ttyOutput ){
340 printf("\n");
341 }
342 return errCnt;
343 }
344
345 /*
@@ -459,37 +544,39 @@
459 }
460 db_begin_transaction();
461 ttyOutput = 1;
462 errCnt = rebuild_db(randomizeFlag, 1, doClustering);
463 db_multi_exec(
464 "REPLACE INTO config(name,value) VALUES('content-schema','%s');"
465 "REPLACE INTO config(name,value) VALUES('aux-schema','%s');",
466 CONTENT_SCHEMA, AUX_SCHEMA
467 );
468 if( errCnt && !forceFlag ){
469 printf("%d errors. Rolling back changes. Use --force to force a commit.\n",
470 errCnt);
 
 
471 db_end_transaction(1);
472 }else{
473 if( runCompress ){
474 printf("Extra delta compression... "); fflush(stdout);
475 extra_deltification();
476 runVacuum = 1;
477 }
478 if( omitVerify ) verify_cancel();
479 db_end_transaction(0);
480 if( runCompress ) printf("done\n");
481 db_close(0);
482 db_open_repository(g.zRepositoryName);
483 if( newPagesize ){
484 db_multi_exec("PRAGMA page_size=%d", newPagesize);
485 runVacuum = 1;
486 }
487 if( runVacuum ){
488 printf("Vacuuming the database... "); fflush(stdout);
489 db_multi_exec("VACUUM");
490 printf("done\n");
491 }
492 if( activateWal ){
493 db_multi_exec("PRAGMA journal_mode=WAL;");
494 }
495 }
@@ -593,16 +680,16 @@
593 manifest_destroy(p);
594 }
595 n = db_int(0, "SELECT count(*) FROM /*scan*/"
596 " (SELECT rid FROM blob EXCEPT SELECT x FROM xdone)");
597 if( n==0 ){
598 printf("all artifacts reachable through clusters\n");
599 }else{
600 printf("%d unreachable artifacts:\n", n);
601 db_prepare(&q, "SELECT rid, uuid FROM blob WHERE rid NOT IN xdone");
602 while( db_step(&q)==SQLITE_ROW ){
603 printf(" %3d %s\n", db_column_int(&q,0), db_column_text(&q,1));
604 }
605 db_finalize(&q);
606 }
607 }
608
@@ -712,11 +799,11 @@
712 }
713 content_put(&aContent);
714 blob_reset(&path);
715 blob_reset(&aContent);
716 free(zSubpath);
717 printf("\r%d", ++nFileRead);
718 fflush(stdout);
719 }
720 closedir(d);
721 }else {
722 fossil_panic("encountered error %d while trying to open \"%s\".",
@@ -739,22 +826,22 @@
739 char *zPassword;
740 if( g.argc!=4 ){
741 usage("FILENAME DIRECTORY");
742 }
743 if( file_isdir(g.argv[3])!=1 ){
744 printf("\"%s\" is not a directory\n\n", g.argv[3]);
745 usage("FILENAME DIRECTORY");
746 }
747 db_create_repository(g.argv[2]);
748 db_open_repository(g.argv[2]);
749 db_open_config(0);
750 db_begin_transaction();
751 db_initial_setup(0, 0, 1);
752
753 printf("Reading files from directory \"%s\"...\n", g.argv[3]);
754 recon_read_dir(g.argv[3]);
755 printf("\nBuilding the Fossil repository...\n");
756
757 rebuild_db(0, 1, 1);
758
759 /* Reconstruct the private table. The private table contains the rid
760 ** of every manifest that is tagged with "private" and every file that
@@ -776,14 +863,14 @@
776 ** long time.
777 */
778 verify_cancel();
779
780 db_end_transaction(0);
781 printf("project-id: %s\n", db_get("project-code", 0));
782 printf("server-id: %s\n", db_get("server-code", 0));
783 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
784 printf("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
785 }
786
787 /*
788 ** COMMAND: deconstruct
789 **
@@ -824,11 +911,11 @@
824 }else{
825 fossil_fatal("N(%s) is not a a valid prefix length!",zPrefixOpt);
826 }
827 }
828 #ifndef _WIN32
829 if( access(zDestDir, W_OK) ){
830 fossil_fatal("DESTINATION(%s) is not writeable!",zDestDir);
831 }
832 #else
833 /* write access on windows is not checked, errors will be
834 ** dected on blob_write_to_file
@@ -843,11 +930,11 @@
843 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
844 bag_init(&bagDone);
845 ttyOutput = 1;
846 processCnt = 0;
847 if (!g.fQuiet) {
848 printf("0 (0%%)...\r");
849 fflush(stdout);
850 }
851 totalSize = db_int(0, "SELECT count(*) FROM blob");
852 db_prepare(&s,
853 "SELECT rid, size FROM blob /*scan*/"
@@ -879,12 +966,12 @@
879 }
880 }
881 }
882 db_finalize(&s);
883 if(!g.fQuiet && ttyOutput ){
884 printf("\n");
885 }
886
887 /* free filename format string */
888 free(zFNameFormat);
889 zFNameFormat = 0;
890 }
891
--- src/rebuild.c
+++ src/rebuild.c
@@ -22,13 +22,15 @@
22 #include <assert.h>
23 #include <dirent.h>
24 #include <errno.h>
25
26 /*
27 ** Make changes to the stable part of the schema (the part that is not
28 ** simply deleted and reconstructed on a rebuild) to bring the schema
29 ** up to the latest.
30 */
31 static const char zSchemaUpdates1[] =
32 @ -- Index on the delta table
33 @ --
34 @ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid);
35 @
36 @ -- Artifacts that should not be processed are identified in the
@@ -39,41 +41,124 @@
41 @ --
42 @ -- Shunned artifacts do not exist in the blob table. Hence they
43 @ -- have not artifact ID (rid) and we thus must store their full
44 @ -- UUID.
45 @ --
46 @ CREATE TABLE IF NOT EXISTS shun(
47 @ uuid UNIQUE, -- UUID of artifact to be shunned. Canonical form
48 @ mtime INTEGER, -- When added. Seconds since 1970
49 @ scom TEXT -- Optional text explaining why the shun occurred
50 @ );
51 @
52 @ -- Artifacts that should not be pushed are stored in the "private"
53 @ -- table.
54 @ --
55 @ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
56 @
 
 
 
 
 
 
 
 
 
 
 
57 @ -- Some ticket content (such as the originators email address or contact
58 @ -- information) needs to be obscured to protect privacy. This is achieved
59 @ -- by storing an SHA1 hash of the content. For display, the hash is
60 @ -- mapped back into the original text using this table.
61 @ --
62 @ -- This table contains sensitive information and should not be shared
63 @ -- with unauthorized users.
64 @ --
65 @ CREATE TABLE IF NOT EXISTS concealed(
66 @ hash TEXT PRIMARY KEY, -- The SHA1 hash of content
67 @ mtime INTEGER, -- Time created. Seconds since 1970
68 @ content TEXT -- Content intended to be concealed
69 @ );
70 ;
71 static const char zSchemaUpdates2[] =
72 @ -- An entry in this table describes a database query that generates a
73 @ -- table of tickets.
74 @ --
75 @ CREATE TABLE IF NOT EXISTS reportfmt(
76 @ rn INTEGER PRIMARY KEY, -- Report number
77 @ owner TEXT, -- Owner of this report format (not used)
78 @ title TEXT UNIQUE, -- Title of this report
79 @ mtime INTEGER, -- Time last modified. Seconds since 1970
80 @ cols TEXT, -- A color-key specification
81 @ sqlcode TEXT -- An SQL SELECT statement for this report
82 @ );
83 ;
84
85 static void rebuild_update_schema(void){
86 int rc;
87 db_multi_exec(zSchemaUpdates1);
88 db_multi_exec(zSchemaUpdates2);
89
90 rc = db_exists("SELECT 1 FROM sqlite_master"
91 " WHERE name='user' AND sql GLOB '* mtime *'");
92 if( rc==0 ){
93 db_multi_exec(
94 "CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
95 "DROP TABLE user;"
96 "CREATE TABLE user(\n"
97 " uid INTEGER PRIMARY KEY,\n"
98 " login TEXT UNIQUE,\n"
99 " pw TEXT,\n"
100 " cap TEXT,\n"
101 " cookie TEXT,\n"
102 " ipaddr TEXT,\n"
103 " cexpire DATETIME,\n"
104 " info TEXT,\n"
105 " mtime DATE,\n"
106 " photo BLOB\n"
107 ");"
108 "INSERT OR IGNORE INTO user"
109 " SELECT uid, login, pw, cap, cookie,"
110 " ipaddr, cexpire, info, now(), photo FROM temp_user;"
111 "DROP TABLE temp_user;"
112 );
113 }
114
115 rc = db_exists("SELECT 1 FROM sqlite_master"
116 " WHERE name='config' AND sql GLOB '* mtime *'");
117 if( rc==0 ){
118 db_multi_exec(
119 "ALTER TABLE config ADD COLUMN mtime INTEGER;"
120 "UPDATE config SET mtime=now();"
121 );
122 }
123
124 rc = db_exists("SELECT 1 FROM sqlite_master"
125 " WHERE name='shun' AND sql GLOB '* mtime *'");
126 if( rc==0 ){
127 db_multi_exec(
128 "ALTER TABLE shun ADD COLUMN mtime INTEGER;"
129 "ALTER TABLE shun ADD COLUMN scom TEXT;"
130 "UPDATE shun SET mtime=now();"
131 );
132 }
133
134 rc = db_exists("SELECT 1 FROM sqlite_master"
135 " WHERE name='reportfmt' AND sql GLOB '* mtime *'");
136 if( rc==0 ){
137 db_multi_exec(
138 "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
139 "DROP TABLE reportfmt;"
140 );
141 db_multi_exec(zSchemaUpdates2);
142 db_multi_exec(
143 "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
144 " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;"
145 "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
146 " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()"
147 " FROM old_fmt;"
148 );
149 }
150
151 rc = db_exists("SELECT 1 FROM sqlite_master"
152 " WHERE name='concealed' AND sql GLOB '* mtime *'");
153 if( rc==0 ){
154 db_multi_exec(
155 "ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
156 "UPDATE concealed SET mtime=now();"
157 );
158 }
159 }
160
161 /*
162 ** Variables used to store state information about an on-going "rebuild"
163 ** or "deconstruct".
164 */
@@ -91,11 +176,11 @@
176 ** The input is actually the permill complete.
177 */
178 static void percent_complete(int permill){
179 static int lastOutput = -1;
180 if( permill>lastOutput ){
181 fossil_print(" %d.%d%% complete...\r", permill/10, permill%10);
182 fflush(stdout);
183 lastOutput = permill;
184 }
185 }
186
@@ -256,11 +341,11 @@
341 ttyOutput = doOut;
342 processCnt = 0;
343 if (!g.fQuiet) {
344 percent_complete(0);
345 }
346 rebuild_update_schema();
347 for(;;){
348 zTable = db_text(0,
349 "SELECT name FROM sqlite_master /*scan*/"
350 " WHERE type='table'"
351 " AND name NOT IN ('blob','delta','rcvfrom','user',"
@@ -335,11 +420,11 @@
420 if( !g.fQuiet && totalSize>0 ){
421 processCnt += incrSize;
422 percent_complete((processCnt*1000)/totalSize);
423 }
424 if(!g.fQuiet && ttyOutput ){
425 fossil_print("\n");
426 }
427 return errCnt;
428 }
429
430 /*
@@ -459,37 +544,39 @@
544 }
545 db_begin_transaction();
546 ttyOutput = 1;
547 errCnt = rebuild_db(randomizeFlag, 1, doClustering);
548 db_multi_exec(
549 "REPLACE INTO config(name,value,mtime) VALUES('content-schema','%s',now());"
550 "REPLACE INTO config(name,value,mtime) VALUES('aux-schema','%s',now());",
551 CONTENT_SCHEMA, AUX_SCHEMA
552 );
553 if( errCnt && !forceFlag ){
554 fossil_print(
555 "%d errors. Rolling back changes. Use --force to force a commit.\n",
556 errCnt
557 );
558 db_end_transaction(1);
559 }else{
560 if( runCompress ){
561 fossil_print("Extra delta compression... "); fflush(stdout);
562 extra_deltification();
563 runVacuum = 1;
564 }
565 if( omitVerify ) verify_cancel();
566 db_end_transaction(0);
567 if( runCompress ) fossil_print("done\n");
568 db_close(0);
569 db_open_repository(g.zRepositoryName);
570 if( newPagesize ){
571 db_multi_exec("PRAGMA page_size=%d", newPagesize);
572 runVacuum = 1;
573 }
574 if( runVacuum ){
575 fossil_print("Vacuuming the database... "); fflush(stdout);
576 db_multi_exec("VACUUM");
577 fossil_print("done\n");
578 }
579 if( activateWal ){
580 db_multi_exec("PRAGMA journal_mode=WAL;");
581 }
582 }
@@ -593,16 +680,16 @@
680 manifest_destroy(p);
681 }
682 n = db_int(0, "SELECT count(*) FROM /*scan*/"
683 " (SELECT rid FROM blob EXCEPT SELECT x FROM xdone)");
684 if( n==0 ){
685 fossil_print("all artifacts reachable through clusters\n");
686 }else{
687 fossil_print("%d unreachable artifacts:\n", n);
688 db_prepare(&q, "SELECT rid, uuid FROM blob WHERE rid NOT IN xdone");
689 while( db_step(&q)==SQLITE_ROW ){
690 fossil_print(" %3d %s\n", db_column_int(&q,0), db_column_text(&q,1));
691 }
692 db_finalize(&q);
693 }
694 }
695
@@ -712,11 +799,11 @@
799 }
800 content_put(&aContent);
801 blob_reset(&path);
802 blob_reset(&aContent);
803 free(zSubpath);
804 fossil_print("\r%d", ++nFileRead);
805 fflush(stdout);
806 }
807 closedir(d);
808 }else {
809 fossil_panic("encountered error %d while trying to open \"%s\".",
@@ -739,22 +826,22 @@
826 char *zPassword;
827 if( g.argc!=4 ){
828 usage("FILENAME DIRECTORY");
829 }
830 if( file_isdir(g.argv[3])!=1 ){
831 fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
832 usage("FILENAME DIRECTORY");
833 }
834 db_create_repository(g.argv[2]);
835 db_open_repository(g.argv[2]);
836 db_open_config(0);
837 db_begin_transaction();
838 db_initial_setup(0, 0, 1);
839
840 fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
841 recon_read_dir(g.argv[3]);
842 fossil_print("\nBuilding the Fossil repository...\n");
843
844 rebuild_db(0, 1, 1);
845
846 /* Reconstruct the private table. The private table contains the rid
847 ** of every manifest that is tagged with "private" and every file that
@@ -776,14 +863,14 @@
863 ** long time.
864 */
865 verify_cancel();
866
867 db_end_transaction(0);
868 fossil_print("project-id: %s\n", db_get("project-code", 0));
869 fossil_print("server-id: %s\n", db_get("server-code", 0));
870 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
871 fossil_print("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
872 }
873
874 /*
875 ** COMMAND: deconstruct
876 **
@@ -824,11 +911,11 @@
911 }else{
912 fossil_fatal("N(%s) is not a a valid prefix length!",zPrefixOpt);
913 }
914 }
915 #ifndef _WIN32
916 if( file_access(zDestDir, W_OK) ){
917 fossil_fatal("DESTINATION(%s) is not writeable!",zDestDir);
918 }
919 #else
920 /* write access on windows is not checked, errors will be
921 ** dected on blob_write_to_file
@@ -843,11 +930,11 @@
930 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
931 bag_init(&bagDone);
932 ttyOutput = 1;
933 processCnt = 0;
934 if (!g.fQuiet) {
935 fossil_print("0 (0%%)...\r");
936 fflush(stdout);
937 }
938 totalSize = db_int(0, "SELECT count(*) FROM blob");
939 db_prepare(&s,
940 "SELECT rid, size FROM blob /*scan*/"
@@ -879,12 +966,12 @@
966 }
967 }
968 }
969 db_finalize(&s);
970 if(!g.fQuiet && ttyOutput ){
971 fossil_print("\n");
972 }
973
974 /* free filename format string */
975 free(zFNameFormat);
976 zFNameFormat = 0;
977 }
978
+18 -12
--- src/report.c
+++ src/report.c
@@ -360,19 +360,25 @@
360360
}else if( (zTitle = trim_string(zTitle))[0]==0 ){
361361
zErr = "Please supply a title";
362362
}else{
363363
zErr = verify_sql_statement(zSQL);
364364
}
365
+ if( zErr==0
366
+ && db_exists("SELECT 1 FROM reportfmt WHERE title=%Q and rn<>%d",
367
+ zTitle, rn)
368
+ ){
369
+ zErr = mprintf("There is already another report named \"%h\"", zTitle);
370
+ }
365371
if( zErr==0 ){
366372
login_verify_csrf_secret();
367373
if( rn>0 ){
368374
db_multi_exec("UPDATE reportfmt SET title=%Q, sqlcode=%Q,"
369
- " owner=%Q, cols=%Q WHERE rn=%d",
375
+ " owner=%Q, cols=%Q, mtime=now() WHERE rn=%d",
370376
zTitle, zSQL, zOwner, zClrKey, rn);
371377
}else{
372
- db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols) "
373
- "VALUES(%Q,%Q,%Q,%Q)",
378
+ db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols,mtime) "
379
+ "VALUES(%Q,%Q,%Q,%Q,now())",
374380
zTitle, zSQL, zOwner, zClrKey);
375381
rn = db_last_insert_rowid();
376382
}
377383
cgi_redirect(mprintf("rptview?rn=%d", rn));
378384
return;
@@ -994,19 +1000,19 @@
9941000
*/
9951001
void rpt_list_reports(void){
9961002
Stmt q;
9971003
char const aRptOutFrmt[] = "%s\t%s\n";
9981004
999
- printf("Available reports:\n");
1000
- printf(aRptOutFrmt,"report number","report title");
1001
- printf(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
1005
+ fossil_print("Available reports:\n");
1006
+ fossil_print(aRptOutFrmt,"report number","report title");
1007
+ fossil_print(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
10021008
db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
10031009
while( db_step(&q)==SQLITE_ROW ){
10041010
const char *zRn = db_column_text(&q, 0);
10051011
const char *zTitle = db_column_text(&q, 1);
10061012
1007
- printf(aRptOutFrmt,zRn,zTitle);
1013
+ fossil_print(aRptOutFrmt,zRn,zTitle);
10081014
}
10091015
db_finalize(&q);
10101016
}
10111017
10121018
/*
@@ -1031,25 +1037,25 @@
10311037
case tktFossilize:
10321038
{ char *zFosZ;
10331039
10341040
if( z && *z ){
10351041
zFosZ = fossilize(z,-1);
1036
- printf("%s",zFosZ);
1042
+ fossil_print("%s",zFosZ);
10371043
free(zFosZ);
10381044
}
10391045
break;
10401046
}
10411047
default:
10421048
while( z && z[0] ){
10431049
int i, j;
10441050
for(i=0; z[i] && (!fossil_isspace(z[i]) || z[i]==' '); i++){}
10451051
if( i>0 ){
1046
- printf("%.*s", i, z);
1052
+ fossil_print("%.*s", i, z);
10471053
}
10481054
for(j=i; fossil_isspace(z[j]); j++){}
10491055
if( j>i ){
1050
- printf("%*s", j-i, "");
1056
+ fossil_print("%*s", j-i, "");
10511057
}
10521058
z += j;
10531059
}
10541060
break;
10551061
}
@@ -1068,17 +1074,17 @@
10681074
int i;
10691075
10701076
if( *pCount==0 ){
10711077
for(i=0; i<nArg; i++){
10721078
output_no_tabs_file(azName[i]);
1073
- printf("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
1079
+ fossil_print("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
10741080
}
10751081
}
10761082
++*pCount;
10771083
for(i=0; i<nArg; i++){
10781084
output_no_tabs_file(azArg[i]);
1079
- printf("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
1085
+ fossil_print("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
10801086
}
10811087
return 0;
10821088
}
10831089
10841090
/*
10851091
--- src/report.c
+++ src/report.c
@@ -360,19 +360,25 @@
360 }else if( (zTitle = trim_string(zTitle))[0]==0 ){
361 zErr = "Please supply a title";
362 }else{
363 zErr = verify_sql_statement(zSQL);
364 }
 
 
 
 
 
 
365 if( zErr==0 ){
366 login_verify_csrf_secret();
367 if( rn>0 ){
368 db_multi_exec("UPDATE reportfmt SET title=%Q, sqlcode=%Q,"
369 " owner=%Q, cols=%Q WHERE rn=%d",
370 zTitle, zSQL, zOwner, zClrKey, rn);
371 }else{
372 db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols) "
373 "VALUES(%Q,%Q,%Q,%Q)",
374 zTitle, zSQL, zOwner, zClrKey);
375 rn = db_last_insert_rowid();
376 }
377 cgi_redirect(mprintf("rptview?rn=%d", rn));
378 return;
@@ -994,19 +1000,19 @@
994 */
995 void rpt_list_reports(void){
996 Stmt q;
997 char const aRptOutFrmt[] = "%s\t%s\n";
998
999 printf("Available reports:\n");
1000 printf(aRptOutFrmt,"report number","report title");
1001 printf(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
1002 db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
1003 while( db_step(&q)==SQLITE_ROW ){
1004 const char *zRn = db_column_text(&q, 0);
1005 const char *zTitle = db_column_text(&q, 1);
1006
1007 printf(aRptOutFrmt,zRn,zTitle);
1008 }
1009 db_finalize(&q);
1010 }
1011
1012 /*
@@ -1031,25 +1037,25 @@
1031 case tktFossilize:
1032 { char *zFosZ;
1033
1034 if( z && *z ){
1035 zFosZ = fossilize(z,-1);
1036 printf("%s",zFosZ);
1037 free(zFosZ);
1038 }
1039 break;
1040 }
1041 default:
1042 while( z && z[0] ){
1043 int i, j;
1044 for(i=0; z[i] && (!fossil_isspace(z[i]) || z[i]==' '); i++){}
1045 if( i>0 ){
1046 printf("%.*s", i, z);
1047 }
1048 for(j=i; fossil_isspace(z[j]); j++){}
1049 if( j>i ){
1050 printf("%*s", j-i, "");
1051 }
1052 z += j;
1053 }
1054 break;
1055 }
@@ -1068,17 +1074,17 @@
1068 int i;
1069
1070 if( *pCount==0 ){
1071 for(i=0; i<nArg; i++){
1072 output_no_tabs_file(azName[i]);
1073 printf("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
1074 }
1075 }
1076 ++*pCount;
1077 for(i=0; i<nArg; i++){
1078 output_no_tabs_file(azArg[i]);
1079 printf("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
1080 }
1081 return 0;
1082 }
1083
1084 /*
1085
--- src/report.c
+++ src/report.c
@@ -360,19 +360,25 @@
360 }else if( (zTitle = trim_string(zTitle))[0]==0 ){
361 zErr = "Please supply a title";
362 }else{
363 zErr = verify_sql_statement(zSQL);
364 }
365 if( zErr==0
366 && db_exists("SELECT 1 FROM reportfmt WHERE title=%Q and rn<>%d",
367 zTitle, rn)
368 ){
369 zErr = mprintf("There is already another report named \"%h\"", zTitle);
370 }
371 if( zErr==0 ){
372 login_verify_csrf_secret();
373 if( rn>0 ){
374 db_multi_exec("UPDATE reportfmt SET title=%Q, sqlcode=%Q,"
375 " owner=%Q, cols=%Q, mtime=now() WHERE rn=%d",
376 zTitle, zSQL, zOwner, zClrKey, rn);
377 }else{
378 db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols,mtime) "
379 "VALUES(%Q,%Q,%Q,%Q,now())",
380 zTitle, zSQL, zOwner, zClrKey);
381 rn = db_last_insert_rowid();
382 }
383 cgi_redirect(mprintf("rptview?rn=%d", rn));
384 return;
@@ -994,19 +1000,19 @@
1000 */
1001 void rpt_list_reports(void){
1002 Stmt q;
1003 char const aRptOutFrmt[] = "%s\t%s\n";
1004
1005 fossil_print("Available reports:\n");
1006 fossil_print(aRptOutFrmt,"report number","report title");
1007 fossil_print(aRptOutFrmt,zFullTicketRptRn,zFullTicketRptTitle);
1008 db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
1009 while( db_step(&q)==SQLITE_ROW ){
1010 const char *zRn = db_column_text(&q, 0);
1011 const char *zTitle = db_column_text(&q, 1);
1012
1013 fossil_print(aRptOutFrmt,zRn,zTitle);
1014 }
1015 db_finalize(&q);
1016 }
1017
1018 /*
@@ -1031,25 +1037,25 @@
1037 case tktFossilize:
1038 { char *zFosZ;
1039
1040 if( z && *z ){
1041 zFosZ = fossilize(z,-1);
1042 fossil_print("%s",zFosZ);
1043 free(zFosZ);
1044 }
1045 break;
1046 }
1047 default:
1048 while( z && z[0] ){
1049 int i, j;
1050 for(i=0; z[i] && (!fossil_isspace(z[i]) || z[i]==' '); i++){}
1051 if( i>0 ){
1052 fossil_print("%.*s", i, z);
1053 }
1054 for(j=i; fossil_isspace(z[j]); j++){}
1055 if( j>i ){
1056 fossil_print("%*s", j-i, "");
1057 }
1058 z += j;
1059 }
1060 break;
1061 }
@@ -1068,17 +1074,17 @@
1074 int i;
1075
1076 if( *pCount==0 ){
1077 for(i=0; i<nArg; i++){
1078 output_no_tabs_file(azName[i]);
1079 fossil_print("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
1080 }
1081 }
1082 ++*pCount;
1083 for(i=0; i<nArg; i++){
1084 output_no_tabs_file(azArg[i]);
1085 fossil_print("%s", i<nArg-1 ? (zSep?zSep:"\t") : "\n");
1086 }
1087 return 0;
1088 }
1089
1090 /*
1091
+41 -21
--- src/schema.c
+++ src/schema.c
@@ -39,12 +39,12 @@
3939
** changes. The aux tables have an arbitrary version number (typically
4040
** a date) which can change frequently. When the content schema changes,
4141
** we have to execute special procedures to update the schema. When
4242
** the aux schema changes, all we need to do is rebuild the database.
4343
*/
44
-#define CONTENT_SCHEMA "1"
45
-#define AUX_SCHEMA "2011-02-25 14:52"
44
+#define CONTENT_SCHEMA "2"
45
+#define AUX_SCHEMA "2011-04-25 19:50"
4646
4747
#endif /* INTERFACE */
4848
4949
5050
/*
@@ -51,21 +51,25 @@
5151
** The schema for a repository database.
5252
**
5353
** Schema1[] contains parts of the schema that are fixed and unchanging
5454
** across versions. Schema2[] contains parts of the schema that can
5555
** change from one version to the next. The information in Schema2[]
56
-** can be reconstructed from the information in Schema1[].
56
+** is reconstructed from the information in Schema1[] by the "rebuild"
57
+** operation.
5758
*/
5859
const char zRepositorySchema1[] =
5960
@ -- The BLOB and DELTA tables contain all records held in the repository.
6061
@ --
61
-@ -- The BLOB.CONTENT column is always compressed using libz. This
62
+@ -- The BLOB.CONTENT column is always compressed using zlib. This
6263
@ -- column might hold the full text of the record or it might hold
6364
@ -- a delta that is able to reconstruct the record from some other
6465
@ -- record. If BLOB.CONTENT holds a delta, then a DELTA table entry
6566
@ -- will exist for the record and that entry will point to another
6667
@ -- entry that holds the source of the delta. Deltas can be chained.
68
+@ --
69
+@ -- The blob and delta tables collectively hold the "global state" of
70
+@ -- a Fossil repository.
6771
@ --
6872
@ CREATE TABLE blob(
6973
@ rid INTEGER PRIMARY KEY, -- Record ID
7074
@ rcvid INTEGER, -- Origin of this record
7175
@ size INTEGER, -- Size of content. -1 for a phantom.
@@ -77,17 +81,24 @@
7781
@ rid INTEGER PRIMARY KEY, -- Record ID
7882
@ srcid INTEGER NOT NULL REFERENCES blob -- Record holding source document
7983
@ );
8084
@ CREATE INDEX delta_i1 ON delta(srcid);
8185
@
86
+@ -------------------------------------------------------------------------
87
+@ -- The BLOB and DELTA tables above hold the "global state" of a Fossil
88
+@ -- project; the stuff that is normally exchanged during "sync". The
89
+@ -- "local state" of a repository is contained in the remaining tables of
90
+@ -- the zRepositorySchema1 string.
91
+@ -------------------------------------------------------------------------
92
+@
8293
@ -- Whenever new blobs are received into the repository, an entry
8394
@ -- in this table records the source of the blob.
8495
@ --
8596
@ CREATE TABLE rcvfrom(
8697
@ rcvid INTEGER PRIMARY KEY, -- Received-From ID
8798
@ uid INTEGER REFERENCES user, -- User login
88
-@ mtime DATETIME, -- Time or receipt
99
+@ mtime DATETIME, -- Time of receipt. Julian day.
89100
@ nonce TEXT UNIQUE, -- Nonce used for login
90101
@ ipaddr TEXT -- Remote IP address. NULL for direct.
91102
@ );
92103
@
93104
@ -- Information about users
@@ -99,26 +110,28 @@
99110
@ -- hash based on the project-code, the user login, and the cleartext
100111
@ -- password.
101112
@ --
102113
@ CREATE TABLE user(
103114
@ uid INTEGER PRIMARY KEY, -- User ID
104
-@ login TEXT, -- login name of the user
115
+@ login TEXT UNIQUE, -- login name of the user
105116
@ pw TEXT, -- password
106117
@ cap TEXT, -- Capabilities of this user
107118
@ cookie TEXT, -- WWW login cookie
108119
@ ipaddr TEXT, -- IP address for which cookie is valid
109120
@ cexpire DATETIME, -- Time when cookie expires
110121
@ info TEXT, -- contact information
122
+@ mtime DATE, -- last change. seconds since 1970
111123
@ photo BLOB -- JPEG image of this user
112124
@ );
113125
@
114126
@ -- The VAR table holds miscellanous information about the repository.
115127
@ -- in the form of name-value pairs.
116128
@ --
117129
@ CREATE TABLE config(
118130
@ name TEXT PRIMARY KEY NOT NULL, -- Primary name of the entry
119131
@ value CLOB, -- Content of the named parameter
132
+@ mtime DATE, -- last modified. seconds since 1970
120133
@ CHECK( typeof(name)='text' AND length(name)>=1 )
121134
@ );
122135
@
123136
@ -- Artifacts that should not be processed are identified in the
124137
@ -- "shun" table. Artifacts that are control-file forgeries or
@@ -128,11 +141,15 @@
128141
@ --
129142
@ -- Shunned artifacts do not exist in the blob table. Hence they
130143
@ -- have not artifact ID (rid) and we thus must store their full
131144
@ -- UUID.
132145
@ --
133
-@ CREATE TABLE shun(uuid UNIQUE);
146
+@ CREATE TABLE shun(
147
+@ uuid UNIQUE, -- UUID of artifact to be shunned. Canonical form
148
+@ mtime DATE, -- When added. seconds since 1970
149
+@ scom TEXT -- Optional text explaining why the shun occurred
150
+@ );
134151
@
135152
@ -- Artifacts that should not be pushed are stored in the "private"
136153
@ -- table. Private artifacts are omitted from the "unclustered" and
137154
@ -- "unsent" tables.
138155
@ --
@@ -140,17 +157,19 @@
140157
@
141158
@ -- An entry in this table describes a database query that generates a
142159
@ -- table of tickets.
143160
@ --
144161
@ CREATE TABLE reportfmt(
145
-@ rn integer primary key, -- Report number
146
-@ owner text, -- Owner of this report format (not used)
147
-@ title text, -- Title of this report
148
-@ cols text, -- A color-key specification
149
-@ sqlcode text -- An SQL SELECT statement for this report
162
+@ rn INTEGER PRIMARY KEY, -- Report number
163
+@ owner TEXT, -- Owner of this report format (not used)
164
+@ title TEXT UNIQUE, -- Title of this report
165
+@ mtime DATE, -- Last modified. seconds since 1970
166
+@ cols TEXT, -- A color-key specification
167
+@ sqlcode TEXT -- An SQL SELECT statement for this report
150168
@ );
151
-@ INSERT INTO reportfmt(title,cols,sqlcode) VALUES('All Tickets','#ffffff Key:
169
+@ INSERT INTO reportfmt(title,mtime,cols,sqlcode)
170
+@ VALUES('All Tickets',julianday('1970-01-01'),'#ffffff Key:
152171
@ #f2dcdc Active
153172
@ #e8e8e8 Review
154173
@ #cfe8bd Fixed
155174
@ #bde5d6 Tested
156175
@ #cacae5 Deferred
@@ -176,12 +195,13 @@
176195
@ --
177196
@ -- This table contains sensitive information and should not be shared
178197
@ -- with unauthorized users.
179198
@ --
180199
@ CREATE TABLE concealed(
181
-@ hash TEXT PRIMARY KEY,
182
-@ content TEXT
200
+@ hash TEXT PRIMARY KEY, -- The SHA1 hash of content
201
+@ mtime DATE, -- Time created. Seconds since 1970
202
+@ content TEXT -- Content intended to be concealed
183203
@ );
184204
;
185205
186206
const char zRepositorySchema2[] =
187207
@ -- Filenames
@@ -214,11 +234,11 @@
214234
@ --
215235
@ CREATE TABLE plink(
216236
@ pid INTEGER REFERENCES blob, -- Parent manifest
217237
@ cid INTEGER REFERENCES blob, -- Child manifest
218238
@ isprim BOOLEAN, -- pid is the primary parent of cid
219
-@ mtime DATETIME, -- the date/time stamp on cid
239
+@ mtime DATETIME, -- the date/time stamp on cid. Julian day.
220240
@ UNIQUE(pid, cid)
221241
@ );
222242
@ CREATE INDEX plink_i2 ON plink(cid,pid);
223243
@
224244
@ -- A "leaf" checkin is a checkin that has no children in the same
@@ -232,11 +252,11 @@
232252
@
233253
@ -- Events used to generate a timeline
234254
@ --
235255
@ CREATE TABLE event(
236256
@ type TEXT, -- Type of event: 'ci', 'w', 'e', 't'
237
-@ mtime DATETIME, -- Date and time when the event occurs
257
+@ mtime DATETIME, -- Time of occurrence. Julian day.
238258
@ objid INTEGER PRIMARY KEY, -- Associated record ID
239259
@ tagid INTEGER, -- Associated ticket or wiki name tag
240260
@ uid INTEGER REFERENCES user, -- User who caused the event
241261
@ bgcolor TEXT, -- Color set by 'bgcolor' property
242262
@ euser TEXT, -- User set by 'user' property
@@ -319,11 +339,11 @@
319339
@ tagid INTEGER REFERENCES tag, -- The tag that added or removed
320340
@ tagtype INTEGER, -- 0:-,cancel 1:+,single 2:*,propagate
321341
@ srcid INTEGER REFERENCES blob, -- Artifact of tag. 0 for propagated tags
322342
@ origid INTEGER REFERENCES blob, -- check-in holding propagated tag
323343
@ value TEXT, -- Value of the tag. Might be NULL.
324
-@ mtime TIMESTAMP, -- Time of addition or removal
344
+@ mtime TIMESTAMP, -- Time of addition or removal. Julian day
325345
@ rid INTEGER REFERENCE blob, -- Artifact tag is applied to
326346
@ UNIQUE(rid, tagid)
327347
@ );
328348
@ CREATE INDEX tagxref_i1 ON tagxref(tagid, mtime);
329349
@
@@ -334,11 +354,11 @@
334354
@ --
335355
@ CREATE TABLE backlink(
336356
@ target TEXT, -- Where the hyperlink points to
337357
@ srctype INT, -- 0: check-in 1: ticket 2: wiki
338358
@ srcid INT, -- rid for checkin or wiki. tkt_id for ticket.
339
-@ mtime TIMESTAMP, -- time that the hyperlink was added
359
+@ mtime TIMESTAMP, -- time that the hyperlink was added. Julian day.
340360
@ UNIQUE(target, srctype, srcid)
341361
@ );
342362
@ CREATE INDEX backlink_src ON backlink(srcid, srctype);
343363
@
344364
@ -- Each attachment is an entry in the following table. Only
@@ -345,11 +365,11 @@
345365
@ -- the most recent attachment (identified by the D card) is saved.
346366
@ --
347367
@ CREATE TABLE attachment(
348368
@ attachid INTEGER PRIMARY KEY, -- Local id for this attachment
349369
@ isLatest BOOLEAN DEFAULT 0, -- True if this is the one to use
350
-@ mtime TIMESTAMP, -- Time when attachment last changed
370
+@ mtime TIMESTAMP, -- Last changed. Julian day.
351371
@ src TEXT, -- UUID of the attachment. NULL to delete
352372
@ target TEXT, -- Object attached to. Wikiname or Tkt UUID
353373
@ filename TEXT, -- Filename for the attachment
354374
@ comment TEXT, -- Comment associated with this attachment
355375
@ user TEXT -- Name of user adding attachment
@@ -443,11 +463,11 @@
443463
@ chnged INT DEFAULT 0, -- 0:unchnged 1:edited 2:m-chng 3:m-add
444464
@ deleted BOOLEAN DEFAULT 0, -- True if deleted
445465
@ isexe BOOLEAN, -- True if file should be executable
446466
@ rid INTEGER, -- Originally from this repository record
447467
@ mrid INTEGER, -- Based on this record due to a merge
448
-@ mtime INTEGER, -- Modification time of file on disk
468
+@ mtime INTEGER, -- Mtime of file on disk. sec since 1970
449469
@ pathname TEXT, -- Full pathname relative to root
450470
@ origname TEXT, -- Original pathname. NULL if unchanged
451471
@ UNIQUE(pathname,vid)
452472
@ );
453473
@
454474
--- src/schema.c
+++ src/schema.c
@@ -39,12 +39,12 @@
39 ** changes. The aux tables have an arbitrary version number (typically
40 ** a date) which can change frequently. When the content schema changes,
41 ** we have to execute special procedures to update the schema. When
42 ** the aux schema changes, all we need to do is rebuild the database.
43 */
44 #define CONTENT_SCHEMA "1"
45 #define AUX_SCHEMA "2011-02-25 14:52"
46
47 #endif /* INTERFACE */
48
49
50 /*
@@ -51,21 +51,25 @@
51 ** The schema for a repository database.
52 **
53 ** Schema1[] contains parts of the schema that are fixed and unchanging
54 ** across versions. Schema2[] contains parts of the schema that can
55 ** change from one version to the next. The information in Schema2[]
56 ** can be reconstructed from the information in Schema1[].
 
57 */
58 const char zRepositorySchema1[] =
59 @ -- The BLOB and DELTA tables contain all records held in the repository.
60 @ --
61 @ -- The BLOB.CONTENT column is always compressed using libz. This
62 @ -- column might hold the full text of the record or it might hold
63 @ -- a delta that is able to reconstruct the record from some other
64 @ -- record. If BLOB.CONTENT holds a delta, then a DELTA table entry
65 @ -- will exist for the record and that entry will point to another
66 @ -- entry that holds the source of the delta. Deltas can be chained.
 
 
 
67 @ --
68 @ CREATE TABLE blob(
69 @ rid INTEGER PRIMARY KEY, -- Record ID
70 @ rcvid INTEGER, -- Origin of this record
71 @ size INTEGER, -- Size of content. -1 for a phantom.
@@ -77,17 +81,24 @@
77 @ rid INTEGER PRIMARY KEY, -- Record ID
78 @ srcid INTEGER NOT NULL REFERENCES blob -- Record holding source document
79 @ );
80 @ CREATE INDEX delta_i1 ON delta(srcid);
81 @
 
 
 
 
 
 
 
82 @ -- Whenever new blobs are received into the repository, an entry
83 @ -- in this table records the source of the blob.
84 @ --
85 @ CREATE TABLE rcvfrom(
86 @ rcvid INTEGER PRIMARY KEY, -- Received-From ID
87 @ uid INTEGER REFERENCES user, -- User login
88 @ mtime DATETIME, -- Time or receipt
89 @ nonce TEXT UNIQUE, -- Nonce used for login
90 @ ipaddr TEXT -- Remote IP address. NULL for direct.
91 @ );
92 @
93 @ -- Information about users
@@ -99,26 +110,28 @@
99 @ -- hash based on the project-code, the user login, and the cleartext
100 @ -- password.
101 @ --
102 @ CREATE TABLE user(
103 @ uid INTEGER PRIMARY KEY, -- User ID
104 @ login TEXT, -- login name of the user
105 @ pw TEXT, -- password
106 @ cap TEXT, -- Capabilities of this user
107 @ cookie TEXT, -- WWW login cookie
108 @ ipaddr TEXT, -- IP address for which cookie is valid
109 @ cexpire DATETIME, -- Time when cookie expires
110 @ info TEXT, -- contact information
 
111 @ photo BLOB -- JPEG image of this user
112 @ );
113 @
114 @ -- The VAR table holds miscellanous information about the repository.
115 @ -- in the form of name-value pairs.
116 @ --
117 @ CREATE TABLE config(
118 @ name TEXT PRIMARY KEY NOT NULL, -- Primary name of the entry
119 @ value CLOB, -- Content of the named parameter
 
120 @ CHECK( typeof(name)='text' AND length(name)>=1 )
121 @ );
122 @
123 @ -- Artifacts that should not be processed are identified in the
124 @ -- "shun" table. Artifacts that are control-file forgeries or
@@ -128,11 +141,15 @@
128 @ --
129 @ -- Shunned artifacts do not exist in the blob table. Hence they
130 @ -- have not artifact ID (rid) and we thus must store their full
131 @ -- UUID.
132 @ --
133 @ CREATE TABLE shun(uuid UNIQUE);
 
 
 
 
134 @
135 @ -- Artifacts that should not be pushed are stored in the "private"
136 @ -- table. Private artifacts are omitted from the "unclustered" and
137 @ -- "unsent" tables.
138 @ --
@@ -140,17 +157,19 @@
140 @
141 @ -- An entry in this table describes a database query that generates a
142 @ -- table of tickets.
143 @ --
144 @ CREATE TABLE reportfmt(
145 @ rn integer primary key, -- Report number
146 @ owner text, -- Owner of this report format (not used)
147 @ title text, -- Title of this report
148 @ cols text, -- A color-key specification
149 @ sqlcode text -- An SQL SELECT statement for this report
 
150 @ );
151 @ INSERT INTO reportfmt(title,cols,sqlcode) VALUES('All Tickets','#ffffff Key:
 
152 @ #f2dcdc Active
153 @ #e8e8e8 Review
154 @ #cfe8bd Fixed
155 @ #bde5d6 Tested
156 @ #cacae5 Deferred
@@ -176,12 +195,13 @@
176 @ --
177 @ -- This table contains sensitive information and should not be shared
178 @ -- with unauthorized users.
179 @ --
180 @ CREATE TABLE concealed(
181 @ hash TEXT PRIMARY KEY,
182 @ content TEXT
 
183 @ );
184 ;
185
186 const char zRepositorySchema2[] =
187 @ -- Filenames
@@ -214,11 +234,11 @@
214 @ --
215 @ CREATE TABLE plink(
216 @ pid INTEGER REFERENCES blob, -- Parent manifest
217 @ cid INTEGER REFERENCES blob, -- Child manifest
218 @ isprim BOOLEAN, -- pid is the primary parent of cid
219 @ mtime DATETIME, -- the date/time stamp on cid
220 @ UNIQUE(pid, cid)
221 @ );
222 @ CREATE INDEX plink_i2 ON plink(cid,pid);
223 @
224 @ -- A "leaf" checkin is a checkin that has no children in the same
@@ -232,11 +252,11 @@
232 @
233 @ -- Events used to generate a timeline
234 @ --
235 @ CREATE TABLE event(
236 @ type TEXT, -- Type of event: 'ci', 'w', 'e', 't'
237 @ mtime DATETIME, -- Date and time when the event occurs
238 @ objid INTEGER PRIMARY KEY, -- Associated record ID
239 @ tagid INTEGER, -- Associated ticket or wiki name tag
240 @ uid INTEGER REFERENCES user, -- User who caused the event
241 @ bgcolor TEXT, -- Color set by 'bgcolor' property
242 @ euser TEXT, -- User set by 'user' property
@@ -319,11 +339,11 @@
319 @ tagid INTEGER REFERENCES tag, -- The tag that added or removed
320 @ tagtype INTEGER, -- 0:-,cancel 1:+,single 2:*,propagate
321 @ srcid INTEGER REFERENCES blob, -- Artifact of tag. 0 for propagated tags
322 @ origid INTEGER REFERENCES blob, -- check-in holding propagated tag
323 @ value TEXT, -- Value of the tag. Might be NULL.
324 @ mtime TIMESTAMP, -- Time of addition or removal
325 @ rid INTEGER REFERENCE blob, -- Artifact tag is applied to
326 @ UNIQUE(rid, tagid)
327 @ );
328 @ CREATE INDEX tagxref_i1 ON tagxref(tagid, mtime);
329 @
@@ -334,11 +354,11 @@
334 @ --
335 @ CREATE TABLE backlink(
336 @ target TEXT, -- Where the hyperlink points to
337 @ srctype INT, -- 0: check-in 1: ticket 2: wiki
338 @ srcid INT, -- rid for checkin or wiki. tkt_id for ticket.
339 @ mtime TIMESTAMP, -- time that the hyperlink was added
340 @ UNIQUE(target, srctype, srcid)
341 @ );
342 @ CREATE INDEX backlink_src ON backlink(srcid, srctype);
343 @
344 @ -- Each attachment is an entry in the following table. Only
@@ -345,11 +365,11 @@
345 @ -- the most recent attachment (identified by the D card) is saved.
346 @ --
347 @ CREATE TABLE attachment(
348 @ attachid INTEGER PRIMARY KEY, -- Local id for this attachment
349 @ isLatest BOOLEAN DEFAULT 0, -- True if this is the one to use
350 @ mtime TIMESTAMP, -- Time when attachment last changed
351 @ src TEXT, -- UUID of the attachment. NULL to delete
352 @ target TEXT, -- Object attached to. Wikiname or Tkt UUID
353 @ filename TEXT, -- Filename for the attachment
354 @ comment TEXT, -- Comment associated with this attachment
355 @ user TEXT -- Name of user adding attachment
@@ -443,11 +463,11 @@
443 @ chnged INT DEFAULT 0, -- 0:unchnged 1:edited 2:m-chng 3:m-add
444 @ deleted BOOLEAN DEFAULT 0, -- True if deleted
445 @ isexe BOOLEAN, -- True if file should be executable
446 @ rid INTEGER, -- Originally from this repository record
447 @ mrid INTEGER, -- Based on this record due to a merge
448 @ mtime INTEGER, -- Modification time of file on disk
449 @ pathname TEXT, -- Full pathname relative to root
450 @ origname TEXT, -- Original pathname. NULL if unchanged
451 @ UNIQUE(pathname,vid)
452 @ );
453 @
454
--- src/schema.c
+++ src/schema.c
@@ -39,12 +39,12 @@
39 ** changes. The aux tables have an arbitrary version number (typically
40 ** a date) which can change frequently. When the content schema changes,
41 ** we have to execute special procedures to update the schema. When
42 ** the aux schema changes, all we need to do is rebuild the database.
43 */
44 #define CONTENT_SCHEMA "2"
45 #define AUX_SCHEMA "2011-04-25 19:50"
46
47 #endif /* INTERFACE */
48
49
50 /*
@@ -51,21 +51,25 @@
51 ** The schema for a repository database.
52 **
53 ** Schema1[] contains parts of the schema that are fixed and unchanging
54 ** across versions. Schema2[] contains parts of the schema that can
55 ** change from one version to the next. The information in Schema2[]
56 ** is reconstructed from the information in Schema1[] by the "rebuild"
57 ** operation.
58 */
59 const char zRepositorySchema1[] =
60 @ -- The BLOB and DELTA tables contain all records held in the repository.
61 @ --
62 @ -- The BLOB.CONTENT column is always compressed using zlib. This
63 @ -- column might hold the full text of the record or it might hold
64 @ -- a delta that is able to reconstruct the record from some other
65 @ -- record. If BLOB.CONTENT holds a delta, then a DELTA table entry
66 @ -- will exist for the record and that entry will point to another
67 @ -- entry that holds the source of the delta. Deltas can be chained.
68 @ --
69 @ -- The blob and delta tables collectively hold the "global state" of
70 @ -- a Fossil repository.
71 @ --
72 @ CREATE TABLE blob(
73 @ rid INTEGER PRIMARY KEY, -- Record ID
74 @ rcvid INTEGER, -- Origin of this record
75 @ size INTEGER, -- Size of content. -1 for a phantom.
@@ -77,17 +81,24 @@
81 @ rid INTEGER PRIMARY KEY, -- Record ID
82 @ srcid INTEGER NOT NULL REFERENCES blob -- Record holding source document
83 @ );
84 @ CREATE INDEX delta_i1 ON delta(srcid);
85 @
86 @ -------------------------------------------------------------------------
87 @ -- The BLOB and DELTA tables above hold the "global state" of a Fossil
88 @ -- project; the stuff that is normally exchanged during "sync". The
89 @ -- "local state" of a repository is contained in the remaining tables of
90 @ -- the zRepositorySchema1 string.
91 @ -------------------------------------------------------------------------
92 @
93 @ -- Whenever new blobs are received into the repository, an entry
94 @ -- in this table records the source of the blob.
95 @ --
96 @ CREATE TABLE rcvfrom(
97 @ rcvid INTEGER PRIMARY KEY, -- Received-From ID
98 @ uid INTEGER REFERENCES user, -- User login
99 @ mtime DATETIME, -- Time of receipt. Julian day.
100 @ nonce TEXT UNIQUE, -- Nonce used for login
101 @ ipaddr TEXT -- Remote IP address. NULL for direct.
102 @ );
103 @
104 @ -- Information about users
@@ -99,26 +110,28 @@
110 @ -- hash based on the project-code, the user login, and the cleartext
111 @ -- password.
112 @ --
113 @ CREATE TABLE user(
114 @ uid INTEGER PRIMARY KEY, -- User ID
115 @ login TEXT UNIQUE, -- login name of the user
116 @ pw TEXT, -- password
117 @ cap TEXT, -- Capabilities of this user
118 @ cookie TEXT, -- WWW login cookie
119 @ ipaddr TEXT, -- IP address for which cookie is valid
120 @ cexpire DATETIME, -- Time when cookie expires
121 @ info TEXT, -- contact information
122 @ mtime DATE, -- last change. seconds since 1970
123 @ photo BLOB -- JPEG image of this user
124 @ );
125 @
126 @ -- The VAR table holds miscellanous information about the repository.
127 @ -- in the form of name-value pairs.
128 @ --
129 @ CREATE TABLE config(
130 @ name TEXT PRIMARY KEY NOT NULL, -- Primary name of the entry
131 @ value CLOB, -- Content of the named parameter
132 @ mtime DATE, -- last modified. seconds since 1970
133 @ CHECK( typeof(name)='text' AND length(name)>=1 )
134 @ );
135 @
136 @ -- Artifacts that should not be processed are identified in the
137 @ -- "shun" table. Artifacts that are control-file forgeries or
@@ -128,11 +141,15 @@
141 @ --
142 @ -- Shunned artifacts do not exist in the blob table. Hence they
143 @ -- have not artifact ID (rid) and we thus must store their full
144 @ -- UUID.
145 @ --
146 @ CREATE TABLE shun(
147 @ uuid UNIQUE, -- UUID of artifact to be shunned. Canonical form
148 @ mtime DATE, -- When added. seconds since 1970
149 @ scom TEXT -- Optional text explaining why the shun occurred
150 @ );
151 @
152 @ -- Artifacts that should not be pushed are stored in the "private"
153 @ -- table. Private artifacts are omitted from the "unclustered" and
154 @ -- "unsent" tables.
155 @ --
@@ -140,17 +157,19 @@
157 @
158 @ -- An entry in this table describes a database query that generates a
159 @ -- table of tickets.
160 @ --
161 @ CREATE TABLE reportfmt(
162 @ rn INTEGER PRIMARY KEY, -- Report number
163 @ owner TEXT, -- Owner of this report format (not used)
164 @ title TEXT UNIQUE, -- Title of this report
165 @ mtime DATE, -- Last modified. seconds since 1970
166 @ cols TEXT, -- A color-key specification
167 @ sqlcode TEXT -- An SQL SELECT statement for this report
168 @ );
169 @ INSERT INTO reportfmt(title,mtime,cols,sqlcode)
170 @ VALUES('All Tickets',julianday('1970-01-01'),'#ffffff Key:
171 @ #f2dcdc Active
172 @ #e8e8e8 Review
173 @ #cfe8bd Fixed
174 @ #bde5d6 Tested
175 @ #cacae5 Deferred
@@ -176,12 +195,13 @@
195 @ --
196 @ -- This table contains sensitive information and should not be shared
197 @ -- with unauthorized users.
198 @ --
199 @ CREATE TABLE concealed(
200 @ hash TEXT PRIMARY KEY, -- The SHA1 hash of content
201 @ mtime DATE, -- Time created. Seconds since 1970
202 @ content TEXT -- Content intended to be concealed
203 @ );
204 ;
205
206 const char zRepositorySchema2[] =
207 @ -- Filenames
@@ -214,11 +234,11 @@
234 @ --
235 @ CREATE TABLE plink(
236 @ pid INTEGER REFERENCES blob, -- Parent manifest
237 @ cid INTEGER REFERENCES blob, -- Child manifest
238 @ isprim BOOLEAN, -- pid is the primary parent of cid
239 @ mtime DATETIME, -- the date/time stamp on cid. Julian day.
240 @ UNIQUE(pid, cid)
241 @ );
242 @ CREATE INDEX plink_i2 ON plink(cid,pid);
243 @
244 @ -- A "leaf" checkin is a checkin that has no children in the same
@@ -232,11 +252,11 @@
252 @
253 @ -- Events used to generate a timeline
254 @ --
255 @ CREATE TABLE event(
256 @ type TEXT, -- Type of event: 'ci', 'w', 'e', 't'
257 @ mtime DATETIME, -- Time of occurrence. Julian day.
258 @ objid INTEGER PRIMARY KEY, -- Associated record ID
259 @ tagid INTEGER, -- Associated ticket or wiki name tag
260 @ uid INTEGER REFERENCES user, -- User who caused the event
261 @ bgcolor TEXT, -- Color set by 'bgcolor' property
262 @ euser TEXT, -- User set by 'user' property
@@ -319,11 +339,11 @@
339 @ tagid INTEGER REFERENCES tag, -- The tag that added or removed
340 @ tagtype INTEGER, -- 0:-,cancel 1:+,single 2:*,propagate
341 @ srcid INTEGER REFERENCES blob, -- Artifact of tag. 0 for propagated tags
342 @ origid INTEGER REFERENCES blob, -- check-in holding propagated tag
343 @ value TEXT, -- Value of the tag. Might be NULL.
344 @ mtime TIMESTAMP, -- Time of addition or removal. Julian day
345 @ rid INTEGER REFERENCE blob, -- Artifact tag is applied to
346 @ UNIQUE(rid, tagid)
347 @ );
348 @ CREATE INDEX tagxref_i1 ON tagxref(tagid, mtime);
349 @
@@ -334,11 +354,11 @@
354 @ --
355 @ CREATE TABLE backlink(
356 @ target TEXT, -- Where the hyperlink points to
357 @ srctype INT, -- 0: check-in 1: ticket 2: wiki
358 @ srcid INT, -- rid for checkin or wiki. tkt_id for ticket.
359 @ mtime TIMESTAMP, -- time that the hyperlink was added. Julian day.
360 @ UNIQUE(target, srctype, srcid)
361 @ );
362 @ CREATE INDEX backlink_src ON backlink(srcid, srctype);
363 @
364 @ -- Each attachment is an entry in the following table. Only
@@ -345,11 +365,11 @@
365 @ -- the most recent attachment (identified by the D card) is saved.
366 @ --
367 @ CREATE TABLE attachment(
368 @ attachid INTEGER PRIMARY KEY, -- Local id for this attachment
369 @ isLatest BOOLEAN DEFAULT 0, -- True if this is the one to use
370 @ mtime TIMESTAMP, -- Last changed. Julian day.
371 @ src TEXT, -- UUID of the attachment. NULL to delete
372 @ target TEXT, -- Object attached to. Wikiname or Tkt UUID
373 @ filename TEXT, -- Filename for the attachment
374 @ comment TEXT, -- Comment associated with this attachment
375 @ user TEXT -- Name of user adding attachment
@@ -443,11 +463,11 @@
463 @ chnged INT DEFAULT 0, -- 0:unchnged 1:edited 2:m-chng 3:m-add
464 @ deleted BOOLEAN DEFAULT 0, -- True if deleted
465 @ isexe BOOLEAN, -- True if file should be executable
466 @ rid INTEGER, -- Originally from this repository record
467 @ mrid INTEGER, -- Based on this record due to a merge
468 @ mtime INTEGER, -- Mtime of file on disk. sec since 1970
469 @ pathname TEXT, -- Full pathname relative to root
470 @ origname TEXT, -- Original pathname. NULL if unchanged
471 @ UNIQUE(pathname,vid)
472 @ );
473 @
474
+7 -6
--- src/setup.c
+++ src/setup.c
@@ -354,12 +354,12 @@
354354
style_footer();
355355
return;
356356
}
357357
login_verify_csrf_secret();
358358
db_multi_exec(
359
- "REPLACE INTO user(uid,login,info,pw,cap) "
360
- "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s')",
359
+ "REPLACE INTO user(uid,login,info,pw,cap,mtime) "
360
+ "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s',now())",
361361
uid, P("login"), P("info"), zPw, zCap
362362
);
363363
if( atoi(PD("all","0"))>0 ){
364364
Blob sql;
365365
char *zErr = 0;
@@ -375,11 +375,12 @@
375375
blob_appendf(&sql,
376376
"UPDATE user SET login=%Q,"
377377
" pw=coalesce(shared_secret(%Q,%Q,"
378378
"(SELECT value FROM config WHERE name='project-code')),pw),"
379379
" info=%Q,"
380
- " cap=%Q"
380
+ " cap=%Q,"
381
+ " mtime=now()"
381382
" WHERE login=%Q;",
382383
zLogin, P("pw"), zLogin, P("info"), zCap,
383384
zOldLogin
384385
);
385386
login_group_sql(blob_str(&sql), "<li> ", " </li>\n", &zErr);
@@ -1286,18 +1287,18 @@
12861287
if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){
12871288
Blob img;
12881289
Stmt ins;
12891290
blob_init(&img, aImg, szImg);
12901291
db_prepare(&ins,
1291
- "REPLACE INTO config(name, value)"
1292
- " VALUES('logo-image',:bytes)"
1292
+ "REPLACE INTO config(name,value,mtime)"
1293
+ " VALUES('logo-image',:bytes,now())"
12931294
);
12941295
db_bind_blob(&ins, ":bytes", &img);
12951296
db_step(&ins);
12961297
db_finalize(&ins);
12971298
db_multi_exec(
1298
- "REPLACE INTO config(name, value) VALUES('logo-mimetype',%Q)",
1299
+ "REPLACE INTO config(name,value,mtime) VALUES('logo-mimetype',%Q,now())",
12991300
zMime
13001301
);
13011302
db_end_transaction(0);
13021303
cgi_redirect("setup_logo");
13031304
}else if( P("clr")!=0 ){
13041305
--- src/setup.c
+++ src/setup.c
@@ -354,12 +354,12 @@
354 style_footer();
355 return;
356 }
357 login_verify_csrf_secret();
358 db_multi_exec(
359 "REPLACE INTO user(uid,login,info,pw,cap) "
360 "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s')",
361 uid, P("login"), P("info"), zPw, zCap
362 );
363 if( atoi(PD("all","0"))>0 ){
364 Blob sql;
365 char *zErr = 0;
@@ -375,11 +375,12 @@
375 blob_appendf(&sql,
376 "UPDATE user SET login=%Q,"
377 " pw=coalesce(shared_secret(%Q,%Q,"
378 "(SELECT value FROM config WHERE name='project-code')),pw),"
379 " info=%Q,"
380 " cap=%Q"
 
381 " WHERE login=%Q;",
382 zLogin, P("pw"), zLogin, P("info"), zCap,
383 zOldLogin
384 );
385 login_group_sql(blob_str(&sql), "<li> ", " </li>\n", &zErr);
@@ -1286,18 +1287,18 @@
1286 if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){
1287 Blob img;
1288 Stmt ins;
1289 blob_init(&img, aImg, szImg);
1290 db_prepare(&ins,
1291 "REPLACE INTO config(name, value)"
1292 " VALUES('logo-image',:bytes)"
1293 );
1294 db_bind_blob(&ins, ":bytes", &img);
1295 db_step(&ins);
1296 db_finalize(&ins);
1297 db_multi_exec(
1298 "REPLACE INTO config(name, value) VALUES('logo-mimetype',%Q)",
1299 zMime
1300 );
1301 db_end_transaction(0);
1302 cgi_redirect("setup_logo");
1303 }else if( P("clr")!=0 ){
1304
--- src/setup.c
+++ src/setup.c
@@ -354,12 +354,12 @@
354 style_footer();
355 return;
356 }
357 login_verify_csrf_secret();
358 db_multi_exec(
359 "REPLACE INTO user(uid,login,info,pw,cap,mtime) "
360 "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s',now())",
361 uid, P("login"), P("info"), zPw, zCap
362 );
363 if( atoi(PD("all","0"))>0 ){
364 Blob sql;
365 char *zErr = 0;
@@ -375,11 +375,12 @@
375 blob_appendf(&sql,
376 "UPDATE user SET login=%Q,"
377 " pw=coalesce(shared_secret(%Q,%Q,"
378 "(SELECT value FROM config WHERE name='project-code')),pw),"
379 " info=%Q,"
380 " cap=%Q,"
381 " mtime=now()"
382 " WHERE login=%Q;",
383 zLogin, P("pw"), zLogin, P("info"), zCap,
384 zOldLogin
385 );
386 login_group_sql(blob_str(&sql), "<li> ", " </li>\n", &zErr);
@@ -1286,18 +1287,18 @@
1287 if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){
1288 Blob img;
1289 Stmt ins;
1290 blob_init(&img, aImg, szImg);
1291 db_prepare(&ins,
1292 "REPLACE INTO config(name,value,mtime)"
1293 " VALUES('logo-image',:bytes,now())"
1294 );
1295 db_bind_blob(&ins, ":bytes", &img);
1296 db_step(&ins);
1297 db_finalize(&ins);
1298 db_multi_exec(
1299 "REPLACE INTO config(name,value,mtime) VALUES('logo-mimetype',%Q,now())",
1300 zMime
1301 );
1302 db_end_transaction(0);
1303 cgi_redirect("setup_logo");
1304 }else if( P("clr")!=0 ){
1305
+2 -2
--- src/sha1.c
+++ src/sha1.c
@@ -266,11 +266,11 @@
266266
FILE *in;
267267
SHA1Context ctx;
268268
unsigned char zResult[20];
269269
char zBuf[10240];
270270
271
- in = fopen(zFilename,"rb");
271
+ in = fossil_fopen(zFilename,"rb");
272272
if( in==0 ){
273273
return 1;
274274
}
275275
SHA1Init(&ctx);
276276
for(;;){
@@ -430,9 +430,9 @@
430430
blob_read_from_channel(&in, stdin, -1);
431431
sha1sum_blob(&in, &cksum);
432432
}else{
433433
sha1sum_file(g.argv[i], &cksum);
434434
}
435
- printf("%s %s\n", blob_str(&cksum), g.argv[i]);
435
+ fossil_print("%s %s\n", blob_str(&cksum), g.argv[i]);
436436
blob_reset(&cksum);
437437
}
438438
}
439439
--- src/sha1.c
+++ src/sha1.c
@@ -266,11 +266,11 @@
266 FILE *in;
267 SHA1Context ctx;
268 unsigned char zResult[20];
269 char zBuf[10240];
270
271 in = fopen(zFilename,"rb");
272 if( in==0 ){
273 return 1;
274 }
275 SHA1Init(&ctx);
276 for(;;){
@@ -430,9 +430,9 @@
430 blob_read_from_channel(&in, stdin, -1);
431 sha1sum_blob(&in, &cksum);
432 }else{
433 sha1sum_file(g.argv[i], &cksum);
434 }
435 printf("%s %s\n", blob_str(&cksum), g.argv[i]);
436 blob_reset(&cksum);
437 }
438 }
439
--- src/sha1.c
+++ src/sha1.c
@@ -266,11 +266,11 @@
266 FILE *in;
267 SHA1Context ctx;
268 unsigned char zResult[20];
269 char zBuf[10240];
270
271 in = fossil_fopen(zFilename,"rb");
272 if( in==0 ){
273 return 1;
274 }
275 SHA1Init(&ctx);
276 for(;;){
@@ -430,9 +430,9 @@
430 blob_read_from_channel(&in, stdin, -1);
431 sha1sum_blob(&in, &cksum);
432 }else{
433 sha1sum_file(g.argv[i], &cksum);
434 }
435 fossil_print("%s %s\n", blob_str(&cksum), g.argv[i]);
436 blob_reset(&cksum);
437 }
438 }
439
+11 -8
--- src/shell.c
+++ src/shell.c
@@ -68,21 +68,21 @@
6868
* thus we always assume that we have a console. That can be
6969
* overridden with the -batch command line option.
7070
*/
7171
#define isatty(x) 1
7272
#endif
73
+
74
+/* True if the timer is enabled */
75
+static int enableTimer = 0;
7376
7477
#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
7578
#include <sys/time.h>
7679
#include <sys/resource.h>
7780
7881
/* Saved resource information for the beginning of an operation */
7982
static struct rusage sBegin;
8083
81
-/* True if the timer is enabled */
82
-static int enableTimer = 0;
83
-
8484
/*
8585
** Begin timing an operation
8686
*/
8787
static void beginTimer(void){
8888
if( enableTimer ){
@@ -122,13 +122,10 @@
122122
static FILETIME ftKernelBegin;
123123
static FILETIME ftUserBegin;
124124
typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
125125
static GETPROCTIMES getProcessTimesAddr = NULL;
126126
127
-/* True if the timer is enabled */
128
-static int enableTimer = 0;
129
-
130127
/*
131128
** Check to see if we have timer support. Return 1 if necessary
132129
** support found (or found previously).
133130
*/
134131
static int hasTimer(void){
@@ -2197,12 +2194,12 @@
21972194
int i, n;
21982195
open_db(p);
21992196
22002197
/* convert testctrl text option to value. allow any unique prefix
22012198
** of the option name, or a numerical value. */
2202
- n = strlen(azArg[1]);
2203
- for(i=0; i<sizeof(aCtrl)/sizeof(aCtrl[0]); i++){
2199
+ n = strlen30(azArg[1]);
2200
+ for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
22042201
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
22052202
if( testctrl<0 ){
22062203
testctrl = aCtrl[i].ctrlCode;
22072204
}else{
22082205
fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[i]);
@@ -2650,10 +2647,11 @@
26502647
static void main_init(struct callback_data *data) {
26512648
memset(data, 0, sizeof(*data));
26522649
data->mode = MODE_List;
26532650
memcpy(data->separator,"|", 2);
26542651
data->showHeader = 0;
2652
+ sqlite3_config(SQLITE_CONFIG_URI, 1);
26552653
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
26562654
sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
26572655
sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
26582656
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
26592657
}
@@ -2664,10 +2662,15 @@
26642662
const char *zInitFile = 0;
26652663
char *zFirstCmd = 0;
26662664
int i;
26672665
int rc = 0;
26682666
2667
+ if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
2668
+ fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
2669
+ sqlite3_sourceid(), SQLITE_SOURCE_ID);
2670
+ exit(1);
2671
+ }
26692672
Argv0 = argv[0];
26702673
main_init(&data);
26712674
stdin_is_interactive = isatty(0);
26722675
26732676
/* Make sure we have a valid signal handler early, before anything
26742677
--- src/shell.c
+++ src/shell.c
@@ -68,21 +68,21 @@
68 * thus we always assume that we have a console. That can be
69 * overridden with the -batch command line option.
70 */
71 #define isatty(x) 1
72 #endif
 
 
 
73
74 #if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
75 #include <sys/time.h>
76 #include <sys/resource.h>
77
78 /* Saved resource information for the beginning of an operation */
79 static struct rusage sBegin;
80
81 /* True if the timer is enabled */
82 static int enableTimer = 0;
83
84 /*
85 ** Begin timing an operation
86 */
87 static void beginTimer(void){
88 if( enableTimer ){
@@ -122,13 +122,10 @@
122 static FILETIME ftKernelBegin;
123 static FILETIME ftUserBegin;
124 typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
125 static GETPROCTIMES getProcessTimesAddr = NULL;
126
127 /* True if the timer is enabled */
128 static int enableTimer = 0;
129
130 /*
131 ** Check to see if we have timer support. Return 1 if necessary
132 ** support found (or found previously).
133 */
134 static int hasTimer(void){
@@ -2197,12 +2194,12 @@
2197 int i, n;
2198 open_db(p);
2199
2200 /* convert testctrl text option to value. allow any unique prefix
2201 ** of the option name, or a numerical value. */
2202 n = strlen(azArg[1]);
2203 for(i=0; i<sizeof(aCtrl)/sizeof(aCtrl[0]); i++){
2204 if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
2205 if( testctrl<0 ){
2206 testctrl = aCtrl[i].ctrlCode;
2207 }else{
2208 fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[i]);
@@ -2650,10 +2647,11 @@
2650 static void main_init(struct callback_data *data) {
2651 memset(data, 0, sizeof(*data));
2652 data->mode = MODE_List;
2653 memcpy(data->separator,"|", 2);
2654 data->showHeader = 0;
 
2655 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
2656 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
2657 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
2658 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
2659 }
@@ -2664,10 +2662,15 @@
2664 const char *zInitFile = 0;
2665 char *zFirstCmd = 0;
2666 int i;
2667 int rc = 0;
2668
 
 
 
 
 
2669 Argv0 = argv[0];
2670 main_init(&data);
2671 stdin_is_interactive = isatty(0);
2672
2673 /* Make sure we have a valid signal handler early, before anything
2674
--- src/shell.c
+++ src/shell.c
@@ -68,21 +68,21 @@
68 * thus we always assume that we have a console. That can be
69 * overridden with the -batch command line option.
70 */
71 #define isatty(x) 1
72 #endif
73
74 /* True if the timer is enabled */
75 static int enableTimer = 0;
76
77 #if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
78 #include <sys/time.h>
79 #include <sys/resource.h>
80
81 /* Saved resource information for the beginning of an operation */
82 static struct rusage sBegin;
83
 
 
 
84 /*
85 ** Begin timing an operation
86 */
87 static void beginTimer(void){
88 if( enableTimer ){
@@ -122,13 +122,10 @@
122 static FILETIME ftKernelBegin;
123 static FILETIME ftUserBegin;
124 typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
125 static GETPROCTIMES getProcessTimesAddr = NULL;
126
 
 
 
127 /*
128 ** Check to see if we have timer support. Return 1 if necessary
129 ** support found (or found previously).
130 */
131 static int hasTimer(void){
@@ -2197,12 +2194,12 @@
2194 int i, n;
2195 open_db(p);
2196
2197 /* convert testctrl text option to value. allow any unique prefix
2198 ** of the option name, or a numerical value. */
2199 n = strlen30(azArg[1]);
2200 for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
2201 if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
2202 if( testctrl<0 ){
2203 testctrl = aCtrl[i].ctrlCode;
2204 }else{
2205 fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[i]);
@@ -2650,10 +2647,11 @@
2647 static void main_init(struct callback_data *data) {
2648 memset(data, 0, sizeof(*data));
2649 data->mode = MODE_List;
2650 memcpy(data->separator,"|", 2);
2651 data->showHeader = 0;
2652 sqlite3_config(SQLITE_CONFIG_URI, 1);
2653 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
2654 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
2655 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
2656 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
2657 }
@@ -2664,10 +2662,15 @@
2662 const char *zInitFile = 0;
2663 char *zFirstCmd = 0;
2664 int i;
2665 int rc = 0;
2666
2667 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
2668 fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
2669 sqlite3_sourceid(), SQLITE_SOURCE_ID);
2670 exit(1);
2671 }
2672 Argv0 = argv[0];
2673 main_init(&data);
2674 stdin_is_interactive = isatty(0);
2675
2676 /* Make sure we have a valid signal handler early, before anything
2677
+15 -1
--- src/shun.c
+++ src/shun.c
@@ -81,17 +81,31 @@
8181
@ <b>fossil rebuild</b> command-line before the artifact content
8282
@ can pulled in from other respositories.</p>
8383
}
8484
}
8585
if( zUuid && P("add") ){
86
+ int rid, tagid;
8687
login_verify_csrf_secret();
87
- db_multi_exec("INSERT OR IGNORE INTO shun VALUES('%s')", zUuid);
88
+ db_multi_exec(
89
+ "INSERT OR IGNORE INTO shun(uuid,mtime)"
90
+ " VALUES('%s', now())", zUuid);
8891
@ <p class="shunned">Artifact
8992
@ <a href="%s(g.zTop)/artifact/%s(zUuid)">%s(zUuid)</a> has been
9093
@ shunned. It will no longer be pushed.
9194
@ It will be removed from the repository the next time the respository
9295
@ is rebuilt using the <b>fossil rebuild</b> command-line</p>
96
+ db_multi_exec("DELETE FROM attachment WHERE src=%Q", zUuid);
97
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
98
+ if( rid ){
99
+ db_multi_exec("DELETE FROM event WHERE objid=%d", rid);
100
+ }
101
+ tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='tkt-%q'", zUuid);
102
+ if( tagid ){
103
+ db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", zUuid);
104
+ db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
105
+ db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
106
+ }
93107
}
94108
@ <p>A shunned artifact will not be pushed nor accepted in a pull and the
95109
@ artifact content will be purged from the repository the next time the
96110
@ repository is rebuilt. A list of shunned artifacts can be seen at the
97111
@ bottom of this page.</p>
98112
--- src/shun.c
+++ src/shun.c
@@ -81,17 +81,31 @@
81 @ <b>fossil rebuild</b> command-line before the artifact content
82 @ can pulled in from other respositories.</p>
83 }
84 }
85 if( zUuid && P("add") ){
 
86 login_verify_csrf_secret();
87 db_multi_exec("INSERT OR IGNORE INTO shun VALUES('%s')", zUuid);
 
 
88 @ <p class="shunned">Artifact
89 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">%s(zUuid)</a> has been
90 @ shunned. It will no longer be pushed.
91 @ It will be removed from the repository the next time the respository
92 @ is rebuilt using the <b>fossil rebuild</b> command-line</p>
 
 
 
 
 
 
 
 
 
 
 
93 }
94 @ <p>A shunned artifact will not be pushed nor accepted in a pull and the
95 @ artifact content will be purged from the repository the next time the
96 @ repository is rebuilt. A list of shunned artifacts can be seen at the
97 @ bottom of this page.</p>
98
--- src/shun.c
+++ src/shun.c
@@ -81,17 +81,31 @@
81 @ <b>fossil rebuild</b> command-line before the artifact content
82 @ can pulled in from other respositories.</p>
83 }
84 }
85 if( zUuid && P("add") ){
86 int rid, tagid;
87 login_verify_csrf_secret();
88 db_multi_exec(
89 "INSERT OR IGNORE INTO shun(uuid,mtime)"
90 " VALUES('%s', now())", zUuid);
91 @ <p class="shunned">Artifact
92 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">%s(zUuid)</a> has been
93 @ shunned. It will no longer be pushed.
94 @ It will be removed from the repository the next time the respository
95 @ is rebuilt using the <b>fossil rebuild</b> command-line</p>
96 db_multi_exec("DELETE FROM attachment WHERE src=%Q", zUuid);
97 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
98 if( rid ){
99 db_multi_exec("DELETE FROM event WHERE objid=%d", rid);
100 }
101 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='tkt-%q'", zUuid);
102 if( tagid ){
103 db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", zUuid);
104 db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
105 db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
106 }
107 }
108 @ <p>A shunned artifact will not be pushed nor accepted in a pull and the
109 @ artifact content will be purged from the repository the next time the
110 @ repository is rebuilt. A list of shunned artifacts can be seen at the
111 @ bottom of this page.</p>
112
+27 -18
--- src/skins.c
+++ src/skins.c
@@ -25,11 +25,12 @@
2525
/*
2626
** A black-and-white theme with the project title in a bar across the top
2727
** and no logo image.
2828
*/
2929
static const char zBuiltinSkin1[] =
30
-@ REPLACE INTO config VALUES('css','/* General settings for the entire page */
30
+@ REPLACE INTO config(name,mtime,value)
31
+@ VALUES('css',now(),'/* General settings for the entire page */
3132
@ body {
3233
@ margin: 0ex 1ex;
3334
@ padding: 0px;
3435
@ background-color: white;
3536
@ font-family: sans-serif;
@@ -152,11 +153,11 @@
152153
@ table.label-value th {
153154
@ vertical-align: top;
154155
@ text-align: right;
155156
@ padding: 0.2ex 2ex;
156157
@ }');
157
-@ REPLACE INTO config VALUES('header','<html>
158
+@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
158159
@ <head>
159160
@ <title>$<project_name>: $<title></title>
160161
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
161162
@ href="$home/timeline.rss">
162163
@ <link rel="stylesheet" href="$home/style.css?blackwhite" type="text/css"
@@ -204,11 +205,12 @@
204205
@ } else {
205206
@ html "<a href=''$home/login''>Login</a> "
206207
@ }
207208
@ </th1></div>
208209
@ ');
209
-@ REPLACE INTO config VALUES('footer','<div class="footer">
210
+@ REPLACE INTO config(name,mtime,value)
211
+@ VALUES('footer',now(),'<div class="footer">
210212
@ Fossil version $manifest_version $manifest_date
211213
@ </div>
212214
@ </body></html>
213215
@ ');
214216
;
@@ -216,11 +218,12 @@
216218
/*
217219
** A tan theme with the project title above the user identification
218220
** and no logo image.
219221
*/
220222
static const char zBuiltinSkin2[] =
221
-@ REPLACE INTO config VALUES('css','/* General settings for the entire page */
223
+@ REPLACE INTO config(name,mtime,value)
224
+@ VALUES('css',now(),'/* General settings for the entire page */
222225
@ body {
223226
@ margin: 0ex 0ex;
224227
@ padding: 0px;
225228
@ background-color: #fef3bc;
226229
@ font-family: sans-serif;
@@ -354,11 +357,11 @@
354357
@ vertical-align: top;
355358
@ text-align: right;
356359
@ padding: 0.2ex 2ex;
357360
@ }
358361
@ ');
359
-@ REPLACE INTO config VALUES('header','<html>
362
+@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
360363
@ <head>
361364
@ <title>$<project_name>: $<title></title>
362365
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
363366
@ href="$home/timeline.rss">
364367
@ <link rel="stylesheet" href="$home/style.css?tan" type="text/css"
@@ -405,11 +408,12 @@
405408
@ } else {
406409
@ html "<a href=''$home/login''>Login</a> "
407410
@ }
408411
@ </th1></div>
409412
@ ');
410
-@ REPLACE INTO config VALUES('footer','<div class="footer">
413
+@ REPLACE INTO config(name,mtime,value)
414
+@ VALUES('footer',now(),'<div class="footer">
411415
@ Fossil version $manifest_version $manifest_date
412416
@ </div>
413417
@ </body></html>
414418
@ ');
415419
;
@@ -417,11 +421,12 @@
417421
/*
418422
** Black letters on a white or cream background with the main menu
419423
** stuck on the left-hand side.
420424
*/
421425
static const char zBuiltinSkin3[] =
422
-@ REPLACE INTO config VALUES('css','/* General settings for the entire page */
426
+@ REPLACE INTO config(name,mtime,value)
427
+@ VALUES('css',now(),'/* General settings for the entire page */
423428
@ body {
424429
@ margin:0px 0px 0px 0px;
425430
@ padding:0px;
426431
@ font-family:verdana, arial, helvetica, "sans serif";
427432
@ color:#333;
@@ -586,11 +591,11 @@
586591
@ table.label-value th {
587592
@ vertical-align: top;
588593
@ text-align: right;
589594
@ padding: 0.2ex 2ex;
590595
@ }');
591
-@ REPLACE INTO config VALUES('header','<html>
596
+@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
592597
@ <head>
593598
@ <title>$<project_name>: $<title></title>
594599
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
595600
@ href="$home/timeline.rss">
596601
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
@@ -640,11 +645,11 @@
640645
@ html "<li><a href=''$home/login''>Login</a></li>"
641646
@ }
642647
@ </th1></ul></div>
643648
@ <div id="container">
644649
@ ');
645
-@ REPLACE INTO config VALUES('footer','</div>
650
+@ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div>
646651
@ <div class="footer">
647652
@ Fossil version $manifest_version $manifest_date
648653
@ </div>
649654
@ </body></html>
650655
@ ');
@@ -653,11 +658,12 @@
653658
654659
/*
655660
** Gradients and rounded corners.
656661
*/
657662
static const char zBuiltinSkin4[] =
658
-@ REPLACE INTO config VALUES('css','/* General settings for the entire page */
663
+@ REPLACE INTO config(name,mtime,value)
664
+@ VALUES('css',now(),'/* General settings for the entire page */
659665
@ html {
660666
@ min-height: 100%;
661667
@ }
662668
@ body {
663669
@ margin: 0ex 1ex;
@@ -880,11 +886,11 @@
880886
@ }
881887
@
882888
@ textarea {
883889
@ font-size: 1em;
884890
@ }');
885
-@ REPLACE INTO config VALUES('header','<html>
891
+@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
886892
@ <head>
887893
@ <title>$<project_name>: $<title></title>
888894
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
889895
@ href="$home/timeline.rss">
890896
@ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
@@ -934,11 +940,11 @@
934940
@ html "<a href=''$home/login''>Login</a>"
935941
@ }
936942
@ </th1></ul></div>
937943
@ <div id="container">
938944
@ ');
939
-@ REPLACE INTO config VALUES('footer','</div>
945
+@ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div>
940946
@ <div class="footer">
941947
@ Fossil version $manifest_version $manifest_date
942948
@ </div>
943949
@ </body></html>
944950
@ ');
@@ -984,17 +990,20 @@
984990
** Memory to hold the returned string is obtained from malloc.
985991
*/
986992
static char *getSkin(int useDefault){
987993
Blob val;
988994
blob_zero(&val);
989
- blob_appendf(&val, "REPLACE INTO config VALUES('css',%Q);\n",
995
+ blob_appendf(&val,
996
+ "REPLACE INTO config(name,value,mtime) VALUES('css',%Q,now());\n",
990997
useDefault ? zDefaultCSS : db_get("css", (char*)zDefaultCSS)
991998
);
992
- blob_appendf(&val, "REPLACE INTO config VALUES('header',%Q);\n",
999
+ blob_appendf(&val,
1000
+ "REPLACE INTO config(name,value,mtime) VALUES('header',%Q,now());\n",
9931001
useDefault ? zDefaultHeader : db_get("header", (char*)zDefaultHeader)
9941002
);
995
- blob_appendf(&val, "REPLACE INTO config VALUES('footer',%Q);\n",
1003
+ blob_appendf(&val,
1004
+ "REPLACE INTO config(name,value,mtime) VALUES('footer',%Q,now());\n",
9961005
useDefault ? zDefaultFooter : db_get("footer", (char*)zDefaultFooter)
9971006
);
9981007
return blob_str(&val);
9991008
}
10001009
@@ -1048,11 +1057,11 @@
10481057
if( db_exists("SELECT 1 FROM config WHERE name=%Q", zName)
10491058
|| strcmp(zName, "Default")==0 ){
10501059
zErr = mprintf("Skin name \"%h\" already exists. "
10511060
"Choose a different name.", P("sn"));
10521061
}else{
1053
- db_multi_exec("INSERT INTO config VALUES(%Q,%Q)",
1062
+ db_multi_exec("INSERT INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
10541063
zName, zCurrent
10551064
);
10561065
}
10571066
}
10581067
@@ -1069,13 +1078,13 @@
10691078
seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
10701079
" AND value=%Q", zCurrent);
10711080
}
10721081
if( !seen ){
10731082
db_multi_exec(
1074
- "INSERT INTO config VALUES("
1083
+ "INSERT INTO config(name,value,mtime) VALUES("
10751084
" strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
1076
- " %Q)", zCurrent
1085
+ " %Q,now())", zCurrent
10771086
);
10781087
}
10791088
seen = 0;
10801089
for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
10811090
if( strcmp(aBuiltinSkin[i].zName, z)==0 ){
10821091
--- src/skins.c
+++ src/skins.c
@@ -25,11 +25,12 @@
25 /*
26 ** A black-and-white theme with the project title in a bar across the top
27 ** and no logo image.
28 */
29 static const char zBuiltinSkin1[] =
30 @ REPLACE INTO config VALUES('css','/* General settings for the entire page */
 
31 @ body {
32 @ margin: 0ex 1ex;
33 @ padding: 0px;
34 @ background-color: white;
35 @ font-family: sans-serif;
@@ -152,11 +153,11 @@
152 @ table.label-value th {
153 @ vertical-align: top;
154 @ text-align: right;
155 @ padding: 0.2ex 2ex;
156 @ }');
157 @ REPLACE INTO config VALUES('header','<html>
158 @ <head>
159 @ <title>$<project_name>: $<title></title>
160 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
161 @ href="$home/timeline.rss">
162 @ <link rel="stylesheet" href="$home/style.css?blackwhite" type="text/css"
@@ -204,11 +205,12 @@
204 @ } else {
205 @ html "<a href=''$home/login''>Login</a> "
206 @ }
207 @ </th1></div>
208 @ ');
209 @ REPLACE INTO config VALUES('footer','<div class="footer">
 
210 @ Fossil version $manifest_version $manifest_date
211 @ </div>
212 @ </body></html>
213 @ ');
214 ;
@@ -216,11 +218,12 @@
216 /*
217 ** A tan theme with the project title above the user identification
218 ** and no logo image.
219 */
220 static const char zBuiltinSkin2[] =
221 @ REPLACE INTO config VALUES('css','/* General settings for the entire page */
 
222 @ body {
223 @ margin: 0ex 0ex;
224 @ padding: 0px;
225 @ background-color: #fef3bc;
226 @ font-family: sans-serif;
@@ -354,11 +357,11 @@
354 @ vertical-align: top;
355 @ text-align: right;
356 @ padding: 0.2ex 2ex;
357 @ }
358 @ ');
359 @ REPLACE INTO config VALUES('header','<html>
360 @ <head>
361 @ <title>$<project_name>: $<title></title>
362 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
363 @ href="$home/timeline.rss">
364 @ <link rel="stylesheet" href="$home/style.css?tan" type="text/css"
@@ -405,11 +408,12 @@
405 @ } else {
406 @ html "<a href=''$home/login''>Login</a> "
407 @ }
408 @ </th1></div>
409 @ ');
410 @ REPLACE INTO config VALUES('footer','<div class="footer">
 
411 @ Fossil version $manifest_version $manifest_date
412 @ </div>
413 @ </body></html>
414 @ ');
415 ;
@@ -417,11 +421,12 @@
417 /*
418 ** Black letters on a white or cream background with the main menu
419 ** stuck on the left-hand side.
420 */
421 static const char zBuiltinSkin3[] =
422 @ REPLACE INTO config VALUES('css','/* General settings for the entire page */
 
423 @ body {
424 @ margin:0px 0px 0px 0px;
425 @ padding:0px;
426 @ font-family:verdana, arial, helvetica, "sans serif";
427 @ color:#333;
@@ -586,11 +591,11 @@
586 @ table.label-value th {
587 @ vertical-align: top;
588 @ text-align: right;
589 @ padding: 0.2ex 2ex;
590 @ }');
591 @ REPLACE INTO config VALUES('header','<html>
592 @ <head>
593 @ <title>$<project_name>: $<title></title>
594 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
595 @ href="$home/timeline.rss">
596 @ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
@@ -640,11 +645,11 @@
640 @ html "<li><a href=''$home/login''>Login</a></li>"
641 @ }
642 @ </th1></ul></div>
643 @ <div id="container">
644 @ ');
645 @ REPLACE INTO config VALUES('footer','</div>
646 @ <div class="footer">
647 @ Fossil version $manifest_version $manifest_date
648 @ </div>
649 @ </body></html>
650 @ ');
@@ -653,11 +658,12 @@
653
654 /*
655 ** Gradients and rounded corners.
656 */
657 static const char zBuiltinSkin4[] =
658 @ REPLACE INTO config VALUES('css','/* General settings for the entire page */
 
659 @ html {
660 @ min-height: 100%;
661 @ }
662 @ body {
663 @ margin: 0ex 1ex;
@@ -880,11 +886,11 @@
880 @ }
881 @
882 @ textarea {
883 @ font-size: 1em;
884 @ }');
885 @ REPLACE INTO config VALUES('header','<html>
886 @ <head>
887 @ <title>$<project_name>: $<title></title>
888 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
889 @ href="$home/timeline.rss">
890 @ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
@@ -934,11 +940,11 @@
934 @ html "<a href=''$home/login''>Login</a>"
935 @ }
936 @ </th1></ul></div>
937 @ <div id="container">
938 @ ');
939 @ REPLACE INTO config VALUES('footer','</div>
940 @ <div class="footer">
941 @ Fossil version $manifest_version $manifest_date
942 @ </div>
943 @ </body></html>
944 @ ');
@@ -984,17 +990,20 @@
984 ** Memory to hold the returned string is obtained from malloc.
985 */
986 static char *getSkin(int useDefault){
987 Blob val;
988 blob_zero(&val);
989 blob_appendf(&val, "REPLACE INTO config VALUES('css',%Q);\n",
 
990 useDefault ? zDefaultCSS : db_get("css", (char*)zDefaultCSS)
991 );
992 blob_appendf(&val, "REPLACE INTO config VALUES('header',%Q);\n",
 
993 useDefault ? zDefaultHeader : db_get("header", (char*)zDefaultHeader)
994 );
995 blob_appendf(&val, "REPLACE INTO config VALUES('footer',%Q);\n",
 
996 useDefault ? zDefaultFooter : db_get("footer", (char*)zDefaultFooter)
997 );
998 return blob_str(&val);
999 }
1000
@@ -1048,11 +1057,11 @@
1048 if( db_exists("SELECT 1 FROM config WHERE name=%Q", zName)
1049 || strcmp(zName, "Default")==0 ){
1050 zErr = mprintf("Skin name \"%h\" already exists. "
1051 "Choose a different name.", P("sn"));
1052 }else{
1053 db_multi_exec("INSERT INTO config VALUES(%Q,%Q)",
1054 zName, zCurrent
1055 );
1056 }
1057 }
1058
@@ -1069,13 +1078,13 @@
1069 seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
1070 " AND value=%Q", zCurrent);
1071 }
1072 if( !seen ){
1073 db_multi_exec(
1074 "INSERT INTO config VALUES("
1075 " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
1076 " %Q)", zCurrent
1077 );
1078 }
1079 seen = 0;
1080 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
1081 if( strcmp(aBuiltinSkin[i].zName, z)==0 ){
1082
--- src/skins.c
+++ src/skins.c
@@ -25,11 +25,12 @@
25 /*
26 ** A black-and-white theme with the project title in a bar across the top
27 ** and no logo image.
28 */
29 static const char zBuiltinSkin1[] =
30 @ REPLACE INTO config(name,mtime,value)
31 @ VALUES('css',now(),'/* General settings for the entire page */
32 @ body {
33 @ margin: 0ex 1ex;
34 @ padding: 0px;
35 @ background-color: white;
36 @ font-family: sans-serif;
@@ -152,11 +153,11 @@
153 @ table.label-value th {
154 @ vertical-align: top;
155 @ text-align: right;
156 @ padding: 0.2ex 2ex;
157 @ }');
158 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
159 @ <head>
160 @ <title>$<project_name>: $<title></title>
161 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
162 @ href="$home/timeline.rss">
163 @ <link rel="stylesheet" href="$home/style.css?blackwhite" type="text/css"
@@ -204,11 +205,12 @@
205 @ } else {
206 @ html "<a href=''$home/login''>Login</a> "
207 @ }
208 @ </th1></div>
209 @ ');
210 @ REPLACE INTO config(name,mtime,value)
211 @ VALUES('footer',now(),'<div class="footer">
212 @ Fossil version $manifest_version $manifest_date
213 @ </div>
214 @ </body></html>
215 @ ');
216 ;
@@ -216,11 +218,12 @@
218 /*
219 ** A tan theme with the project title above the user identification
220 ** and no logo image.
221 */
222 static const char zBuiltinSkin2[] =
223 @ REPLACE INTO config(name,mtime,value)
224 @ VALUES('css',now(),'/* General settings for the entire page */
225 @ body {
226 @ margin: 0ex 0ex;
227 @ padding: 0px;
228 @ background-color: #fef3bc;
229 @ font-family: sans-serif;
@@ -354,11 +357,11 @@
357 @ vertical-align: top;
358 @ text-align: right;
359 @ padding: 0.2ex 2ex;
360 @ }
361 @ ');
362 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
363 @ <head>
364 @ <title>$<project_name>: $<title></title>
365 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
366 @ href="$home/timeline.rss">
367 @ <link rel="stylesheet" href="$home/style.css?tan" type="text/css"
@@ -405,11 +408,12 @@
408 @ } else {
409 @ html "<a href=''$home/login''>Login</a> "
410 @ }
411 @ </th1></div>
412 @ ');
413 @ REPLACE INTO config(name,mtime,value)
414 @ VALUES('footer',now(),'<div class="footer">
415 @ Fossil version $manifest_version $manifest_date
416 @ </div>
417 @ </body></html>
418 @ ');
419 ;
@@ -417,11 +421,12 @@
421 /*
422 ** Black letters on a white or cream background with the main menu
423 ** stuck on the left-hand side.
424 */
425 static const char zBuiltinSkin3[] =
426 @ REPLACE INTO config(name,mtime,value)
427 @ VALUES('css',now(),'/* General settings for the entire page */
428 @ body {
429 @ margin:0px 0px 0px 0px;
430 @ padding:0px;
431 @ font-family:verdana, arial, helvetica, "sans serif";
432 @ color:#333;
@@ -586,11 +591,11 @@
591 @ table.label-value th {
592 @ vertical-align: top;
593 @ text-align: right;
594 @ padding: 0.2ex 2ex;
595 @ }');
596 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
597 @ <head>
598 @ <title>$<project_name>: $<title></title>
599 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
600 @ href="$home/timeline.rss">
601 @ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
@@ -640,11 +645,11 @@
645 @ html "<li><a href=''$home/login''>Login</a></li>"
646 @ }
647 @ </th1></ul></div>
648 @ <div id="container">
649 @ ');
650 @ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div>
651 @ <div class="footer">
652 @ Fossil version $manifest_version $manifest_date
653 @ </div>
654 @ </body></html>
655 @ ');
@@ -653,11 +658,12 @@
658
659 /*
660 ** Gradients and rounded corners.
661 */
662 static const char zBuiltinSkin4[] =
663 @ REPLACE INTO config(name,mtime,value)
664 @ VALUES('css',now(),'/* General settings for the entire page */
665 @ html {
666 @ min-height: 100%;
667 @ }
668 @ body {
669 @ margin: 0ex 1ex;
@@ -880,11 +886,11 @@
886 @ }
887 @
888 @ textarea {
889 @ font-size: 1em;
890 @ }');
891 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
892 @ <head>
893 @ <title>$<project_name>: $<title></title>
894 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
895 @ href="$home/timeline.rss">
896 @ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
@@ -934,11 +940,11 @@
940 @ html "<a href=''$home/login''>Login</a>"
941 @ }
942 @ </th1></ul></div>
943 @ <div id="container">
944 @ ');
945 @ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div>
946 @ <div class="footer">
947 @ Fossil version $manifest_version $manifest_date
948 @ </div>
949 @ </body></html>
950 @ ');
@@ -984,17 +990,20 @@
990 ** Memory to hold the returned string is obtained from malloc.
991 */
992 static char *getSkin(int useDefault){
993 Blob val;
994 blob_zero(&val);
995 blob_appendf(&val,
996 "REPLACE INTO config(name,value,mtime) VALUES('css',%Q,now());\n",
997 useDefault ? zDefaultCSS : db_get("css", (char*)zDefaultCSS)
998 );
999 blob_appendf(&val,
1000 "REPLACE INTO config(name,value,mtime) VALUES('header',%Q,now());\n",
1001 useDefault ? zDefaultHeader : db_get("header", (char*)zDefaultHeader)
1002 );
1003 blob_appendf(&val,
1004 "REPLACE INTO config(name,value,mtime) VALUES('footer',%Q,now());\n",
1005 useDefault ? zDefaultFooter : db_get("footer", (char*)zDefaultFooter)
1006 );
1007 return blob_str(&val);
1008 }
1009
@@ -1048,11 +1057,11 @@
1057 if( db_exists("SELECT 1 FROM config WHERE name=%Q", zName)
1058 || strcmp(zName, "Default")==0 ){
1059 zErr = mprintf("Skin name \"%h\" already exists. "
1060 "Choose a different name.", P("sn"));
1061 }else{
1062 db_multi_exec("INSERT INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
1063 zName, zCurrent
1064 );
1065 }
1066 }
1067
@@ -1069,13 +1078,13 @@
1078 seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
1079 " AND value=%Q", zCurrent);
1080 }
1081 if( !seen ){
1082 db_multi_exec(
1083 "INSERT INTO config(name,value,mtime) VALUES("
1084 " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
1085 " %Q,now())", zCurrent
1086 );
1087 }
1088 seen = 0;
1089 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
1090 if( strcmp(aBuiltinSkin[i].zName, z)==0 ){
1091
+59
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -20,10 +20,11 @@
2020
** is a copy of the "shell.c" code from SQLite. This file contains logic
2121
** to initialize the code in shell.c.
2222
*/
2323
#include "config.h"
2424
#include "sqlcmd.h"
25
+#include <zlib.h>
2526
2627
/*
2728
** Implementation of the "content(X)" SQL function. Return the complete
2829
** content of artifact identified by X as a blob.
2930
*/
@@ -46,10 +47,64 @@
4647
sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx),
4748
SQLITE_TRANSIENT);
4849
blob_reset(&cx);
4950
}
5051
}
52
+
53
+/*
54
+** Implementation of the "compress(X)" SQL function. The input X is
55
+** compressed using zLib and the output is returned.
56
+*/
57
+static void sqlcmd_compress(
58
+ sqlite3_context *context,
59
+ int argc,
60
+ sqlite3_value **argv
61
+){
62
+ const unsigned char *pIn;
63
+ unsigned char *pOut;
64
+ unsigned int nIn;
65
+ unsigned long int nOut;
66
+
67
+ pIn = sqlite3_value_blob(argv[0]);
68
+ nIn = sqlite3_value_bytes(argv[0]);
69
+ nOut = 13 + nIn + (nIn+999)/1000;
70
+ pOut = sqlite3_malloc( nOut+4 );
71
+ pOut[0] = nIn>>24 & 0xff;
72
+ pOut[1] = nIn>>16 & 0xff;
73
+ pOut[2] = nIn>>8 & 0xff;
74
+ pOut[3] = nIn & 0xff;
75
+ compress(&pOut[4], &nOut, pIn, nIn);
76
+ sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free);
77
+}
78
+
79
+/*
80
+** Implementation of the "uncontent(X)" SQL function. The argument X
81
+** is a blob which was obtained from compress(Y). The output will be
82
+** the value Y.
83
+*/
84
+static void sqlcmd_decompress(
85
+ sqlite3_context *context,
86
+ int argc,
87
+ sqlite3_value **argv
88
+){
89
+ const unsigned char *pIn;
90
+ unsigned char *pOut;
91
+ unsigned int nIn;
92
+ unsigned long int nOut;
93
+ int rc;
94
+
95
+ pIn = sqlite3_value_blob(argv[0]);
96
+ nIn = sqlite3_value_bytes(argv[0]);
97
+ nOut = (pIn[0]<<24) + (pIn[1]<<16) + (pIn[2]<<8) + pIn[3];
98
+ pOut = sqlite3_malloc( nOut+1 );
99
+ rc = uncompress(pOut, &nOut, &pIn[4], nIn-4);
100
+ if( rc==Z_OK ){
101
+ sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
102
+ }else{
103
+ sqlite3_result_error(context, "input is not zlib compressed", -1);
104
+ }
105
+}
51106
52107
/*
53108
** This is the "automatic extensionn" initializer that runs right after
54109
** the connection to the repository database is opened. Set up the
55110
** database connection to be more useful to the human operator.
@@ -59,10 +114,14 @@
59114
const char **pzErrMsg,
60115
const void *notUsed
61116
){
62117
sqlite3_create_function(db, "content", 1, SQLITE_ANY, 0,
63118
sqlcmd_content, 0, 0);
119
+ sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0,
120
+ sqlcmd_compress, 0, 0);
121
+ sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0,
122
+ sqlcmd_decompress, 0, 0);
64123
return SQLITE_OK;
65124
}
66125
67126
68127
/*
69128
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -20,10 +20,11 @@
20 ** is a copy of the "shell.c" code from SQLite. This file contains logic
21 ** to initialize the code in shell.c.
22 */
23 #include "config.h"
24 #include "sqlcmd.h"
 
25
26 /*
27 ** Implementation of the "content(X)" SQL function. Return the complete
28 ** content of artifact identified by X as a blob.
29 */
@@ -46,10 +47,64 @@
46 sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx),
47 SQLITE_TRANSIENT);
48 blob_reset(&cx);
49 }
50 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
52 /*
53 ** This is the "automatic extensionn" initializer that runs right after
54 ** the connection to the repository database is opened. Set up the
55 ** database connection to be more useful to the human operator.
@@ -59,10 +114,14 @@
59 const char **pzErrMsg,
60 const void *notUsed
61 ){
62 sqlite3_create_function(db, "content", 1, SQLITE_ANY, 0,
63 sqlcmd_content, 0, 0);
 
 
 
 
64 return SQLITE_OK;
65 }
66
67
68 /*
69
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -20,10 +20,11 @@
20 ** is a copy of the "shell.c" code from SQLite. This file contains logic
21 ** to initialize the code in shell.c.
22 */
23 #include "config.h"
24 #include "sqlcmd.h"
25 #include <zlib.h>
26
27 /*
28 ** Implementation of the "content(X)" SQL function. Return the complete
29 ** content of artifact identified by X as a blob.
30 */
@@ -46,10 +47,64 @@
47 sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx),
48 SQLITE_TRANSIENT);
49 blob_reset(&cx);
50 }
51 }
52
53 /*
54 ** Implementation of the "compress(X)" SQL function. The input X is
55 ** compressed using zLib and the output is returned.
56 */
57 static void sqlcmd_compress(
58 sqlite3_context *context,
59 int argc,
60 sqlite3_value **argv
61 ){
62 const unsigned char *pIn;
63 unsigned char *pOut;
64 unsigned int nIn;
65 unsigned long int nOut;
66
67 pIn = sqlite3_value_blob(argv[0]);
68 nIn = sqlite3_value_bytes(argv[0]);
69 nOut = 13 + nIn + (nIn+999)/1000;
70 pOut = sqlite3_malloc( nOut+4 );
71 pOut[0] = nIn>>24 & 0xff;
72 pOut[1] = nIn>>16 & 0xff;
73 pOut[2] = nIn>>8 & 0xff;
74 pOut[3] = nIn & 0xff;
75 compress(&pOut[4], &nOut, pIn, nIn);
76 sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free);
77 }
78
79 /*
80 ** Implementation of the "uncontent(X)" SQL function. The argument X
81 ** is a blob which was obtained from compress(Y). The output will be
82 ** the value Y.
83 */
84 static void sqlcmd_decompress(
85 sqlite3_context *context,
86 int argc,
87 sqlite3_value **argv
88 ){
89 const unsigned char *pIn;
90 unsigned char *pOut;
91 unsigned int nIn;
92 unsigned long int nOut;
93 int rc;
94
95 pIn = sqlite3_value_blob(argv[0]);
96 nIn = sqlite3_value_bytes(argv[0]);
97 nOut = (pIn[0]<<24) + (pIn[1]<<16) + (pIn[2]<<8) + pIn[3];
98 pOut = sqlite3_malloc( nOut+1 );
99 rc = uncompress(pOut, &nOut, &pIn[4], nIn-4);
100 if( rc==Z_OK ){
101 sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
102 }else{
103 sqlite3_result_error(context, "input is not zlib compressed", -1);
104 }
105 }
106
107 /*
108 ** This is the "automatic extensionn" initializer that runs right after
109 ** the connection to the repository database is opened. Set up the
110 ** database connection to be more useful to the human operator.
@@ -59,10 +114,14 @@
114 const char **pzErrMsg,
115 const void *notUsed
116 ){
117 sqlite3_create_function(db, "content", 1, SQLITE_ANY, 0,
118 sqlcmd_content, 0, 0);
119 sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0,
120 sqlcmd_compress, 0, 0);
121 sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0,
122 sqlcmd_decompress, 0, 0);
123 return SQLITE_OK;
124 }
125
126
127 /*
128
+1584 -416
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.7.6. By combining all the individual C code files into this
3
+** version 3.7.7. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -648,13 +648,13 @@
648648
**
649649
** See also: [sqlite3_libversion()],
650650
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651651
** [sqlite_version()] and [sqlite_source_id()].
652652
*/
653
-#define SQLITE_VERSION "3.7.6"
654
-#define SQLITE_VERSION_NUMBER 3007006
655
-#define SQLITE_SOURCE_ID "2011-04-12 01:58:40 f9d43fa363d54beab6f45db005abac0a7c0c47a7"
653
+#define SQLITE_VERSION "3.7.7"
654
+#define SQLITE_VERSION_NUMBER 3007007
655
+#define SQLITE_SOURCE_ID "2011-05-20 01:50:01 2018d4e108872f2436df046636401b89cfde589d"
656656
657657
/*
658658
** CAPI3REF: Run-Time Library Version Numbers
659659
** KEYWORDS: sqlite3_version, sqlite3_sourceid
660660
**
@@ -916,11 +916,12 @@
916916
** Many SQLite functions return an integer result code from the set shown
917917
** here in order to indicates success or failure.
918918
**
919919
** New error codes may be added in future versions of SQLite.
920920
**
921
-** See also: [SQLITE_IOERR_READ | extended result codes]
921
+** See also: [SQLITE_IOERR_READ | extended result codes],
922
+** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
922923
*/
923924
#define SQLITE_OK 0 /* Successful result */
924925
/* beginning-of-error-codes */
925926
#define SQLITE_ERROR 1 /* SQL error or missing database */
926927
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -993,28 +994,31 @@
993994
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
994995
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
995996
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
996997
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
997998
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
999
+#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
1000
+#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
9981001
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
9991002
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
10001003
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
1004
+#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
10011005
10021006
/*
10031007
** CAPI3REF: Flags For File Open Operations
10041008
**
10051009
** These bit values are intended for use in the
10061010
** 3rd parameter to the [sqlite3_open_v2()] interface and
1007
-** in the 4th parameter to the xOpen method of the
1008
-** [sqlite3_vfs] object.
1011
+** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
10091012
*/
10101013
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
10111014
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
10121015
#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
10131016
#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
10141017
#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
10151018
#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
1019
+#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
10161020
#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
10171021
#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
10181022
#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
10191023
#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
10201024
#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
@@ -1121,21 +1125,22 @@
11211125
};
11221126
11231127
/*
11241128
** CAPI3REF: OS Interface File Virtual Methods Object
11251129
**
1126
-** Every file opened by the [sqlite3_vfs] xOpen method populates an
1130
+** Every file opened by the [sqlite3_vfs.xOpen] method populates an
11271131
** [sqlite3_file] object (or, more commonly, a subclass of the
11281132
** [sqlite3_file] object) with a pointer to an instance of this object.
11291133
** This object defines the methods used to perform various operations
11301134
** against the open file represented by the [sqlite3_file] object.
11311135
**
1132
-** If the xOpen method sets the sqlite3_file.pMethods element
1136
+** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
11331137
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
1134
-** may be invoked even if the xOpen reported that it failed. The
1135
-** only way to prevent a call to xClose following a failed xOpen
1136
-** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
1138
+** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
1139
+** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
1140
+** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
1141
+** to NULL.
11371142
**
11381143
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
11391144
** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
11401145
** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
11411146
** flag may be ORed in to indicate that only the data of the file
@@ -1300,10 +1305,11 @@
13001305
*/
13011306
typedef struct sqlite3_mutex sqlite3_mutex;
13021307
13031308
/*
13041309
** CAPI3REF: OS Interface Object
1310
+** KEYWORDS: VFS VFSes
13051311
**
13061312
** An instance of the sqlite3_vfs object defines the interface between
13071313
** the SQLite core and the underlying operating system. The "vfs"
13081314
** in the name of the object stands for "virtual file system".
13091315
**
@@ -1332,10 +1338,11 @@
13321338
** object once the object has been registered.
13331339
**
13341340
** The zName field holds the name of the VFS module. The name must
13351341
** be unique across all VFS modules.
13361342
**
1343
+** [[sqlite3_vfs.xOpen]]
13371344
** ^SQLite guarantees that the zFilename parameter to xOpen
13381345
** is either a NULL pointer or string obtained
13391346
** from xFullPathname() with an optional suffix added.
13401347
** ^If a suffix is added to the zFilename parameter, it will
13411348
** consist of a single "-" character followed by no more than
@@ -1409,10 +1416,11 @@
14091416
** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
14101417
** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
14111418
** element will be valid after xOpen returns regardless of the success
14121419
** or failure of the xOpen call.
14131420
**
1421
+** [[sqlite3_vfs.xAccess]]
14141422
** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
14151423
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
14161424
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
14171425
** to test whether a file is at least readable. The file can be a
14181426
** directory.
@@ -1655,13 +1663,13 @@
16551663
** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
16561664
** Note, however, that ^sqlite3_config() can be called as part of the
16571665
** implementation of an application-defined [sqlite3_os_init()].
16581666
**
16591667
** The first argument to sqlite3_config() is an integer
1660
-** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
1668
+** [configuration option] that determines
16611669
** what property of SQLite is to be configured. Subsequent arguments
1662
-** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
1670
+** vary depending on the [configuration option]
16631671
** in the first argument.
16641672
**
16651673
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
16661674
** ^If the option is unknown or SQLite is unable to set the option
16671675
** then this routine returns a non-zero [error code].
@@ -1767,10 +1775,11 @@
17671775
void *pAppData; /* Argument to xInit() and xShutdown() */
17681776
};
17691777
17701778
/*
17711779
** CAPI3REF: Configuration Options
1780
+** KEYWORDS: {configuration option}
17721781
**
17731782
** These constants are the available integer configuration options that
17741783
** can be passed as the first argument to the [sqlite3_config()] interface.
17751784
**
17761785
** New configuration options may be added in future releases of SQLite.
@@ -1779,11 +1788,11 @@
17791788
** the call worked. The [sqlite3_config()] interface will return a
17801789
** non-zero [error code] if a discontinued or unsupported configuration option
17811790
** is invoked.
17821791
**
17831792
** <dl>
1784
-** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
1793
+** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
17851794
** <dd>There are no arguments to this option. ^This option sets the
17861795
** [threading mode] to Single-thread. In other words, it disables
17871796
** all mutexing and puts SQLite into a mode where it can only be used
17881797
** by a single thread. ^If SQLite is compiled with
17891798
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
@@ -1790,11 +1799,11 @@
17901799
** it is not possible to change the [threading mode] from its default
17911800
** value of Single-thread and so [sqlite3_config()] will return
17921801
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
17931802
** configuration option.</dd>
17941803
**
1795
-** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
1804
+** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
17961805
** <dd>There are no arguments to this option. ^This option sets the
17971806
** [threading mode] to Multi-thread. In other words, it disables
17981807
** mutexing on [database connection] and [prepared statement] objects.
17991808
** The application is responsible for serializing access to
18001809
** [database connections] and [prepared statements]. But other mutexes
@@ -1804,11 +1813,11 @@
18041813
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
18051814
** it is not possible to set the Multi-thread [threading mode] and
18061815
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
18071816
** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
18081817
**
1809
-** <dt>SQLITE_CONFIG_SERIALIZED</dt>
1818
+** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
18101819
** <dd>There are no arguments to this option. ^This option sets the
18111820
** [threading mode] to Serialized. In other words, this option enables
18121821
** all mutexes including the recursive
18131822
** mutexes on [database connection] and [prepared statement] objects.
18141823
** In this mode (which is the default when SQLite is compiled with
@@ -1820,27 +1829,27 @@
18201829
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
18211830
** it is not possible to set the Serialized [threading mode] and
18221831
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
18231832
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
18241833
**
1825
-** <dt>SQLITE_CONFIG_MALLOC</dt>
1834
+** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
18261835
** <dd> ^(This option takes a single argument which is a pointer to an
18271836
** instance of the [sqlite3_mem_methods] structure. The argument specifies
18281837
** alternative low-level memory allocation routines to be used in place of
18291838
** the memory allocation routines built into SQLite.)^ ^SQLite makes
18301839
** its own private copy of the content of the [sqlite3_mem_methods] structure
18311840
** before the [sqlite3_config()] call returns.</dd>
18321841
**
1833
-** <dt>SQLITE_CONFIG_GETMALLOC</dt>
1842
+** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
18341843
** <dd> ^(This option takes a single argument which is a pointer to an
18351844
** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
18361845
** structure is filled with the currently defined memory allocation routines.)^
18371846
** This option can be used to overload the default memory allocation
18381847
** routines with a wrapper that simulations memory allocation failure or
18391848
** tracks memory usage, for example. </dd>
18401849
**
1841
-** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
1850
+** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
18421851
** <dd> ^This option takes single argument of type int, interpreted as a
18431852
** boolean, which enables or disables the collection of memory allocation
18441853
** statistics. ^(When memory allocation statistics are disabled, the
18451854
** following SQLite interfaces become non-operational:
18461855
** <ul>
@@ -1852,11 +1861,11 @@
18521861
** ^Memory allocation statistics are enabled by default unless SQLite is
18531862
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
18541863
** allocation statistics are disabled by default.
18551864
** </dd>
18561865
**
1857
-** <dt>SQLITE_CONFIG_SCRATCH</dt>
1866
+** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
18581867
** <dd> ^This option specifies a static memory buffer that SQLite can use for
18591868
** scratch memory. There are three arguments: A pointer an 8-byte
18601869
** aligned memory buffer from which the scratch allocations will be
18611870
** drawn, the size of each scratch allocation (sz),
18621871
** and the maximum number of scratch allocations (N). The sz
@@ -1868,11 +1877,11 @@
18681877
** ^SQLite will never require a scratch buffer that is more than 6
18691878
** times the database page size. ^If SQLite needs needs additional
18701879
** scratch memory beyond what is provided by this configuration option, then
18711880
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
18721881
**
1873
-** <dt>SQLITE_CONFIG_PAGECACHE</dt>
1882
+** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
18741883
** <dd> ^This option specifies a static memory buffer that SQLite can use for
18751884
** the database page cache with the default page cache implemenation.
18761885
** This configuration should not be used if an application-define page
18771886
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
18781887
** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1889,11 +1898,11 @@
18891898
** SQLite goes to [sqlite3_malloc()] for the additional storage space.
18901899
** The pointer in the first argument must
18911900
** be aligned to an 8-byte boundary or subsequent behavior of SQLite
18921901
** will be undefined.</dd>
18931902
**
1894
-** <dt>SQLITE_CONFIG_HEAP</dt>
1903
+** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
18951904
** <dd> ^This option specifies a static memory buffer that SQLite will use
18961905
** for all of its dynamic memory allocation needs beyond those provided
18971906
** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
18981907
** There are three arguments: An 8-byte aligned pointer to the memory,
18991908
** the number of bytes in the memory buffer, and the minimum allocation size.
@@ -1906,11 +1915,11 @@
19061915
** The first pointer (the memory pointer) must be aligned to an 8-byte
19071916
** boundary or subsequent behavior of SQLite will be undefined.
19081917
** The minimum allocation size is capped at 2^12. Reasonable values
19091918
** for the minimum allocation size are 2^5 through 2^8.</dd>
19101919
**
1911
-** <dt>SQLITE_CONFIG_MUTEX</dt>
1920
+** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
19121921
** <dd> ^(This option takes a single argument which is a pointer to an
19131922
** instance of the [sqlite3_mutex_methods] structure. The argument specifies
19141923
** alternative low-level mutex routines to be used in place
19151924
** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
19161925
** content of the [sqlite3_mutex_methods] structure before the call to
@@ -1918,11 +1927,11 @@
19181927
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
19191928
** the entire mutexing subsystem is omitted from the build and hence calls to
19201929
** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
19211930
** return [SQLITE_ERROR].</dd>
19221931
**
1923
-** <dt>SQLITE_CONFIG_GETMUTEX</dt>
1932
+** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
19241933
** <dd> ^(This option takes a single argument which is a pointer to an
19251934
** instance of the [sqlite3_mutex_methods] structure. The
19261935
** [sqlite3_mutex_methods]
19271936
** structure is filled with the currently defined mutex routines.)^
19281937
** This option can be used to overload the default mutex allocation
@@ -1931,32 +1940,32 @@
19311940
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
19321941
** the entire mutexing subsystem is omitted from the build and hence calls to
19331942
** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
19341943
** return [SQLITE_ERROR].</dd>
19351944
**
1936
-** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
1945
+** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
19371946
** <dd> ^(This option takes two arguments that determine the default
19381947
** memory allocation for the lookaside memory allocator on each
19391948
** [database connection]. The first argument is the
19401949
** size of each lookaside buffer slot and the second is the number of
19411950
** slots allocated to each database connection.)^ ^(This option sets the
19421951
** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
19431952
** verb to [sqlite3_db_config()] can be used to change the lookaside
19441953
** configuration on individual connections.)^ </dd>
19451954
**
1946
-** <dt>SQLITE_CONFIG_PCACHE</dt>
1955
+** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
19471956
** <dd> ^(This option takes a single argument which is a pointer to
19481957
** an [sqlite3_pcache_methods] object. This object specifies the interface
19491958
** to a custom page cache implementation.)^ ^SQLite makes a copy of the
19501959
** object and uses it for page cache memory allocations.</dd>
19511960
**
1952
-** <dt>SQLITE_CONFIG_GETPCACHE</dt>
1961
+** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
19531962
** <dd> ^(This option takes a single argument which is a pointer to an
19541963
** [sqlite3_pcache_methods] object. SQLite copies of the current
19551964
** page cache implementation into that object.)^ </dd>
19561965
**
1957
-** <dt>SQLITE_CONFIG_LOG</dt>
1966
+** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
19581967
** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
19591968
** function with a call signature of void(*)(void*,int,const char*),
19601969
** and a pointer to void. ^If the function pointer is not NULL, it is
19611970
** invoked by [sqlite3_log()] to process each logging event. ^If the
19621971
** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
@@ -1970,10 +1979,22 @@
19701979
** The SQLite logging interface is not reentrant; the logger function
19711980
** supplied by the application must not invoke any SQLite interface.
19721981
** In a multi-threaded application, the application-defined logger
19731982
** function must be threadsafe. </dd>
19741983
**
1984
+** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
1985
+** <dd> This option takes a single argument of type int. If non-zero, then
1986
+** URI handling is globally enabled. If the parameter is zero, then URI handling
1987
+** is globally disabled. If URI handling is globally enabled, all filenames
1988
+** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
1989
+** specified as part of [ATTACH] commands are interpreted as URIs, regardless
1990
+** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
1991
+** connection is opened. If it is globally disabled, filenames are
1992
+** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
1993
+** database connection is opened. By default, URI handling is globally
1994
+** disabled. The default value may be changed by compiling with the
1995
+** [SQLITE_USE_URI] symbol defined.
19751996
** </dl>
19761997
*/
19771998
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
19781999
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
19792000
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1988,10 +2009,11 @@
19882009
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
19892010
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
19902011
#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
19912012
#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
19922013
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
2014
+#define SQLITE_CONFIG_URI 17 /* int */
19932015
19942016
/*
19952017
** CAPI3REF: Database Connection Configuration Options
19962018
**
19972019
** These constants are the available integer configuration options that
@@ -2073,17 +2095,21 @@
20732095
** the table has a column of type [INTEGER PRIMARY KEY] then that column
20742096
** is another alias for the rowid.
20752097
**
20762098
** ^This routine returns the [rowid] of the most recent
20772099
** successful [INSERT] into the database from the [database connection]
2078
-** in the first argument. ^If no successful [INSERT]s
2100
+** in the first argument. ^As of SQLite version 3.7.7, this routines
2101
+** records the last insert rowid of both ordinary tables and [virtual tables].
2102
+** ^If no successful [INSERT]s
20792103
** have ever occurred on that database connection, zero is returned.
20802104
**
2081
-** ^(If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
2082
-** row is returned by this routine as long as the trigger is running.
2083
-** But once the trigger terminates, the value returned by this routine
2084
-** reverts to the last value inserted before the trigger fired.)^
2105
+** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
2106
+** method, then this routine will return the [rowid] of the inserted
2107
+** row as long as the trigger or virtual table method is running.
2108
+** But once the trigger or virtual table method ends, the value returned
2109
+** by this routine reverts to what it was before the trigger or virtual
2110
+** table method began.)^
20852111
**
20862112
** ^An [INSERT] that fails due to a constraint violation is not a
20872113
** successful [INSERT] and does not change the value returned by this
20882114
** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
20892115
** and INSERT OR ABORT make no changes to the return value of this
@@ -2742,10 +2768,13 @@
27422768
** The [sqlite3_set_authorizer | authorizer callback function] must
27432769
** return either [SQLITE_OK] or one of these two constants in order
27442770
** to signal SQLite whether or not the action is permitted. See the
27452771
** [sqlite3_set_authorizer | authorizer documentation] for additional
27462772
** information.
2773
+**
2774
+** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
2775
+** from the [sqlite3_vtab_on_conflict()] interface.
27472776
*/
27482777
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
27492778
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
27502779
27512780
/*
@@ -2864,11 +2893,11 @@
28642893
SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
28652894
28662895
/*
28672896
** CAPI3REF: Opening A New Database Connection
28682897
**
2869
-** ^These routines open an SQLite database file whose name is given by the
2898
+** ^These routines open an SQLite database file as specified by the
28702899
** filename argument. ^The filename argument is interpreted as UTF-8 for
28712900
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
28722901
** order for sqlite3_open16(). ^(A [database connection] handle is usually
28732902
** returned in *ppDb, even if an error occurs. The only exception is that
28742903
** if SQLite is unable to allocate memory to hold the [sqlite3] object,
@@ -2891,11 +2920,11 @@
28912920
** except that it accepts two additional parameters for additional control
28922921
** over the new database connection. ^(The flags parameter to
28932922
** sqlite3_open_v2() can take one of
28942923
** the following three values, optionally combined with the
28952924
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
2896
-** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
2925
+** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
28972926
**
28982927
** <dl>
28992928
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
29002929
** <dd>The database is opened in read-only mode. If the database does not
29012930
** already exist, an error is returned.</dd>)^
@@ -2910,13 +2939,12 @@
29102939
** it does not already exist. This is the behavior that is always used for
29112940
** sqlite3_open() and sqlite3_open16().</dd>)^
29122941
** </dl>
29132942
**
29142943
** If the 3rd parameter to sqlite3_open_v2() is not one of the
2915
-** combinations shown above or one of the combinations shown above combined
2916
-** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX],
2917
-** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags,
2944
+** combinations shown above optionally combined with other
2945
+** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
29182946
** then the behavior is undefined.
29192947
**
29202948
** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
29212949
** opens in the multi-thread [threading mode] as long as the single-thread
29222950
** mode has not been set at compile-time or start-time. ^If the
@@ -2926,10 +2954,15 @@
29262954
** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
29272955
** eligible to use [shared cache mode], regardless of whether or not shared
29282956
** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
29292957
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
29302958
** participate in [shared cache mode] even if it is enabled.
2959
+**
2960
+** ^The fourth parameter to sqlite3_open_v2() is the name of the
2961
+** [sqlite3_vfs] object that defines the operating system interface that
2962
+** the new database connection should use. ^If the fourth parameter is
2963
+** a NULL pointer then the default [sqlite3_vfs] object is used.
29312964
**
29322965
** ^If the filename is ":memory:", then a private, temporary in-memory database
29332966
** is created for the connection. ^This in-memory database will vanish when
29342967
** the database connection is closed. Future versions of SQLite might
29352968
** make use of additional special filenames that begin with the ":" character.
@@ -2939,14 +2972,115 @@
29392972
**
29402973
** ^If the filename is an empty string, then a private, temporary
29412974
** on-disk database will be created. ^This private database will be
29422975
** automatically deleted as soon as the database connection is closed.
29432976
**
2944
-** ^The fourth parameter to sqlite3_open_v2() is the name of the
2945
-** [sqlite3_vfs] object that defines the operating system interface that
2946
-** the new database connection should use. ^If the fourth parameter is
2947
-** a NULL pointer then the default [sqlite3_vfs] object is used.
2977
+** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
2978
+**
2979
+** ^If [URI filename] interpretation is enabled, and the filename argument
2980
+** begins with "file:", then the filename is interpreted as a URI. ^URI
2981
+** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2982
+** is set in the fourth argument to sqlite3_open_v2(), or if it has
2983
+** been enabled globally using the [SQLITE_CONFIG_URI] option with the
2984
+** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
2985
+** As of SQLite version 3.7.7, URI filename interpretation is turned off
2986
+** by default, but future releases of SQLite might enable URI filename
2987
+** intepretation by default. See "[URI filenames]" for additional
2988
+** information.
2989
+**
2990
+** URI filenames are parsed according to RFC 3986. ^If the URI contains an
2991
+** authority, then it must be either an empty string or the string
2992
+** "localhost". ^If the authority is not an empty string or "localhost", an
2993
+** error is returned to the caller. ^The fragment component of a URI, if
2994
+** present, is ignored.
2995
+**
2996
+** ^SQLite uses the path component of the URI as the name of the disk file
2997
+** which contains the database. ^If the path begins with a '/' character,
2998
+** then it is interpreted as an absolute path. ^If the path does not begin
2999
+** with a '/' (meaning that the authority section is omitted from the URI)
3000
+** then the path is interpreted as a relative path.
3001
+** ^On windows, the first component of an absolute path
3002
+** is a drive specification (e.g. "C:").
3003
+**
3004
+** [[core URI query parameters]]
3005
+** The query component of a URI may contain parameters that are interpreted
3006
+** either by SQLite itself, or by a [VFS | custom VFS implementation].
3007
+** SQLite interprets the following three query parameters:
3008
+**
3009
+** <ul>
3010
+** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
3011
+** a VFS object that provides the operating system interface that should
3012
+** be used to access the database file on disk. ^If this option is set to
3013
+** an empty string the default VFS object is used. ^Specifying an unknown
3014
+** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
3015
+** present, then the VFS specified by the option takes precedence over
3016
+** the value passed as the fourth parameter to sqlite3_open_v2().
3017
+**
3018
+** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
3019
+** "rwc". Attempting to set it to any other value is an error)^.
3020
+** ^If "ro" is specified, then the database is opened for read-only
3021
+** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
3022
+** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
3023
+** "rw", then the database is opened for read-write (but not create)
3024
+** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
3025
+** been set. ^Value "rwc" is equivalent to setting both
3026
+** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
3027
+** used, it is an error to specify a value for the mode parameter that is
3028
+** less restrictive than that specified by the flags passed as the third
3029
+** parameter.
3030
+**
3031
+** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
3032
+** "private". ^Setting it to "shared" is equivalent to setting the
3033
+** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
3034
+** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
3035
+** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
3036
+** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
3037
+** a URI filename, its value overrides any behaviour requested by setting
3038
+** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
3039
+** </ul>
3040
+**
3041
+** ^Specifying an unknown parameter in the query component of a URI is not an
3042
+** error. Future versions of SQLite might understand additional query
3043
+** parameters. See "[query parameters with special meaning to SQLite]" for
3044
+** additional information.
3045
+**
3046
+** [[URI filename examples]] <h3>URI filename examples</h3>
3047
+**
3048
+** <table border="1" align=center cellpadding=5>
3049
+** <tr><th> URI filenames <th> Results
3050
+** <tr><td> file:data.db <td>
3051
+** Open the file "data.db" in the current directory.
3052
+** <tr><td> file:/home/fred/data.db<br>
3053
+** file:///home/fred/data.db <br>
3054
+** file://localhost/home/fred/data.db <br> <td>
3055
+** Open the database file "/home/fred/data.db".
3056
+** <tr><td> file://darkstar/home/fred/data.db <td>
3057
+** An error. "darkstar" is not a recognized authority.
3058
+** <tr><td style="white-space:nowrap">
3059
+** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
3060
+** <td> Windows only: Open the file "data.db" on fred's desktop on drive
3061
+** C:. Note that the %20 escaping in this example is not strictly
3062
+** necessary - space characters can be used literally
3063
+** in URI filenames.
3064
+** <tr><td> file:data.db?mode=ro&cache=private <td>
3065
+** Open file "data.db" in the current directory for read-only access.
3066
+** Regardless of whether or not shared-cache mode is enabled by
3067
+** default, use a private cache.
3068
+** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
3069
+** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
3070
+** <tr><td> file:data.db?mode=readonly <td>
3071
+** An error. "readonly" is not a valid option for the "mode" parameter.
3072
+** </table>
3073
+**
3074
+** ^URI hexadecimal escape sequences (%HH) are supported within the path and
3075
+** query components of a URI. A hexadecimal escape sequence consists of a
3076
+** percent sign - "%" - followed by exactly two hexadecimal digits
3077
+** specifying an octet value. ^Before the path or query components of a
3078
+** URI filename are interpreted, they are encoded using UTF-8 and all
3079
+** hexadecimal escape sequences replaced by a single byte containing the
3080
+** corresponding octet. If this process generates an invalid UTF-8 encoding,
3081
+** the results are undefined.
29483082
**
29493083
** <b>Note to Windows users:</b> The encoding used for the filename argument
29503084
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
29513085
** codepage is currently defined. Filenames containing international
29523086
** characters must be converted to UTF-8 prior to passing them into
@@ -2964,10 +3098,30 @@
29643098
const char *filename, /* Database filename (UTF-8) */
29653099
sqlite3 **ppDb, /* OUT: SQLite db handle */
29663100
int flags, /* Flags */
29673101
const char *zVfs /* Name of VFS module to use */
29683102
);
3103
+
3104
+/*
3105
+** CAPI3REF: Obtain Values For URI Parameters
3106
+**
3107
+** This is a utility routine, useful to VFS implementations, that checks
3108
+** to see if a database file was a URI that contained a specific query
3109
+** parameter, and if so obtains the value of the query parameter.
3110
+**
3111
+** The zFilename argument is the filename pointer passed into the xOpen()
3112
+** method of a VFS implementation. The zParam argument is the name of the
3113
+** query parameter we seek. This routine returns the value of the zParam
3114
+** parameter if it exists. If the parameter does not exist, this routine
3115
+** returns a NULL pointer.
3116
+**
3117
+** If the zFilename argument to this function is not a pointer that SQLite
3118
+** passed into the xOpen VFS method, then the behavior of this routine
3119
+** is undefined and probably undesirable.
3120
+*/
3121
+SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
3122
+
29693123
29703124
/*
29713125
** CAPI3REF: Error Codes And Messages
29723126
**
29733127
** ^The sqlite3_errcode() interface returns the numeric [result code] or
@@ -3080,47 +3234,49 @@
30803234
** that can be lowered at run-time using [sqlite3_limit()].
30813235
** The synopsis of the meanings of the various limits is shown below.
30823236
** Additional information is available at [limits | Limits in SQLite].
30833237
**
30843238
** <dl>
3085
-** ^(<dt>SQLITE_LIMIT_LENGTH</dt>
3239
+** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
30863240
** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
30873241
**
3088
-** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
3242
+** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
30893243
** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
30903244
**
3091
-** ^(<dt>SQLITE_LIMIT_COLUMN</dt>
3245
+** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
30923246
** <dd>The maximum number of columns in a table definition or in the
30933247
** result set of a [SELECT] or the maximum number of columns in an index
30943248
** or in an ORDER BY or GROUP BY clause.</dd>)^
30953249
**
3096
-** ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
3250
+** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
30973251
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
30983252
**
3099
-** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
3253
+** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
31003254
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
31013255
**
3102
-** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
3256
+** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
31033257
** <dd>The maximum number of instructions in a virtual machine program
31043258
** used to implement an SQL statement. This limit is not currently
31053259
** enforced, though that might be added in some future release of
31063260
** SQLite.</dd>)^
31073261
**
3108
-** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
3262
+** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
31093263
** <dd>The maximum number of arguments on a function.</dd>)^
31103264
**
3111
-** ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
3265
+** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
31123266
** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
31133267
**
3268
+** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
31143269
** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
31153270
** <dd>The maximum length of the pattern argument to the [LIKE] or
31163271
** [GLOB] operators.</dd>)^
31173272
**
3273
+** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
31183274
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
31193275
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
31203276
**
3121
-** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
3277
+** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
31223278
** <dd>The maximum depth of recursion for triggers.</dd>)^
31233279
** </dl>
31243280
*/
31253281
#define SQLITE_LIMIT_LENGTH 0
31263282
#define SQLITE_LIMIT_SQL_LENGTH 1
@@ -5151,10 +5307,15 @@
51515307
int (*xRollback)(sqlite3_vtab *pVTab);
51525308
int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
51535309
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
51545310
void **ppArg);
51555311
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
5312
+ /* The methods above are in version 1 of the sqlite_module object. Those
5313
+ ** below are for version 2 and greater. */
5314
+ int (*xSavepoint)(sqlite3_vtab *pVTab, int);
5315
+ int (*xRelease)(sqlite3_vtab *pVTab, int);
5316
+ int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
51565317
};
51575318
51585319
/*
51595320
** CAPI3REF: Virtual Table Indexing Information
51605321
** KEYWORDS: sqlite3_index_info
@@ -5965,11 +6126,11 @@
59656126
**
59666127
** ^This interface is used to retrieve runtime status information
59676128
** about the performance of SQLite, and optionally to reset various
59686129
** highwater marks. ^The first argument is an integer code for
59696130
** the specific parameter to measure. ^(Recognized integer codes
5970
-** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
6131
+** are of the form [status parameters | SQLITE_STATUS_...].)^
59716132
** ^The current value of the parameter is returned into *pCurrent.
59726133
** ^The highest recorded value is returned in *pHighwater. ^If the
59736134
** resetFlag is true, then the highest record value is reset after
59746135
** *pHighwater is written. ^(Some parameters do not record the highest
59756136
** value. For those parameters
@@ -5992,82 +6153,84 @@
59926153
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
59936154
59946155
59956156
/*
59966157
** CAPI3REF: Status Parameters
6158
+** KEYWORDS: {status parameters}
59976159
**
59986160
** These integer constants designate various run-time status parameters
59996161
** that can be returned by [sqlite3_status()].
60006162
**
60016163
** <dl>
6002
-** ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
6164
+** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
60036165
** <dd>This parameter is the current amount of memory checked out
60046166
** using [sqlite3_malloc()], either directly or indirectly. The
60056167
** figure includes calls made to [sqlite3_malloc()] by the application
60066168
** and internal memory usage by the SQLite library. Scratch memory
60076169
** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
60086170
** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
60096171
** this parameter. The amount returned is the sum of the allocation
60106172
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
60116173
**
6012
-** ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
6174
+** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
60136175
** <dd>This parameter records the largest memory allocation request
60146176
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
60156177
** internal equivalents). Only the value returned in the
60166178
** *pHighwater parameter to [sqlite3_status()] is of interest.
60176179
** The value written into the *pCurrent parameter is undefined.</dd>)^
60186180
**
6019
-** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
6181
+** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
60206182
** <dd>This parameter records the number of separate memory allocations
60216183
** currently checked out.</dd>)^
60226184
**
6023
-** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
6185
+** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
60246186
** <dd>This parameter returns the number of pages used out of the
60256187
** [pagecache memory allocator] that was configured using
60266188
** [SQLITE_CONFIG_PAGECACHE]. The
60276189
** value returned is in pages, not in bytes.</dd>)^
60286190
**
6191
+** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
60296192
** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
60306193
** <dd>This parameter returns the number of bytes of page cache
60316194
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
60326195
** buffer and where forced to overflow to [sqlite3_malloc()]. The
60336196
** returned value includes allocations that overflowed because they
60346197
** where too large (they were larger than the "sz" parameter to
60356198
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
60366199
** no space was left in the page cache.</dd>)^
60376200
**
6038
-** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
6201
+** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
60396202
** <dd>This parameter records the largest memory allocation request
60406203
** handed to [pagecache memory allocator]. Only the value returned in the
60416204
** *pHighwater parameter to [sqlite3_status()] is of interest.
60426205
** The value written into the *pCurrent parameter is undefined.</dd>)^
60436206
**
6044
-** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
6207
+** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
60456208
** <dd>This parameter returns the number of allocations used out of the
60466209
** [scratch memory allocator] configured using
60476210
** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
60486211
** in bytes. Since a single thread may only have one scratch allocation
60496212
** outstanding at time, this parameter also reports the number of threads
60506213
** using scratch memory at the same time.</dd>)^
60516214
**
6052
-** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
6215
+** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
60536216
** <dd>This parameter returns the number of bytes of scratch memory
60546217
** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
60556218
** buffer and where forced to overflow to [sqlite3_malloc()]. The values
60566219
** returned include overflows because the requested allocation was too
60576220
** larger (that is, because the requested allocation was larger than the
60586221
** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
60596222
** slots were available.
60606223
** </dd>)^
60616224
**
6062
-** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
6225
+** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
60636226
** <dd>This parameter records the largest memory allocation request
60646227
** handed to [scratch memory allocator]. Only the value returned in the
60656228
** *pHighwater parameter to [sqlite3_status()] is of interest.
60666229
** The value written into the *pCurrent parameter is undefined.</dd>)^
60676230
**
6068
-** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
6231
+** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
60696232
** <dd>This parameter records the deepest parser stack. It is only
60706233
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
60716234
** </dl>
60726235
**
60736236
** New status parameters may be added from time to time.
@@ -6088,13 +6251,13 @@
60886251
**
60896252
** ^This interface is used to retrieve runtime status information
60906253
** about a single [database connection]. ^The first argument is the
60916254
** database connection object to be interrogated. ^The second argument
60926255
** is an integer constant, taken from the set of
6093
-** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
6256
+** [SQLITE_DBSTATUS options], that
60946257
** determines the parameter to interrogate. The set of
6095
-** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
6258
+** [SQLITE_DBSTATUS options] is likely
60966259
** to grow in future releases of SQLite.
60976260
**
60986261
** ^The current value of the requested parameter is written into *pCur
60996262
** and the highest instantaneous value is written into *pHiwtr. ^If
61006263
** the resetFlg is true, then the highest instantaneous value is
@@ -6107,10 +6270,11 @@
61076270
*/
61086271
SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
61096272
61106273
/*
61116274
** CAPI3REF: Status Parameters for database connections
6275
+** KEYWORDS: {SQLITE_DBSTATUS options}
61126276
**
61136277
** These constants are the available integer "verbs" that can be passed as
61146278
** the second argument to the [sqlite3_db_status()] interface.
61156279
**
61166280
** New verbs may be added in future releases of SQLite. Existing verbs
@@ -6118,48 +6282,50 @@
61186282
** [sqlite3_db_status()] to make sure that the call worked.
61196283
** The [sqlite3_db_status()] interface will return a non-zero error code
61206284
** if a discontinued or unsupported verb is invoked.
61216285
**
61226286
** <dl>
6123
-** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
6287
+** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
61246288
** <dd>This parameter returns the number of lookaside memory slots currently
61256289
** checked out.</dd>)^
61266290
**
6127
-** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
6291
+** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
61286292
** <dd>This parameter returns the number malloc attempts that were
61296293
** satisfied using lookaside memory. Only the high-water value is meaningful;
61306294
** the current value is always zero.)^
61316295
**
6296
+** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
61326297
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
61336298
** <dd>This parameter returns the number malloc attempts that might have
61346299
** been satisfied using lookaside memory but failed due to the amount of
61356300
** memory requested being larger than the lookaside slot size.
61366301
** Only the high-water value is meaningful;
61376302
** the current value is always zero.)^
61386303
**
6304
+** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
61396305
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
61406306
** <dd>This parameter returns the number malloc attempts that might have
61416307
** been satisfied using lookaside memory but failed due to all lookaside
61426308
** memory already being in use.
61436309
** Only the high-water value is meaningful;
61446310
** the current value is always zero.)^
61456311
**
6146
-** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
6312
+** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
61476313
** <dd>This parameter returns the approximate number of of bytes of heap
61486314
** memory used by all pager caches associated with the database connection.)^
61496315
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
61506316
**
6151
-** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
6317
+** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
61526318
** <dd>This parameter returns the approximate number of of bytes of heap
61536319
** memory used to store the schema for all databases associated
61546320
** with the connection - main, temp, and any [ATTACH]-ed databases.)^
61556321
** ^The full amount of memory used by the schemas is reported, even if the
61566322
** schema memory is shared with other database connections due to
61576323
** [shared cache mode] being enabled.
61586324
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
61596325
**
6160
-** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
6326
+** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
61616327
** <dd>This parameter returns the approximate number of of bytes of heap
61626328
** and lookaside memory used by all prepared statements associated with
61636329
** the database connection.)^
61646330
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
61656331
** </dd>
@@ -6177,11 +6343,11 @@
61776343
61786344
/*
61796345
** CAPI3REF: Prepared Statement Status
61806346
**
61816347
** ^(Each prepared statement maintains various
6182
-** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
6348
+** [SQLITE_STMTSTATUS counters] that measure the number
61836349
** of times it has performed specific operations.)^ These counters can
61846350
** be used to monitor the performance characteristics of the prepared
61856351
** statements. For example, if the number of table steps greatly exceeds
61866352
** the number of table searches or result rows, that would tend to indicate
61876353
** that the prepared statement is using a full table scan rather than
@@ -6188,11 +6354,11 @@
61886354
** an index.
61896355
**
61906356
** ^(This interface is used to retrieve and reset counter values from
61916357
** a [prepared statement]. The first argument is the prepared statement
61926358
** object to be interrogated. The second argument
6193
-** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
6359
+** is an integer code for a specific [SQLITE_STMTSTATUS counter]
61946360
** to be interrogated.)^
61956361
** ^The current value of the requested counter is returned.
61966362
** ^If the resetFlg is true, then the counter is reset to zero after this
61976363
** interface call returns.
61986364
**
@@ -6200,28 +6366,29 @@
62006366
*/
62016367
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
62026368
62036369
/*
62046370
** CAPI3REF: Status Parameters for prepared statements
6371
+** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
62056372
**
62066373
** These preprocessor macros define integer codes that name counter
62076374
** values associated with the [sqlite3_stmt_status()] interface.
62086375
** The meanings of the various counters are as follows:
62096376
**
62106377
** <dl>
6211
-** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
6378
+** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
62126379
** <dd>^This is the number of times that SQLite has stepped forward in
62136380
** a table as part of a full table scan. Large numbers for this counter
62146381
** may indicate opportunities for performance improvement through
62156382
** careful use of indices.</dd>
62166383
**
6217
-** <dt>SQLITE_STMTSTATUS_SORT</dt>
6384
+** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
62186385
** <dd>^This is the number of sort operations that have occurred.
62196386
** A non-zero value in this counter may indicate an opportunity to
62206387
** improvement performance through careful use of indices.</dd>
62216388
**
6222
-** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
6389
+** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
62236390
** <dd>^This is the number of rows inserted into transient indices that
62246391
** were created automatically in order to help joins run faster.
62256392
** A non-zero value in this counter may indicate an opportunity to
62266393
** improvement performance by adding permanent indices that do not
62276394
** need to be reinitialized each time the statement is run.</dd>
@@ -6268,10 +6435,11 @@
62686435
** ^(The contents of the sqlite3_pcache_methods structure are copied to an
62696436
** internal buffer by SQLite within the call to [sqlite3_config]. Hence
62706437
** the application may discard the parameter after the call to
62716438
** [sqlite3_config()] returns.)^
62726439
**
6440
+** [[the xInit() page cache method]]
62736441
** ^(The xInit() method is called once for each effective
62746442
** call to [sqlite3_initialize()])^
62756443
** (usually only once during the lifetime of the process). ^(The xInit()
62766444
** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^
62776445
** The intent of the xInit() method is to set up global data structures
@@ -6278,10 +6446,11 @@
62786446
** required by the custom page cache implementation.
62796447
** ^(If the xInit() method is NULL, then the
62806448
** built-in default page cache is used instead of the application defined
62816449
** page cache.)^
62826450
**
6451
+** [[the xShutdown() page cache method]]
62836452
** ^The xShutdown() method is called by [sqlite3_shutdown()].
62846453
** It can be used to clean up
62856454
** any outstanding resources before process shutdown, if required.
62866455
** ^The xShutdown() method may be NULL.
62876456
**
@@ -6292,10 +6461,11 @@
62926461
** in multithreaded applications.
62936462
**
62946463
** ^SQLite will never invoke xInit() more than once without an intervening
62956464
** call to xShutdown().
62966465
**
6466
+** [[the xCreate() page cache methods]]
62976467
** ^SQLite invokes the xCreate() method to construct a new cache instance.
62986468
** SQLite will typically create one cache instance for each open database file,
62996469
** though this is not guaranteed. ^The
63006470
** first parameter, szPage, is the size in bytes of the pages that must
63016471
** be allocated by the cache. ^szPage will not be a power of two. ^szPage
@@ -6316,20 +6486,23 @@
63166486
** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
63176487
** false will always have the "discard" flag set to true.
63186488
** ^Hence, a cache created with bPurgeable false will
63196489
** never contain any unpinned pages.
63206490
**
6491
+** [[the xCachesize() page cache method]]
63216492
** ^(The xCachesize() method may be called at any time by SQLite to set the
63226493
** suggested maximum cache-size (number of pages stored by) the cache
63236494
** instance passed as the first argument. This is the value configured using
63246495
** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
63256496
** parameter, the implementation is not required to do anything with this
63266497
** value; it is advisory only.
63276498
**
6499
+** [[the xPagecount() page cache methods]]
63286500
** The xPagecount() method must return the number of pages currently
63296501
** stored in the cache, both pinned and unpinned.
63306502
**
6503
+** [[the xFetch() page cache methods]]
63316504
** The xFetch() method locates a page in the cache and returns a pointer to
63326505
** the page, or a NULL pointer.
63336506
** A "page", in this context, means a buffer of szPage bytes aligned at an
63346507
** 8-byte boundary. The page to be fetched is determined by the key. ^The
63356508
** mimimum key value is 1. After it has been retrieved using xFetch, the page
@@ -6354,10 +6527,11 @@
63546527
** will only use a createFlag of 2 after a prior call with a createFlag of 1
63556528
** failed.)^ In between the to xFetch() calls, SQLite may
63566529
** attempt to unpin one or more cache pages by spilling the content of
63576530
** pinned pages to disk and synching the operating system disk cache.
63586531
**
6532
+** [[the xUnpin() page cache method]]
63596533
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
63606534
** as its second argument. If the third parameter, discard, is non-zero,
63616535
** then the page must be evicted from the cache.
63626536
** ^If the discard parameter is
63636537
** zero, then the page may be discarded or retained at the discretion of
@@ -6366,10 +6540,11 @@
63666540
**
63676541
** The cache must not perform any reference counting. A single
63686542
** call to xUnpin() unpins the page regardless of the number of prior calls
63696543
** to xFetch().
63706544
**
6545
+** [[the xRekey() page cache methods]]
63716546
** The xRekey() method is used to change the key value associated with the
63726547
** page passed as the second argument. If the cache
63736548
** previously contains an entry associated with newKey, it must be
63746549
** discarded. ^Any prior cache entry associated with newKey is guaranteed not
63756550
** to be pinned.
@@ -6378,10 +6553,11 @@
63786553
** existing cache entries with page numbers (keys) greater than or equal
63796554
** to the value of the iLimit parameter passed to xTruncate(). If any
63806555
** of these pages are pinned, they are implicitly unpinned, meaning that
63816556
** they can be safely discarded.
63826557
**
6558
+** [[the xDestroy() page cache method]]
63836559
** ^The xDestroy() method is used to delete a cache allocated by xCreate().
63846560
** All resources associated with the specified cache should be freed. ^After
63856561
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
63866562
** handle invalid, and will not use it with any other sqlite3_pcache_methods
63876563
** functions.
@@ -6440,11 +6616,11 @@
64406616
** associated with the backup operation.
64416617
** </ol>)^
64426618
** There should be exactly one call to sqlite3_backup_finish() for each
64436619
** successful call to sqlite3_backup_init().
64446620
**
6445
-** <b>sqlite3_backup_init()</b>
6621
+** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
64466622
**
64476623
** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
64486624
** [database connection] associated with the destination database
64496625
** and the database name, respectively.
64506626
** ^The database name is "main" for the main database, "temp" for the
@@ -6467,11 +6643,11 @@
64676643
** [sqlite3_backup] object.
64686644
** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
64696645
** sqlite3_backup_finish() functions to perform the specified backup
64706646
** operation.
64716647
**
6472
-** <b>sqlite3_backup_step()</b>
6648
+** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
64736649
**
64746650
** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
64756651
** the source and destination databases specified by [sqlite3_backup] object B.
64766652
** ^If N is negative, all remaining source pages are copied.
64776653
** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
@@ -6524,11 +6700,11 @@
65246700
** restarted by the next call to sqlite3_backup_step(). ^If the source
65256701
** database is modified by the using the same database connection as is used
65266702
** by the backup operation, then the backup database is automatically
65276703
** updated at the same time.
65286704
**
6529
-** <b>sqlite3_backup_finish()</b>
6705
+** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
65306706
**
65316707
** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
65326708
** application wishes to abandon the backup operation, the application
65336709
** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
65346710
** ^The sqlite3_backup_finish() interfaces releases all
@@ -6547,11 +6723,12 @@
65476723
**
65486724
** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
65496725
** is not a permanent error and does not affect the return value of
65506726
** sqlite3_backup_finish().
65516727
**
6552
-** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b>
6728
+** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
6729
+** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
65536730
**
65546731
** ^Each call to sqlite3_backup_step() sets two values inside
65556732
** the [sqlite3_backup] object: the number of pages still to be backed
65566733
** up and the total number of pages in the source database file.
65576734
** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
@@ -6932,10 +7109,97 @@
69327109
** each of these values.
69337110
*/
69347111
#define SQLITE_CHECKPOINT_PASSIVE 0
69357112
#define SQLITE_CHECKPOINT_FULL 1
69367113
#define SQLITE_CHECKPOINT_RESTART 2
7114
+
7115
+/*
7116
+** CAPI3REF: Virtual Table Interface Configuration
7117
+**
7118
+** This function may be called by either the [xConnect] or [xCreate] method
7119
+** of a [virtual table] implementation to configure
7120
+** various facets of the virtual table interface.
7121
+**
7122
+** If this interface is invoked outside the context of an xConnect or
7123
+** xCreate virtual table method then the behavior is undefined.
7124
+**
7125
+** At present, there is only one option that may be configured using
7126
+** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
7127
+** may be added in the future.
7128
+*/
7129
+SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
7130
+
7131
+/*
7132
+** CAPI3REF: Virtual Table Configuration Options
7133
+**
7134
+** These macros define the various options to the
7135
+** [sqlite3_vtab_config()] interface that [virtual table] implementations
7136
+** can use to customize and optimize their behavior.
7137
+**
7138
+** <dl>
7139
+** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
7140
+** <dd>Calls of the form
7141
+** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
7142
+** where X is an integer. If X is zero, then the [virtual table] whose
7143
+** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
7144
+** support constraints. In this configuration (which is the default) if
7145
+** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
7146
+** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
7147
+** specified as part of the users SQL statement, regardless of the actual
7148
+** ON CONFLICT mode specified.
7149
+**
7150
+** If X is non-zero, then the virtual table implementation guarantees
7151
+** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
7152
+** any modifications to internal or persistent data structures have been made.
7153
+** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
7154
+** is able to roll back a statement or database transaction, and abandon
7155
+** or continue processing the current SQL statement as appropriate.
7156
+** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
7157
+** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
7158
+** had been ABORT.
7159
+**
7160
+** Virtual table implementations that are required to handle OR REPLACE
7161
+** must do so within the [xUpdate] method. If a call to the
7162
+** [sqlite3_vtab_on_conflict()] function indicates that the current ON
7163
+** CONFLICT policy is REPLACE, the virtual table implementation should
7164
+** silently replace the appropriate rows within the xUpdate callback and
7165
+** return SQLITE_OK. Or, if this is not possible, it may return
7166
+** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
7167
+** constraint handling.
7168
+** </dl>
7169
+*/
7170
+#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
7171
+
7172
+/*
7173
+** CAPI3REF: Determine The Virtual Table Conflict Policy
7174
+**
7175
+** This function may only be called from within a call to the [xUpdate] method
7176
+** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
7177
+** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
7178
+** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
7179
+** of the SQL statement that triggered the call to the [xUpdate] method of the
7180
+** [virtual table].
7181
+*/
7182
+SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
7183
+
7184
+/*
7185
+** CAPI3REF: Conflict resolution modes
7186
+**
7187
+** These constants are returned by [sqlite3_vtab_on_conflict()] to
7188
+** inform a [virtual table] implementation what the [ON CONFLICT] mode
7189
+** is for the SQL statement being evaluated.
7190
+**
7191
+** Note that the [SQLITE_IGNORE] constant is also used as a potential
7192
+** return value from the [sqlite3_set_authorizer()] callback and that
7193
+** [SQLITE_ABORT] is also a [result code].
7194
+*/
7195
+#define SQLITE_ROLLBACK 1
7196
+/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
7197
+#define SQLITE_FAIL 3
7198
+/* #define SQLITE_ABORT 4 // Also an error code */
7199
+#define SQLITE_REPLACE 5
7200
+
69377201
69387202
69397203
/*
69407204
** Undo the hack that converts floating point types to integer for
69417205
** builds on processors without floating point support.
@@ -7599,10 +7863,11 @@
75997863
typedef struct Trigger Trigger;
76007864
typedef struct TriggerPrg TriggerPrg;
76017865
typedef struct TriggerStep TriggerStep;
76027866
typedef struct UnpackedRecord UnpackedRecord;
76037867
typedef struct VTable VTable;
7868
+typedef struct VtabCtx VtabCtx;
76047869
typedef struct Walker Walker;
76057870
typedef struct WherePlan WherePlan;
76067871
typedef struct WhereInfo WhereInfo;
76077872
typedef struct WhereLevel WhereLevel;
76087873
@@ -7655,10 +7920,11 @@
76557920
typedef struct BtCursor BtCursor;
76567921
typedef struct BtShared BtShared;
76577922
76587923
76597924
SQLITE_PRIVATE int sqlite3BtreeOpen(
7925
+ sqlite3_vfs *pVfs, /* VFS to use with this b-tree */
76607926
const char *zFilename, /* Name of database file to open */
76617927
sqlite3 *db, /* Associated database connection */
76627928
Btree **ppBtree, /* Return open Btree* here */
76637929
int flags, /* Flags */
76647930
int vfsFlags /* Flags passed through to VFS open */
@@ -9134,19 +9400,20 @@
91349400
struct sqlite3 {
91359401
sqlite3_vfs *pVfs; /* OS Interface */
91369402
int nDb; /* Number of backends currently in use */
91379403
Db *aDb; /* All backends */
91389404
int flags; /* Miscellaneous flags. See below */
9139
- int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
9405
+ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
91409406
int errCode; /* Most recent error code (SQLITE_*) */
91419407
int errMask; /* & result codes with this before returning */
91429408
u8 autoCommit; /* The auto-commit flag. */
91439409
u8 temp_store; /* 1: file 2: memory 0: default */
91449410
u8 mallocFailed; /* True if we have seen a malloc failure */
91459411
u8 dfltLockMode; /* Default locking-mode for attached dbs */
91469412
signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
91479413
u8 suppressErr; /* Do not issue error messages if true */
9414
+ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
91489415
int nextPagesize; /* Pagesize after VACUUM if >0 */
91499416
int nTable; /* Number of tables in the database */
91509417
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
91519418
i64 lastRowid; /* ROWID of most recent insert (see above) */
91529419
u32 magic; /* Magic number for detect library misuse */
@@ -9201,11 +9468,11 @@
92019468
void *pProgressArg; /* Argument to the progress callback */
92029469
int nProgressOps; /* Number of opcodes for progress callback */
92039470
#endif
92049471
#ifndef SQLITE_OMIT_VIRTUALTABLE
92059472
Hash aModule; /* populated by sqlite3_create_module() */
9206
- Table *pVTab; /* vtab with active Connect/Create method */
9473
+ VtabCtx *pVtabCtx; /* Context for active vtab connect/create */
92079474
VTable **aVTrans; /* Virtual tables with open transactions */
92089475
int nVTrans; /* Allocated size of aVTrans */
92099476
VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
92109477
#endif
92119478
FuncDefHash aFunc; /* Hash table of connection functions */
@@ -9564,10 +9831,11 @@
95649831
struct VTable {
95659832
sqlite3 *db; /* Database connection associated with this table */
95669833
Module *pMod; /* Pointer to module implementation */
95679834
sqlite3_vtab *pVtab; /* Pointer to vtab instance */
95689835
int nRef; /* Number of pointers to this structure */
9836
+ u8 bConstraint; /* True if constraints are supported */
95699837
VTable *pNext; /* Next in linked list (see above) */
95709838
};
95719839
95729840
/*
95739841
** Each SQL table is represented in memory by an instance of the
@@ -10752,10 +11020,11 @@
1075211020
*/
1075311021
struct Sqlite3Config {
1075411022
int bMemstat; /* True to enable memory status */
1075511023
int bCoreMutex; /* True to enable core mutexing */
1075611024
int bFullMutex; /* True to enable full mutexing */
11025
+ int bOpenUri; /* True to interpret filenames as URIs */
1075711026
int mxStrlen; /* Maximum string length */
1075811027
int szLookaside; /* Default lookaside buffer size */
1075911028
int nLookaside; /* Default lookaside buffer count */
1076011029
sqlite3_mem_methods m; /* Low-level memory allocation interface */
1076111030
sqlite3_mutex_methods mutex; /* Low-level mutex interface */
@@ -11001,10 +11270,12 @@
1100111270
SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
1100211271
SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
1100311272
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
1100411273
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
1100511274
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
11275
+SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
11276
+ sqlite3_vfs**,char**,char **);
1100611277
1100711278
SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
1100811279
SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
1100911280
SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
1101011281
SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*);
@@ -11251,10 +11522,11 @@
1125111522
SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
1125211523
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
1125311524
SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
1125411525
SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
1125511526
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
11527
+SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
1125611528
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
1125711529
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
1125811530
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
1125911531
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
1126011532
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
@@ -11266,10 +11538,16 @@
1126611538
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
1126711539
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
1126811540
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
1126911541
SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
1127011542
SQLITE_PRIVATE int sqlite3AbsInt32(int);
11543
+#ifdef SQLITE_ENABLE_8_3_NAMES
11544
+SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
11545
+#else
11546
+# define sqlite3FileSuffix3(X,Y)
11547
+#endif
11548
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z);
1127111549
1127211550
SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
1127311551
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
1127411552
SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
1127511553
void(*)(void*));
@@ -11375,18 +11653,20 @@
1137511653
# define sqlite3VtabCommit(X)
1137611654
# define sqlite3VtabInSync(db) 0
1137711655
# define sqlite3VtabLock(X)
1137811656
# define sqlite3VtabUnlock(X)
1137911657
# define sqlite3VtabUnlockList(X)
11658
+# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
1138011659
#else
1138111660
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*);
1138211661
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **);
1138311662
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
1138411663
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
1138511664
SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
1138611665
SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
1138711666
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
11667
+SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
1138811668
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
1138911669
#endif
1139011670
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
1139111671
SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
1139211672
SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
@@ -11689,20 +11969,23 @@
1168911969
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
1169011970
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
1169111971
};
1169211972
#endif
1169311973
11694
-
11974
+#ifndef SQLITE_USE_URI
11975
+# define SQLITE_USE_URI 0
11976
+#endif
1169511977
1169611978
/*
1169711979
** The following singleton contains the global configuration for
1169811980
** the SQLite library.
1169911981
*/
1170011982
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
1170111983
SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
1170211984
1, /* bCoreMutex */
1170311985
SQLITE_THREADSAFE==1, /* bFullMutex */
11986
+ SQLITE_USE_URI, /* bOpenUri */
1170411987
0x7ffffffe, /* mxStrlen */
1170511988
100, /* szLookaside */
1170611989
500, /* nLookaside */
1170711990
{0,0,0,0,0,0,0,0}, /* m */
1170811991
{0,0,0,0,0,0,0,0,0}, /* mutex */
@@ -17948,11 +18231,11 @@
1794818231
assert( sqlite3_mutex_held(mem0.mutex) );
1794918232
nFull = sqlite3GlobalConfig.m.xRoundup(n);
1795018233
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
1795118234
if( mem0.alarmCallback!=0 ){
1795218235
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
17953
- if( nUsed+nFull >= mem0.alarmThreshold ){
18236
+ if( nUsed >= mem0.alarmThreshold - nFull ){
1795418237
mem0.nearlyFull = 1;
1795518238
sqlite3MallocAlarm(nFull);
1795618239
}else{
1795718240
mem0.nearlyFull = 0;
1795818241
}
@@ -18189,11 +18472,11 @@
1818918472
1819018473
/*
1819118474
** Change the size of an existing memory allocation
1819218475
*/
1819318476
SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
18194
- int nOld, nNew;
18477
+ int nOld, nNew, nDiff;
1819518478
void *pNew;
1819618479
if( pOld==0 ){
1819718480
return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
1819818481
}
1819918482
if( nBytes<=0 ){
@@ -18212,13 +18495,14 @@
1821218495
if( nOld==nNew ){
1821318496
pNew = pOld;
1821418497
}else if( sqlite3GlobalConfig.bMemstat ){
1821518498
sqlite3_mutex_enter(mem0.mutex);
1821618499
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
18217
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >=
18218
- mem0.alarmThreshold ){
18219
- sqlite3MallocAlarm(nNew-nOld);
18500
+ nDiff = nNew - nOld;
18501
+ if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
18502
+ mem0.alarmThreshold-nDiff ){
18503
+ sqlite3MallocAlarm(nDiff);
1822018504
}
1822118505
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
1822218506
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
1822318507
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
1822418508
if( pNew==0 && mem0.alarmCallback ){
@@ -21180,27 +21464,25 @@
2118021464
p[3] = (u8)v;
2118121465
}
2118221466
2118321467
2118421468
21185
-#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
2118621469
/*
2118721470
** Translate a single byte of Hex into an integer.
2118821471
** This routine only works if h really is a valid hexadecimal
2118921472
** character: 0..9a..fA..F
2119021473
*/
21191
-static u8 hexToInt(int h){
21474
+SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
2119221475
assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
2119321476
#ifdef SQLITE_ASCII
2119421477
h += 9*(1&(h>>6));
2119521478
#endif
2119621479
#ifdef SQLITE_EBCDIC
2119721480
h += 9*(1&~(h>>4));
2119821481
#endif
2119921482
return (u8)(h & 0xf);
2120021483
}
21201
-#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
2120221484
2120321485
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
2120421486
/*
2120521487
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
2120621488
** value. Return a pointer to its binary value. Space to hold the
@@ -21213,11 +21495,11 @@
2121321495
2121421496
zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
2121521497
n--;
2121621498
if( zBlob ){
2121721499
for(i=0; i<n; i+=2){
21218
- zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
21500
+ zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
2121921501
}
2122021502
zBlob[i/2] = 0;
2122121503
}
2122221504
return zBlob;
2122321505
}
@@ -21345,10 +21627,36 @@
2134521627
SQLITE_PRIVATE int sqlite3AbsInt32(int x){
2134621628
if( x>=0 ) return x;
2134721629
if( x==(int)0x80000000 ) return 0x7fffffff;
2134821630
return -x;
2134921631
}
21632
+
21633
+#ifdef SQLITE_ENABLE_8_3_NAMES
21634
+/*
21635
+** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
21636
+** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
21637
+** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
21638
+** three characters, then shorten the suffix on z[] to be the last three
21639
+** characters of the original suffix.
21640
+**
21641
+** Examples:
21642
+**
21643
+** test.db-journal => test.nal
21644
+** test.db-wal => test.wal
21645
+** test.db-shm => test.shm
21646
+*/
21647
+SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
21648
+ const char *zOk;
21649
+ zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
21650
+ if( zOk && sqlite3GetBoolean(zOk) ){
21651
+ int i, sz;
21652
+ sz = sqlite3Strlen30(z);
21653
+ for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
21654
+ if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
21655
+ }
21656
+}
21657
+#endif
2135021658
2135121659
/************** End of util.c ************************************************/
2135221660
/************** Begin file hash.c ********************************************/
2135321661
/*
2135421662
** 2001 September 22
@@ -24398,10 +24706,22 @@
2439824706
#if SQLITE_THREADSAFE
2439924707
#define threadid pthread_self()
2440024708
#else
2440124709
#define threadid 0
2440224710
#endif
24711
+
24712
+/*
24713
+** Different Unix systems declare open() in different ways. Same use
24714
+** open(const char*,int,mode_t). Others use open(const char*,int,...).
24715
+** The difference is important when using a pointer to the function.
24716
+**
24717
+** The safest way to deal with the problem is to always use this wrapper
24718
+** which always has the same well-defined interface.
24719
+*/
24720
+static int posixOpen(const char *zFile, int flags, int mode){
24721
+ return open(zFile, flags, mode);
24722
+}
2440324723
2440424724
/*
2440524725
** Many system calls are accessed through pointer-to-functions so that
2440624726
** they may be overridden at runtime to facilitate fault injection during
2440724727
** testing and sandboxing. The following array holds the names and pointers
@@ -24410,11 +24730,11 @@
2441024730
static struct unix_syscall {
2441124731
const char *zName; /* Name of the sytem call */
2441224732
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
2441324733
sqlite3_syscall_ptr pDefault; /* Default value */
2441424734
} aSyscall[] = {
24415
- { "open", (sqlite3_syscall_ptr)open, 0 },
24735
+ { "open", (sqlite3_syscall_ptr)posixOpen, 0 },
2441624736
#define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
2441724737
2441824738
{ "close", (sqlite3_syscall_ptr)close, 0 },
2441924739
#define osClose ((int(*)(int))aSyscall[1].pCurrent)
2442024740
@@ -24448,11 +24768,11 @@
2444824768
#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
2444924769
2445024770
{ "read", (sqlite3_syscall_ptr)read, 0 },
2445124771
#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
2445224772
24453
-#if defined(USE_PREAD) || defined(SQLITE_ENABLE_LOCKING_STYLE)
24773
+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
2445424774
{ "pread", (sqlite3_syscall_ptr)pread, 0 },
2445524775
#else
2445624776
{ "pread", (sqlite3_syscall_ptr)0, 0 },
2445724777
#endif
2445824778
#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -24465,11 +24785,11 @@
2446524785
#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
2446624786
2446724787
{ "write", (sqlite3_syscall_ptr)write, 0 },
2446824788
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
2446924789
24470
-#if defined(USE_PREAD) || defined(SQLITE_ENABLE_LOCKING_STYLE)
24790
+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
2447124791
{ "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
2447224792
#else
2447324793
{ "pwrite", (sqlite3_syscall_ptr)0, 0 },
2447424794
#endif
2447524795
#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -24483,12 +24803,14 @@
2448324803
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
2448424804
aSyscall[13].pCurrent)
2448524805
2448624806
#if SQLITE_ENABLE_LOCKING_STYLE
2448724807
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
24808
+#else
24809
+ { "fchmod", (sqlite3_syscall_ptr)0, 0 },
24810
+#endif
2448824811
#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
24489
-#endif
2449024812
2449124813
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
2449224814
{ "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
2449324815
#else
2449424816
{ "fallocate", (sqlite3_syscall_ptr)0, 0 },
@@ -25049,11 +25371,11 @@
2504925371
unixShmNode *pShmNode; /* Shared memory associated with this inode */
2505025372
int nLock; /* Number of outstanding file locks */
2505125373
UnixUnusedFd *pUnused; /* Unused file descriptors to close */
2505225374
unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
2505325375
unixInodeInfo *pPrev; /* .... doubly linked */
25054
-#if defined(SQLITE_ENABLE_LOCKING_STYLE)
25376
+#if SQLITE_ENABLE_LOCKING_STYLE
2505525377
unsigned long long sharedByte; /* for AFP simulated shared lock */
2505625378
#endif
2505725379
#if OS_VXWORKS
2505825380
sem_t *pSem; /* Named POSIX semaphore */
2505925381
char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
@@ -27206,11 +27528,11 @@
2720627528
}
2720727529
SimulateIOError(( wrote=(-1), amt=1 ));
2720827530
SimulateDiskfullError(( wrote=0, amt=1 ));
2720927531
2721027532
if( amt>0 ){
27211
- if( wrote<0 ){
27533
+ if( wrote<0 && pFile->lastErrno!=ENOSPC ){
2721227534
/* lastErrno set by seekAndWrite */
2721327535
return SQLITE_IOERR_WRITE;
2721427536
}else{
2721527537
pFile->lastErrno = 0; /* not a system error */
2721627538
return SQLITE_FULL;
@@ -27873,10 +28195,11 @@
2787328195
sqlite3_snprintf(nShmFilename, zShmFilename,
2787428196
SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
2787528197
(u32)sStat.st_ino, (u32)sStat.st_dev);
2787628198
#else
2787728199
sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
28200
+ sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
2787828201
#endif
2787928202
pShmNode->h = -1;
2788028203
pDbFd->pInode->pShmNode = pShmNode;
2788128204
pShmNode->pInode = pDbFd->pInode;
2788228205
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
@@ -28031,11 +28354,11 @@
2803128354
if( pShmNode->h>=0 ){
2803228355
pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
2803328356
MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
2803428357
);
2803528358
if( pMem==MAP_FAILED ){
28036
- rc = SQLITE_IOERR;
28359
+ rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
2803728360
goto shmpage_out;
2803828361
}
2803928362
}else{
2804028363
pMem = sqlite3_malloc(szRegion);
2804128364
if( pMem==0 ){
@@ -28906,17 +29229,23 @@
2890629229
** Finally, if the file being opened is a WAL or regular journal file, then
2890729230
** this function queries the file-system for the permissions on the
2890829231
** corresponding database file and sets *pMode to this value. Whenever
2890929232
** possible, WAL and journal files are created using the same permissions
2891029233
** as the associated database file.
29234
+**
29235
+** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
29236
+** original filename is unavailable. But 8_3_NAMES is only used for
29237
+** FAT filesystems and permissions do not matter there, so just use
29238
+** the default permissions.
2891129239
*/
2891229240
static int findCreateFileMode(
2891329241
const char *zPath, /* Path of file (possibly) being created */
2891429242
int flags, /* Flags passed as 4th argument to xOpen() */
2891529243
mode_t *pMode /* OUT: Permissions to open file with */
2891629244
){
2891729245
int rc = SQLITE_OK; /* Return Code */
29246
+ *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
2891829247
if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
2891929248
char zDb[MAX_PATHNAME+1]; /* Database file path */
2892029249
int nDb; /* Number of valid bytes in zDb */
2892129250
struct stat sStat; /* Output of stat() on database file */
2892229251
@@ -28924,19 +29253,19 @@
2892429253
** the path to the associated database file from zPath. This block handles
2892529254
** the following naming conventions:
2892629255
**
2892729256
** "<path to db>-journal"
2892829257
** "<path to db>-wal"
28929
- ** "<path to db>-journal-NNNN"
28930
- ** "<path to db>-wal-NNNN"
29258
+ ** "<path to db>-journalNN"
29259
+ ** "<path to db>-walNN"
2893129260
**
28932
- ** where NNNN is a 4 digit decimal number. The NNNN naming schemes are
29261
+ ** where NN is a 4 digit decimal number. The NN naming schemes are
2893329262
** used by the test_multiplex.c module.
2893429263
*/
2893529264
nDb = sqlite3Strlen30(zPath) - 1;
28936
- while( nDb>0 && zPath[nDb]!='l' ) nDb--;
28937
- nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7);
29265
+ while( nDb>0 && zPath[nDb]!='-' ) nDb--;
29266
+ if( nDb==0 ) return SQLITE_OK;
2893829267
memcpy(zDb, zPath, nDb);
2893929268
zDb[nDb] = '\0';
2894029269
2894129270
if( 0==stat(zDb, &sStat) ){
2894229271
*pMode = sStat.st_mode & 0777;
@@ -28943,12 +29272,10 @@
2894329272
}else{
2894429273
rc = SQLITE_IOERR_FSTAT;
2894529274
}
2894629275
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
2894729276
*pMode = 0600;
28948
- }else{
28949
- *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
2895029277
}
2895129278
return rc;
2895229279
}
2895329280
2895429281
/*
@@ -30801,10 +31128,14 @@
3080131128
UNIXVFS("unix-nfs", nfsIoFinder ),
3080231129
UNIXVFS("unix-proxy", proxyIoFinder ),
3080331130
#endif
3080431131
};
3080531132
unsigned int i; /* Loop counter */
31133
+
31134
+ /* Double-check that the aSyscall[] array has been constructed
31135
+ ** correctly. See ticket [bb3a86e890c8e96ab] */
31136
+ assert( ArraySize(aSyscall)==16 );
3080631137
3080731138
/* Register all VFSes defined in the aVfs[] array */
3080831139
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
3080931140
sqlite3_vfs_register(&aVfs[i], i==0);
3081031141
}
@@ -31147,10 +31478,11 @@
3114731478
HANDLE hShared; /* Shared memory segment used for locking */
3114831479
winceLock local; /* Locks obtained by this instance of winFile */
3114931480
winceLock *shared; /* Global shared lock memory for the file */
3115031481
#endif
3115131482
};
31483
+
3115231484
3115331485
/*
3115431486
** Forward prototypes.
3115531487
*/
3115631488
static int getSectorSize(
@@ -31315,11 +31647,11 @@
3131531647
3131631648
/*
3131731649
** Convert UTF-8 to multibyte character string. Space to hold the
3131831650
** returned string is obtained from malloc().
3131931651
*/
31320
-static char *utf8ToMbcs(const char *zFilename){
31652
+SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
3132131653
char *zFilenameMbcs;
3132231654
WCHAR *zTmpWide;
3132331655
3132431656
zTmpWide = utf8ToUnicode(zFilename);
3132531657
if( zTmpWide==0 ){
@@ -31328,10 +31660,113 @@
3132831660
zFilenameMbcs = unicodeToMbcs(zTmpWide);
3132931661
free(zTmpWide);
3133031662
return zFilenameMbcs;
3133131663
}
3133231664
31665
+
31666
+/*
31667
+** The return value of getLastErrorMsg
31668
+** is zero if the error message fits in the buffer, or non-zero
31669
+** otherwise (if the message was truncated).
31670
+*/
31671
+static int getLastErrorMsg(int nBuf, char *zBuf){
31672
+ /* FormatMessage returns 0 on failure. Otherwise it
31673
+ ** returns the number of TCHARs written to the output
31674
+ ** buffer, excluding the terminating null char.
31675
+ */
31676
+ DWORD error = GetLastError();
31677
+ DWORD dwLen = 0;
31678
+ char *zOut = 0;
31679
+
31680
+ if( isNT() ){
31681
+ WCHAR *zTempWide = NULL;
31682
+ dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
31683
+ NULL,
31684
+ error,
31685
+ 0,
31686
+ (LPWSTR) &zTempWide,
31687
+ 0,
31688
+ 0);
31689
+ if( dwLen > 0 ){
31690
+ /* allocate a buffer and convert to UTF8 */
31691
+ zOut = unicodeToUtf8(zTempWide);
31692
+ /* free the system buffer allocated by FormatMessage */
31693
+ LocalFree(zTempWide);
31694
+ }
31695
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
31696
+** Since the ASCII version of these Windows API do not exist for WINCE,
31697
+** it's important to not reference them for WINCE builds.
31698
+*/
31699
+#if SQLITE_OS_WINCE==0
31700
+ }else{
31701
+ char *zTemp = NULL;
31702
+ dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
31703
+ NULL,
31704
+ error,
31705
+ 0,
31706
+ (LPSTR) &zTemp,
31707
+ 0,
31708
+ 0);
31709
+ if( dwLen > 0 ){
31710
+ /* allocate a buffer and convert to UTF8 */
31711
+ zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
31712
+ /* free the system buffer allocated by FormatMessage */
31713
+ LocalFree(zTemp);
31714
+ }
31715
+#endif
31716
+ }
31717
+ if( 0 == dwLen ){
31718
+ sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
31719
+ }else{
31720
+ /* copy a maximum of nBuf chars to output buffer */
31721
+ sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
31722
+ /* free the UTF8 buffer */
31723
+ free(zOut);
31724
+ }
31725
+ return 0;
31726
+}
31727
+
31728
+/*
31729
+**
31730
+** This function - winLogErrorAtLine() - is only ever called via the macro
31731
+** winLogError().
31732
+**
31733
+** This routine is invoked after an error occurs in an OS function.
31734
+** It logs a message using sqlite3_log() containing the current value of
31735
+** error code and, if possible, the human-readable equivalent from
31736
+** FormatMessage.
31737
+**
31738
+** The first argument passed to the macro should be the error code that
31739
+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
31740
+** The two subsequent arguments should be the name of the OS function that
31741
+** failed and the the associated file-system path, if any.
31742
+*/
31743
+#define winLogError(a,b,c) winLogErrorAtLine(a,b,c,__LINE__)
31744
+static int winLogErrorAtLine(
31745
+ int errcode, /* SQLite error code */
31746
+ const char *zFunc, /* Name of OS function that failed */
31747
+ const char *zPath, /* File path associated with error */
31748
+ int iLine /* Source line number where error occurred */
31749
+){
31750
+ char zMsg[500]; /* Human readable error text */
31751
+ int i; /* Loop counter */
31752
+ DWORD iErrno = GetLastError(); /* Error code */
31753
+
31754
+ zMsg[0] = 0;
31755
+ getLastErrorMsg(sizeof(zMsg), zMsg);
31756
+ assert( errcode!=SQLITE_OK );
31757
+ if( zPath==0 ) zPath = "";
31758
+ for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
31759
+ zMsg[i] = 0;
31760
+ sqlite3_log(errcode,
31761
+ "os_win.c:%d: (%d) %s(%s) - %s",
31762
+ iLine, iErrno, zFunc, zPath, zMsg
31763
+ );
31764
+
31765
+ return errcode;
31766
+}
31767
+
3133331768
#if SQLITE_OS_WINCE
3133431769
/*************************************************************************
3133531770
** This section contains code for WinCE only.
3133631771
*/
3133731772
/*
@@ -31404,10 +31839,11 @@
3140431839
3140531840
/* Create/open the named mutex */
3140631841
pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
3140731842
if (!pFile->hMutex){
3140831843
pFile->lastErrno = GetLastError();
31844
+ winLogError(SQLITE_ERROR, "winceCreateLock1", zFilename);
3140931845
free(zName);
3141031846
return FALSE;
3141131847
}
3141231848
3141331849
/* Acquire the mutex before continuing */
@@ -31435,10 +31871,11 @@
3143531871
pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
3143631872
FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
3143731873
/* If mapping failed, close the shared memory handle and erase it */
3143831874
if (!pFile->shared){
3143931875
pFile->lastErrno = GetLastError();
31876
+ winLogError(SQLITE_ERROR, "winceCreateLock2", zFilename);
3144031877
CloseHandle(pFile->hShared);
3144131878
pFile->hShared = NULL;
3144231879
}
3144331880
}
3144431881
@@ -31680,10 +32117,11 @@
3168032117
** GetLastError().
3168132118
*/
3168232119
dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
3168332120
if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){
3168432121
pFile->lastErrno = GetLastError();
32122
+ winLogError(SQLITE_IOERR_SEEK, "seekWinFile", pFile->zPath);
3168532123
return 1;
3168632124
}
3168732125
3168832126
return 0;
3168932127
}
@@ -31725,11 +32163,12 @@
3172532163
free(pFile->zDeleteOnClose);
3172632164
}
3172732165
#endif
3172832166
OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
3172932167
OpenCounter(-1);
31730
- return rc ? SQLITE_OK : SQLITE_IOERR;
32168
+ return rc ? SQLITE_OK
32169
+ : winLogError(SQLITE_IOERR_CLOSE, "winClose", pFile->zPath);
3173132170
}
3173232171
3173332172
/*
3173432173
** Read data from a file into a buffer. Return SQLITE_OK if all
3173532174
** bytes were read successfully and SQLITE_IOERR if anything goes
@@ -31751,11 +32190,11 @@
3175132190
if( seekWinFile(pFile, offset) ){
3175232191
return SQLITE_FULL;
3175332192
}
3175432193
if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
3175532194
pFile->lastErrno = GetLastError();
31756
- return SQLITE_IOERR_READ;
32195
+ return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
3175732196
}
3175832197
if( nRead<(DWORD)amt ){
3175932198
/* Unread parts of the buffer must be zero-filled */
3176032199
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
3176132200
return SQLITE_IOERR_SHORT_READ;
@@ -31802,11 +32241,11 @@
3180232241
3180332242
if( rc ){
3180432243
if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
3180532244
return SQLITE_FULL;
3180632245
}
31807
- return SQLITE_IOERR_WRITE;
32246
+ return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
3180832247
}
3180932248
return SQLITE_OK;
3181032249
}
3181132250
3181232251
/*
@@ -31830,14 +32269,14 @@
3183032269
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
3183132270
}
3183232271
3183332272
/* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
3183432273
if( seekWinFile(pFile, nByte) ){
31835
- rc = SQLITE_IOERR_TRUNCATE;
32274
+ rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate1", pFile->zPath);
3183632275
}else if( 0==SetEndOfFile(pFile->h) ){
3183732276
pFile->lastErrno = GetLastError();
31838
- rc = SQLITE_IOERR_TRUNCATE;
32277
+ rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate2", pFile->zPath);
3183932278
}
3184032279
3184132280
OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
3184232281
return rc;
3184332282
}
@@ -31855,10 +32294,11 @@
3185532294
** Make sure all writes to a particular file are committed to disk.
3185632295
*/
3185732296
static int winSync(sqlite3_file *id, int flags){
3185832297
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
3185932298
winFile *pFile = (winFile*)id;
32299
+ BOOL rc;
3186032300
#else
3186132301
UNUSED_PARAMETER(id);
3186232302
#endif
3186332303
3186432304
assert( pFile );
@@ -31867,36 +32307,37 @@
3186732307
|| (flags&0x0F)==SQLITE_SYNC_FULL
3186832308
);
3186932309
3187032310
OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
3187132311
32312
+ /* Unix cannot, but some systems may return SQLITE_FULL from here. This
32313
+ ** line is to test that doing so does not cause any problems.
32314
+ */
32315
+ SimulateDiskfullError( return SQLITE_FULL );
32316
+
3187232317
#ifndef SQLITE_TEST
3187332318
UNUSED_PARAMETER(flags);
3187432319
#else
31875
- if( flags & SQLITE_SYNC_FULL ){
32320
+ if( (flags&0x0F)==SQLITE_SYNC_FULL ){
3187632321
sqlite3_fullsync_count++;
3187732322
}
3187832323
sqlite3_sync_count++;
3187932324
#endif
3188032325
31881
- /* Unix cannot, but some systems may return SQLITE_FULL from here. This
31882
- ** line is to test that doing so does not cause any problems.
31883
- */
31884
- SimulateDiskfullError( return SQLITE_FULL );
31885
- SimulateIOError( return SQLITE_IOERR; );
31886
-
3188732326
/* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
3188832327
** no-op
3188932328
*/
3189032329
#ifdef SQLITE_NO_SYNC
3189132330
return SQLITE_OK;
3189232331
#else
31893
- if( FlushFileBuffers(pFile->h) ){
32332
+ rc = FlushFileBuffers(pFile->h);
32333
+ SimulateIOError( rc=FALSE );
32334
+ if( rc ){
3189432335
return SQLITE_OK;
3189532336
}else{
3189632337
pFile->lastErrno = GetLastError();
31897
- return SQLITE_IOERR;
32338
+ return winLogError(SQLITE_IOERR_FSYNC, "winSync", pFile->zPath);
3189832339
}
3189932340
#endif
3190032341
}
3190132342
3190232343
/*
@@ -31913,11 +32354,11 @@
3191332354
lowerBits = GetFileSize(pFile->h, &upperBits);
3191432355
if( (lowerBits == INVALID_FILE_SIZE)
3191532356
&& ((error = GetLastError()) != NO_ERROR) )
3191632357
{
3191732358
pFile->lastErrno = error;
31918
- return SQLITE_IOERR_FSTAT;
32359
+ return winLogError(SQLITE_IOERR_FSTAT, "winFileSize", pFile->zPath);
3191932360
}
3192032361
*pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
3192132362
return SQLITE_OK;
3192232363
}
3192332364
@@ -31952,10 +32393,11 @@
3195232393
res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
3195332394
#endif
3195432395
}
3195532396
if( res == 0 ){
3195632397
pFile->lastErrno = GetLastError();
32398
+ /* No need to log a failure to lock */
3195732399
}
3195832400
return res;
3195932401
}
3196032402
3196132403
/*
@@ -31970,12 +32412,13 @@
3197032412
#if SQLITE_OS_WINCE==0
3197132413
}else{
3197232414
res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
3197332415
#endif
3197432416
}
31975
- if( res == 0 ){
32417
+ if( res==0 && GetLastError()!=ERROR_NOT_LOCKED ){
3197632418
pFile->lastErrno = GetLastError();
32419
+ winLogError(SQLITE_IOERR_UNLOCK, "unlockReadLock", pFile->zPath);
3197732420
}
3197832421
return res;
3197932422
}
3198032423
3198132424
/*
@@ -32172,11 +32615,11 @@
3217232615
if( type>=EXCLUSIVE_LOCK ){
3217332616
UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
3217432617
if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
3217532618
/* This should never happen. We should always be able to
3217632619
** reacquire the read lock */
32177
- rc = SQLITE_IOERR_UNLOCK;
32620
+ rc = winLogError(SQLITE_IOERR_UNLOCK, "winUnlock", pFile->zPath);
3217832621
}
3217932622
}
3218032623
if( type>=RESERVED_LOCK ){
3218132624
UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
3218232625
}
@@ -32487,10 +32930,11 @@
3248732930
return SQLITE_NOMEM;
3248832931
}
3248932932
memset(pNew, 0, sizeof(*pNew));
3249032933
pNew->zFilename = (char*)&pNew[1];
3249132934
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
32935
+ sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
3249232936
3249332937
/* Look to see if there is an existing winShmNode that can be used.
3249432938
** If no matching winShmNode currently exists, create a new one.
3249532939
*/
3249632940
winShmEnterMutex();
@@ -32529,11 +32973,11 @@
3252932973
** If not, truncate the file to zero length.
3253032974
*/
3253132975
if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
3253232976
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
3253332977
if( rc!=SQLITE_OK ){
32534
- rc = SQLITE_IOERR_SHMOPEN;
32978
+ rc = winLogError(SQLITE_IOERR_SHMOPEN, "winOpenShm", pDbFd->zPath);
3253532979
}
3253632980
}
3253732981
if( rc==SQLITE_OK ){
3253832982
winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
3253932983
rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
@@ -32788,11 +33232,11 @@
3278833232
** Check to see if it has been allocated (i.e. if the wal-index file is
3278933233
** large enough to contain the requested region).
3279033234
*/
3279133235
rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
3279233236
if( rc!=SQLITE_OK ){
32793
- rc = SQLITE_IOERR_SHMSIZE;
33237
+ rc = winLogError(SQLITE_IOERR_SHMSIZE, "winShmMap1", pDbFd->zPath);
3279433238
goto shmpage_out;
3279533239
}
3279633240
3279733241
if( sz<nByte ){
3279833242
/* The requested memory region does not exist. If isWrite is set to
@@ -32802,11 +33246,11 @@
3280233246
** the requested memory region.
3280333247
*/
3280433248
if( !isWrite ) goto shmpage_out;
3280533249
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
3280633250
if( rc!=SQLITE_OK ){
32807
- rc = SQLITE_IOERR_SHMSIZE;
33251
+ rc = winLogError(SQLITE_IOERR_SHMSIZE, "winShmMap2", pDbFd->zPath);
3280833252
goto shmpage_out;
3280933253
}
3281033254
}
3281133255
3281233256
/* Map the requested memory region into this processes address space. */
@@ -32839,11 +33283,11 @@
3283933283
(int)GetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion,
3284033284
pMap ? "ok" : "failed"));
3284133285
}
3284233286
if( !pMap ){
3284333287
pShmNode->lastErrno = GetLastError();
32844
- rc = SQLITE_IOERR;
33288
+ rc = winLogError(SQLITE_IOERR_SHMMAP, "winShmMap3", pDbFd->zPath);
3284533289
if( hMap ) CloseHandle(hMap);
3284633290
goto shmpage_out;
3284733291
}
3284833292
3284933293
pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
@@ -32921,11 +33365,11 @@
3292133365
zConverted = utf8ToUnicode(zFilename);
3292233366
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3292333367
*/
3292433368
#if SQLITE_OS_WINCE==0
3292533369
}else{
32926
- zConverted = utf8ToMbcs(zFilename);
33370
+ zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
3292733371
#endif
3292833372
}
3292933373
/* caller will handle out of memory */
3293033374
return zConverted;
3293133375
}
@@ -33001,72 +33445,10 @@
3300133445
3300233446
OSTRACE(("TEMP FILENAME: %s\n", zBuf));
3300333447
return SQLITE_OK;
3300433448
}
3300533449
33006
-/*
33007
-** The return value of getLastErrorMsg
33008
-** is zero if the error message fits in the buffer, or non-zero
33009
-** otherwise (if the message was truncated).
33010
-*/
33011
-static int getLastErrorMsg(int nBuf, char *zBuf){
33012
- /* FormatMessage returns 0 on failure. Otherwise it
33013
- ** returns the number of TCHARs written to the output
33014
- ** buffer, excluding the terminating null char.
33015
- */
33016
- DWORD error = GetLastError();
33017
- DWORD dwLen = 0;
33018
- char *zOut = 0;
33019
-
33020
- if( isNT() ){
33021
- WCHAR *zTempWide = NULL;
33022
- dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
33023
- NULL,
33024
- error,
33025
- 0,
33026
- (LPWSTR) &zTempWide,
33027
- 0,
33028
- 0);
33029
- if( dwLen > 0 ){
33030
- /* allocate a buffer and convert to UTF8 */
33031
- zOut = unicodeToUtf8(zTempWide);
33032
- /* free the system buffer allocated by FormatMessage */
33033
- LocalFree(zTempWide);
33034
- }
33035
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
33036
-** Since the ASCII version of these Windows API do not exist for WINCE,
33037
-** it's important to not reference them for WINCE builds.
33038
-*/
33039
-#if SQLITE_OS_WINCE==0
33040
- }else{
33041
- char *zTemp = NULL;
33042
- dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
33043
- NULL,
33044
- error,
33045
- 0,
33046
- (LPSTR) &zTemp,
33047
- 0,
33048
- 0);
33049
- if( dwLen > 0 ){
33050
- /* allocate a buffer and convert to UTF8 */
33051
- zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
33052
- /* free the system buffer allocated by FormatMessage */
33053
- LocalFree(zTemp);
33054
- }
33055
-#endif
33056
- }
33057
- if( 0 == dwLen ){
33058
- sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
33059
- }else{
33060
- /* copy a maximum of nBuf chars to output buffer */
33061
- sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
33062
- /* free the UTF8 buffer */
33063
- free(zOut);
33064
- }
33065
- return 0;
33066
-}
33067
-
3306833450
/*
3306933451
** Open a file.
3307033452
*/
3307133453
static int winOpen(
3307233454
sqlite3_vfs *pVfs, /* Not used */
@@ -33234,10 +33616,11 @@
3323433616
h, zName, dwDesiredAccess,
3323533617
h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
3323633618
3323733619
if( h==INVALID_HANDLE_VALUE ){
3323833620
pFile->lastErrno = GetLastError();
33621
+ winLogError(SQLITE_CANTOPEN, "winOpen", zUtf8Name);
3323933622
free(zConverted);
3324033623
if( isReadWrite ){
3324133624
return winOpen(pVfs, zName, id,
3324233625
((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
3324333626
}else{
@@ -33337,11 +33720,12 @@
3333733720
OSTRACE(("DELETE \"%s\" %s\n", zFilename,
3333833721
( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
3333933722
"ok" : "failed" ));
3334033723
3334133724
return ( (rc == INVALID_FILE_ATTRIBUTES)
33342
- && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
33725
+ && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
33726
+ winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
3334333727
}
3334433728
3334533729
/*
3334633730
** Check the existance and status of a file.
3334733731
*/
@@ -33377,10 +33761,11 @@
3337733761
}else{
3337833762
attr = sAttrData.dwFileAttributes;
3337933763
}
3338033764
}else{
3338133765
if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
33766
+ winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
3338233767
free(zConverted);
3338333768
return SQLITE_IOERR_ACCESS;
3338433769
}else{
3338533770
attr = INVALID_FILE_ATTRIBUTES;
3338633771
}
@@ -33440,10 +33825,17 @@
3344033825
3344133826
#if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
3344233827
int nByte;
3344333828
void *zConverted;
3344433829
char *zOut;
33830
+
33831
+ /* If this path name begins with "/X:", where "X" is any alphabetic
33832
+ ** character, discard the initial "/" from the pathname.
33833
+ */
33834
+ if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
33835
+ zRelative++;
33836
+ }
3344533837
3344633838
/* It's odd to simulate an io-error here, but really this is just
3344733839
** using the io-error infrastructure to test that SQLite handles this
3344833840
** function failing. This function could fail if, for example, the
3344933841
** current working directory has been unlinked.
@@ -36252,10 +36644,11 @@
3625236644
#define _WAL_H_
3625336645
3625436646
3625536647
#ifdef SQLITE_OMIT_WAL
3625636648
# define sqlite3WalOpen(x,y,z) 0
36649
+# define sqlite3WalLimit(x,y)
3625736650
# define sqlite3WalClose(w,x,y,z) 0
3625836651
# define sqlite3WalBeginReadTransaction(y,z) 0
3625936652
# define sqlite3WalEndReadTransaction(z)
3626036653
# define sqlite3WalRead(v,w,x,y,z) 0
3626136654
# define sqlite3WalDbsize(y) 0
@@ -36277,13 +36670,16 @@
3627736670
** There is one object of this type for each pager.
3627836671
*/
3627936672
typedef struct Wal Wal;
3628036673
3628136674
/* Open and close a connection to a write-ahead log. */
36282
-SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, int, Wal**);
36675
+SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
3628336676
SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
3628436677
36678
+/* Set the limiting size of a WAL file. */
36679
+SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
36680
+
3628536681
/* Used by readers to open (lock) and close (unlock) a snapshot. A
3628636682
** snapshot is like a read-transaction. It is the state of the database
3628736683
** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
3628836684
** preserves the current state even if the other threads or processes
3628936685
** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
@@ -40628,10 +41024,12 @@
4062841024
int nPathname = 0; /* Number of bytes in zPathname */
4062941025
int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
4063041026
int noReadlock = (flags & PAGER_NO_READLOCK)!=0; /* True to omit read-lock */
4063141027
int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
4063241028
u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
41029
+ const char *zUri = 0; /* URI args to copy */
41030
+ int nUri = 0; /* Number of bytes of URI args at *zUri */
4063341031
4063441032
/* Figure out how much space is required for each journal file-handle
4063541033
** (there are two of them, the main journal and the sub-journal). This
4063641034
** is the maximum space required for an in-memory journal file handle
4063741035
** and a regular journal file-handle. Note that a "regular journal-handle"
@@ -40658,18 +41056,25 @@
4065841056
/* Compute and store the full pathname in an allocated buffer pointed
4065941057
** to by zPathname, length nPathname. Or, if this is a temporary file,
4066041058
** leave both nPathname and zPathname set to 0.
4066141059
*/
4066241060
if( zFilename && zFilename[0] ){
41061
+ const char *z;
4066341062
nPathname = pVfs->mxPathname+1;
4066441063
zPathname = sqlite3Malloc(nPathname*2);
4066541064
if( zPathname==0 ){
4066641065
return SQLITE_NOMEM;
4066741066
}
4066841067
zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
4066941068
rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
4067041069
nPathname = sqlite3Strlen30(zPathname);
41070
+ z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
41071
+ while( *z ){
41072
+ z += sqlite3Strlen30(z)+1;
41073
+ z += sqlite3Strlen30(z)+1;
41074
+ }
41075
+ nUri = &z[1] - zUri;
4067141076
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
4067241077
/* This branch is taken when the journal path required by
4067341078
** the database being opened will be more than pVfs->mxPathname
4067441079
** bytes in length. This means the database cannot be opened,
4067541080
** as it will not be possible to open the journal file or even
@@ -40698,11 +41103,11 @@
4069841103
pPtr = (u8 *)sqlite3MallocZero(
4069941104
ROUND8(sizeof(*pPager)) + /* Pager structure */
4070041105
ROUND8(pcacheSize) + /* PCache object */
4070141106
ROUND8(pVfs->szOsFile) + /* The main db file */
4070241107
journalFileSize * 2 + /* The two journal files */
40703
- nPathname + 1 + /* zFilename */
41108
+ nPathname + 1 + nUri + /* zFilename */
4070441109
nPathname + 8 + 1 /* zJournal */
4070541110
#ifndef SQLITE_OMIT_WAL
4070641111
+ nPathname + 4 + 1 /* zWal */
4070741112
#endif
4070841113
);
@@ -40720,18 +41125,21 @@
4072041125
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
4072141126
4072241127
/* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
4072341128
if( zPathname ){
4072441129
assert( nPathname>0 );
40725
- pPager->zJournal = (char*)(pPtr += nPathname + 1);
41130
+ pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
4072641131
memcpy(pPager->zFilename, zPathname, nPathname);
41132
+ memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
4072741133
memcpy(pPager->zJournal, zPathname, nPathname);
4072841134
memcpy(&pPager->zJournal[nPathname], "-journal", 8);
41135
+ sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
4072941136
#ifndef SQLITE_OMIT_WAL
4073041137
pPager->zWal = &pPager->zJournal[nPathname+8+1];
4073141138
memcpy(pPager->zWal, zPathname, nPathname);
4073241139
memcpy(&pPager->zWal[nPathname], "-wal", 4);
41140
+ sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
4073341141
#endif
4073441142
sqlite3_free(zPathname);
4073541143
}
4073641144
pPager->pVfs = pVfs;
4073741145
pPager->vfsFlags = vfsFlags;
@@ -42064,15 +42472,25 @@
4206442472
*/
4206542473
sqlite3BackupRestart(pPager->pBackup);
4206642474
}else{
4206742475
if( pagerUseWal(pPager) ){
4206842476
PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
42069
- if( pList ){
42477
+ PgHdr *pPageOne = 0;
42478
+ if( pList==0 ){
42479
+ /* Must have at least one page for the WAL commit flag.
42480
+ ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
42481
+ rc = sqlite3PagerGet(pPager, 1, &pPageOne);
42482
+ pList = pPageOne;
42483
+ pList->pDirty = 0;
42484
+ }
42485
+ assert( rc==SQLITE_OK );
42486
+ if( ALWAYS(pList) ){
4207042487
rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1,
4207142488
(pPager->fullSync ? pPager->syncFlags : 0)
4207242489
);
4207342490
}
42491
+ sqlite3PagerUnref(pPageOne);
4207442492
if( rc==SQLITE_OK ){
4207542493
sqlite3PcacheCleanAll(pPager->pPCache);
4207642494
}
4207742495
}else{
4207842496
/* The following block updates the change-counter. Exactly how it
@@ -42926,10 +43344,11 @@
4292643344
** An attempt to set a limit smaller than -1 is a no-op.
4292743345
*/
4292843346
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
4292943347
if( iLimit>=-1 ){
4293043348
pPager->journalSizeLimit = iLimit;
43349
+ sqlite3WalLimit(pPager->pWal, iLimit);
4293143350
}
4293243351
return pPager->journalSizeLimit;
4293343352
}
4293443353
4293543354
/*
@@ -43017,11 +43436,12 @@
4301743436
/* Open the connection to the log file. If this operation fails,
4301843437
** (e.g. due to malloc() failure), return an error code.
4301943438
*/
4302043439
if( rc==SQLITE_OK ){
4302143440
rc = sqlite3WalOpen(pPager->pVfs,
43022
- pPager->fd, pPager->zWal, pPager->exclusiveMode, &pPager->pWal
43441
+ pPager->fd, pPager->zWal, pPager->exclusiveMode,
43442
+ pPager->journalSizeLimit, &pPager->pWal
4302343443
);
4302443444
}
4302543445
4302643446
return rc;
4302743447
}
@@ -43549,10 +43969,11 @@
4354943969
struct Wal {
4355043970
sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
4355143971
sqlite3_file *pDbFd; /* File handle for the database file */
4355243972
sqlite3_file *pWalFd; /* File handle for WAL file */
4355343973
u32 iCallback; /* Value to pass to log callback (or 0) */
43974
+ i64 mxWalSize; /* Truncate WAL to this size upon reset */
4355443975
int nWiData; /* Size of array apWiData */
4355543976
volatile u32 **apWiData; /* Pointer to wal-index content in memory */
4355643977
u32 szPage; /* Database page size */
4355743978
i16 readLock; /* Which read lock is being held. -1 for none */
4355843979
u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
@@ -44371,10 +44792,11 @@
4437144792
SQLITE_PRIVATE int sqlite3WalOpen(
4437244793
sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
4437344794
sqlite3_file *pDbFd, /* The open database file */
4437444795
const char *zWalName, /* Name of the WAL file */
4437544796
int bNoShm, /* True to run in heap-memory mode */
44797
+ i64 mxWalSize, /* Truncate WAL to this size on reset */
4437644798
Wal **ppWal /* OUT: Allocated Wal handle */
4437744799
){
4437844800
int rc; /* Return Code */
4437944801
Wal *pRet; /* Object to allocate and return */
4438044802
int flags; /* Flags passed to OsOpen() */
@@ -44403,10 +44825,11 @@
4440344825
4440444826
pRet->pVfs = pVfs;
4440544827
pRet->pWalFd = (sqlite3_file *)&pRet[1];
4440644828
pRet->pDbFd = pDbFd;
4440744829
pRet->readLock = -1;
44830
+ pRet->mxWalSize = mxWalSize;
4440844831
pRet->zWalName = zWalName;
4440944832
pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
4441044833
4441144834
/* Open file handle on the write-ahead log file. */
4441244835
flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
@@ -44423,10 +44846,17 @@
4442344846
*ppWal = pRet;
4442444847
WALTRACE(("WAL%d: opened\n", pRet));
4442544848
}
4442644849
return rc;
4442744850
}
44851
+
44852
+/*
44853
+** Change the size to which the WAL file is trucated on each reset.
44854
+*/
44855
+SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
44856
+ if( pWal ) pWal->mxWalSize = iLimit;
44857
+}
4442844858
4442944859
/*
4443044860
** Find the smallest page number out of all pages held in the WAL that
4443144861
** has not been returned by any prior invocation of this method on the
4443244862
** same WalIterator object. Write into *piFrame the frame index where
@@ -45659,10 +46089,26 @@
4565946089
** safe and means there is no special case for sqlite3WalUndo()
4566046090
** to handle if this transaction is rolled back.
4566146091
*/
4566246092
int i; /* Loop counter */
4566346093
u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */
46094
+
46095
+ /* Limit the size of WAL file if the journal_size_limit PRAGMA is
46096
+ ** set to a non-negative value. Log errors encountered
46097
+ ** during the truncation attempt. */
46098
+ if( pWal->mxWalSize>=0 ){
46099
+ i64 sz;
46100
+ int rx;
46101
+ rx = sqlite3OsFileSize(pWal->pWalFd, &sz);
46102
+ if( rx==SQLITE_OK && (sz > pWal->mxWalSize) ){
46103
+ rx = sqlite3OsTruncate(pWal->pWalFd, pWal->mxWalSize);
46104
+ }
46105
+ if( rx ){
46106
+ sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
46107
+ }
46108
+ }
46109
+
4566446110
pWal->nCkpt++;
4566546111
pWal->hdr.mxFrame = 0;
4566646112
sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
4566746113
aSalt[1] = salt1;
4566846114
walIndexWriteHdr(pWal);
@@ -47764,10 +48210,11 @@
4776448210
offset = PTRMAP_PTROFFSET(iPtrmap, key);
4776548211
if( offset<0 ){
4776648212
*pRC = SQLITE_CORRUPT_BKPT;
4776748213
goto ptrmap_exit;
4776848214
}
48215
+ assert( offset <= (int)pBt->usableSize-5 );
4776948216
pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
4777048217
4777148218
if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
4777248219
TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));
4777348220
*pRC= rc = sqlite3PagerWrite(pDbPage);
@@ -47803,10 +48250,15 @@
4780348250
return rc;
4780448251
}
4780548252
pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
4780648253
4780748254
offset = PTRMAP_PTROFFSET(iPtrmap, key);
48255
+ if( offset<0 ){
48256
+ sqlite3PagerUnref(pDbPage);
48257
+ return SQLITE_CORRUPT_BKPT;
48258
+ }
48259
+ assert( offset <= (int)pBt->usableSize-5 );
4780848260
assert( pEType!=0 );
4780948261
*pEType = pPtrmap[offset];
4781048262
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
4781148263
4781248264
sqlite3PagerUnref(pDbPage);
@@ -48664,17 +49116,17 @@
4866449116
** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
4866549117
** objects in the same database connection since doing so will lead
4866649118
** to problems with locking.
4866749119
*/
4866849120
SQLITE_PRIVATE int sqlite3BtreeOpen(
49121
+ sqlite3_vfs *pVfs, /* VFS to use for this b-tree */
4866949122
const char *zFilename, /* Name of the file containing the BTree database */
4867049123
sqlite3 *db, /* Associated database handle */
4867149124
Btree **ppBtree, /* Pointer to new Btree object written here */
4867249125
int flags, /* Options */
4867349126
int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */
4867449127
){
48675
- sqlite3_vfs *pVfs; /* The VFS to use for this btree */
4867649128
BtShared *pBt = 0; /* Shared part of btree structure */
4867749129
Btree *p; /* Handle to return */
4867849130
sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */
4867949131
int rc = SQLITE_OK; /* Result code from this function */
4868049132
u8 nReserve; /* Byte of unused space on each page */
@@ -48692,10 +49144,11 @@
4869249144
const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
4869349145
|| (isTempDb && sqlite3TempInMemory(db));
4869449146
#endif
4869549147
4869649148
assert( db!=0 );
49149
+ assert( pVfs!=0 );
4869749150
assert( sqlite3_mutex_held(db->mutex) );
4869849151
assert( (flags&0xff)==flags ); /* flags fit in 8 bits */
4869949152
4870049153
/* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
4870149154
assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
@@ -48710,11 +49163,10 @@
4871049163
flags |= BTREE_MEMORY;
4871149164
}
4871249165
if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
4871349166
vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
4871449167
}
48715
- pVfs = db->pVfs;
4871649168
p = sqlite3MallocZero(sizeof(Btree));
4871749169
if( !p ){
4871849170
return SQLITE_NOMEM;
4871949171
}
4872049172
p->inTrans = TRANS_NONE;
@@ -58781,10 +59233,11 @@
5878159233
sqlite3_randomness(sizeof(iRandom), &iRandom);
5878259234
zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, iRandom&0x7fffffff);
5878359235
if( !zMaster ){
5878459236
return SQLITE_NOMEM;
5878559237
}
59238
+ sqlite3FileSuffix3(zMainFile, zMaster);
5878659239
rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
5878759240
}while( rc==SQLITE_OK && res );
5878859241
if( rc==SQLITE_OK ){
5878959242
/* Open the master journal. */
5879059243
rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
@@ -58994,10 +59447,19 @@
5899459447
}
5899559448
}
5899659449
}
5899759450
db->nStatement--;
5899859451
p->iStatement = 0;
59452
+
59453
+ if( rc==SQLITE_OK ){
59454
+ if( eOp==SAVEPOINT_ROLLBACK ){
59455
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
59456
+ }
59457
+ if( rc==SQLITE_OK ){
59458
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
59459
+ }
59460
+ }
5899959461
5900059462
/* If the statement transaction is being rolled back, also restore the
5900159463
** database handles deferred constraint counter to the value it had when
5900259464
** the statement transaction was opened. */
5900359465
if( eOp==SAVEPOINT_ROLLBACK ){
@@ -59911,11 +60373,11 @@
5991160373
/* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
5991260374
VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
5991360375
5991460376
/* Compilers may complain that mem1.u.i is potentially uninitialized.
5991560377
** We could initialize it, as shown here, to silence those complaints.
59916
- ** But in fact, mem1.u.i will never actually be used initialized, and doing
60378
+ ** But in fact, mem1.u.i will never actually be used uninitialized, and doing
5991760379
** the unnecessary initialization has a measurable negative performance
5991860380
** impact, since this routine is a very high runner. And so, we choose
5991960381
** to ignore the compiler warnings and leave this variable uninitialized.
5992060382
*/
5992160383
/* mem1.u.i = 0; // not needed, here to silence compiler warning */
@@ -62326,10 +62788,11 @@
6232662788
Mem *pIn2 = 0; /* 2nd input operand */
6232762789
Mem *pIn3 = 0; /* 3rd input operand */
6232862790
Mem *pOut = 0; /* Output operand */
6232962791
int iCompare = 0; /* Result of last OP_Compare operation */
6233062792
int *aPermute = 0; /* Permutation of columns for OP_Compare */
62793
+ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
6233162794
#ifdef VDBE_PROFILE
6233262795
u64 start; /* CPU clock count at start of opcode */
6233362796
int origPc; /* Program counter at start of opcode */
6233462797
#endif
6233562798
/********************************************************************
@@ -63004,10 +63467,11 @@
6300463467
VdbeFrame *pFrame = p->pFrame;
6300563468
p->pFrame = pFrame->pParent;
6300663469
p->nFrame--;
6300763470
sqlite3VdbeSetChanges(db, p->nChange);
6300863471
pc = sqlite3VdbeFrameRestore(pFrame);
63472
+ lastRowid = db->lastRowid;
6300963473
if( pOp->p2==OE_Ignore ){
6301063474
/* Instruction pc is the OP_Program that invoked the sub-program
6301163475
** currently being halted. If the p2 instruction of this OP_Halt
6301263476
** instruction is set to OE_Ignore, then the sub-program is throwing
6301363477
** an IGNORE exception. In this case jump to the address specified
@@ -63576,11 +64040,13 @@
6357664040
assert( pOp>aOp );
6357764041
assert( pOp[-1].p4type==P4_COLLSEQ );
6357864042
assert( pOp[-1].opcode==OP_CollSeq );
6357964043
u.ag.ctx.pColl = pOp[-1].p4.pColl;
6358064044
}
64045
+ db->lastRowid = lastRowid;
6358164046
(*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); /* IMP: R-24505-23230 */
64047
+ lastRowid = db->lastRowid;
6358264048
if( db->mallocFailed ){
6358364049
/* Even though a malloc() has failed, the implementation of the
6358464050
** user function may have called an sqlite3_result_XXX() function
6358564051
** to return a value. The following call releases any resources
6358664052
** associated with such a value.
@@ -64783,10 +65249,18 @@
6478365249
"SQL statements in progress");
6478465250
rc = SQLITE_BUSY;
6478565251
}else{
6478665252
u.aq.nName = sqlite3Strlen30(u.aq.zName);
6478765253
65254
+ /* This call is Ok even if this savepoint is actually a transaction
65255
+ ** savepoint (and therefore should not prompt xSavepoint()) callbacks.
65256
+ ** If this is a transaction savepoint being opened, it is guaranteed
65257
+ ** that the db->aVTrans[] array is empty. */
65258
+ assert( db->autoCommit==0 || db->nVTrans==0 );
65259
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement);
65260
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
65261
+
6478865262
/* Create a new savepoint structure. */
6478965263
u.aq.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.aq.nName+1);
6479065264
if( u.aq.pNew ){
6479165265
u.aq.pNew->zName = (char *)&u.aq.pNew[1];
6479265266
memcpy(u.aq.pNew->zName, u.aq.zName, u.aq.nName+1);
@@ -64889,10 +65363,15 @@
6488965363
db->nSavepoint--;
6489065364
}
6489165365
}else{
6489265366
db->nDeferredCons = u.aq.pSavepoint->nDeferredCons;
6489365367
}
65368
+
65369
+ if( !isTransaction ){
65370
+ rc = sqlite3VtabSavepoint(db, u.aq.p1, u.aq.iSavepoint);
65371
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
65372
+ }
6489465373
}
6489565374
}
6489665375
6489765376
break;
6489865377
}
@@ -65028,11 +65507,15 @@
6502865507
if( p->iStatement==0 ){
6502965508
assert( db->nStatement>=0 && db->nSavepoint>=0 );
6503065509
db->nStatement++;
6503165510
p->iStatement = db->nSavepoint + db->nStatement;
6503265511
}
65033
- rc = sqlite3BtreeBeginStmt(u.as.pBt, p->iStatement);
65512
+
65513
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement);
65514
+ if( rc==SQLITE_OK ){
65515
+ rc = sqlite3BtreeBeginStmt(u.as.pBt, p->iStatement);
65516
+ }
6503465517
6503565518
/* Store the current value of the database handles deferred constraint
6503665519
** counter. If the statement transaction needs to be rolled back,
6503765520
** the value of this counter needs to be restored too. */
6503865521
p->nStmtDefCons = db->nDeferredCons;
@@ -65349,11 +65832,11 @@
6534965832
6535065833
assert( pOp->p1>=0 );
6535165834
u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
6535265835
if( u.ax.pCx==0 ) goto no_mem;
6535365836
u.ax.pCx->nullRow = 1;
65354
- rc = sqlite3BtreeOpen(0, db, &u.ax.pCx->pBt,
65837
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
6535565838
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
6535665839
if( rc==SQLITE_OK ){
6535765840
rc = sqlite3BtreeBeginTrans(u.ax.pCx->pBt, 1);
6535865841
}
6535965842
if( rc==SQLITE_OK ){
@@ -66023,11 +66506,11 @@
6602366506
** engine starts picking positive candidate ROWIDs at random until
6602466507
** it finds one that is not previously used. */
6602566508
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
6602666509
** an AUTOINCREMENT table. */
6602766510
/* on the first attempt, simply do one more than previous */
66028
- u.be.v = db->lastRowid;
66511
+ u.be.v = lastRowid;
6602966512
u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
6603066513
u.be.v++; /* ensure non-zero */
6603166514
u.be.cnt = 0;
6603266515
while( ((rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v,
6603366516
0, &u.be.res))==SQLITE_OK)
@@ -66135,11 +66618,11 @@
6613566618
assert( pOp->opcode==OP_InsertInt );
6613666619
u.bf.iKey = pOp->p3;
6613766620
}
6613866621
6613966622
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
66140
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = u.bf.iKey;
66623
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bf.iKey;
6614166624
if( u.bf.pData->flags & MEM_Null ){
6614266625
u.bf.pData->z = 0;
6614366626
u.bf.pData->n = 0;
6614466627
}else{
6614566628
assert( u.bf.pData->flags & (MEM_Blob|MEM_Str) );
@@ -67261,11 +67744,11 @@
6726167744
assert( pc==u.by.pFrame->pc );
6726267745
}
6726367746
6726467747
p->nFrame++;
6726567748
u.by.pFrame->pParent = p->pFrame;
67266
- u.by.pFrame->lastRowid = db->lastRowid;
67749
+ u.by.pFrame->lastRowid = lastRowid;
6726767750
u.by.pFrame->nChange = p->nChange;
6726867751
p->nChange = 0;
6726967752
p->pFrame = u.by.pFrame;
6727067753
p->aMem = aMem = &VdbeFrameMem(u.by.pFrame)[-1];
6727167754
p->nMem = u.by.pFrame->nChildMem;
@@ -68072,31 +68555,45 @@
6807268555
sqlite_int64 rowid;
6807368556
Mem **apArg;
6807468557
Mem *pX;
6807568558
#endif /* local variables moved into u.cm */
6807668559
68560
+ assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
68561
+ || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
68562
+ );
6807768563
u.cm.pVtab = pOp->p4.pVtab->pVtab;
6807868564
u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
6807968565
u.cm.nArg = pOp->p2;
6808068566
assert( pOp->p4type==P4_VTAB );
6808168567
if( ALWAYS(u.cm.pModule->xUpdate) ){
68568
+ u8 vtabOnConflict = db->vtabOnConflict;
6808268569
u.cm.apArg = p->apArg;
6808368570
u.cm.pX = &aMem[pOp->p3];
6808468571
for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){
6808568572
assert( memIsValid(u.cm.pX) );
6808668573
memAboutToChange(p, u.cm.pX);
6808768574
sqlite3VdbeMemStoreType(u.cm.pX);
6808868575
u.cm.apArg[u.cm.i] = u.cm.pX;
6808968576
u.cm.pX++;
6809068577
}
68578
+ db->vtabOnConflict = pOp->p5;
6809168579
rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
68580
+ db->vtabOnConflict = vtabOnConflict;
6809268581
importVtabErrMsg(p, u.cm.pVtab);
6809368582
if( rc==SQLITE_OK && pOp->p1 ){
6809468583
assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) );
68095
- db->lastRowid = u.cm.rowid;
68584
+ db->lastRowid = lastRowid = u.cm.rowid;
6809668585
}
68097
- p->nChange++;
68586
+ if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
68587
+ if( pOp->p5==OE_Ignore ){
68588
+ rc = SQLITE_OK;
68589
+ }else{
68590
+ p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
68591
+ }
68592
+ }else{
68593
+ p->nChange++;
68594
+ }
6809868595
}
6809968596
break;
6810068597
}
6810168598
#endif /* SQLITE_OMIT_VIRTUALTABLE */
6810268599
@@ -68242,10 +68739,11 @@
6824268739
6824368740
/* This is the only way out of this procedure. We have to
6824468741
** release the mutexes on btrees that were acquired at the
6824568742
** top. */
6824668743
vdbe_return:
68744
+ db->lastRowid = lastRowid;
6824768745
sqlite3VdbeLeave(p);
6824868746
return rc;
6824968747
6825068748
/* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
6825168749
** is encountered.
@@ -75970,12 +76468,16 @@
7597076468
int i;
7597176469
int rc = 0;
7597276470
sqlite3 *db = sqlite3_context_db_handle(context);
7597376471
const char *zName;
7597476472
const char *zFile;
76473
+ char *zPath = 0;
76474
+ char *zErr = 0;
76475
+ unsigned int flags;
7597576476
Db *aNew;
7597676477
char *zErrDyn = 0;
76478
+ sqlite3_vfs *pVfs;
7597776479
7597876480
UNUSED_PARAMETER(NotUsed);
7597976481
7598076482
zFile = (const char *)sqlite3_value_text(argv[0]);
7598176483
zName = (const char *)sqlite3_value_text(argv[1]);
@@ -76024,12 +76526,22 @@
7602476526
7602576527
/* Open the database file. If the btree is successfully opened, use
7602676528
** it to obtain the database schema. At this point the schema may
7602776529
** or may not be initialised.
7602876530
*/
76029
- rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0,
76030
- db->openFlags | SQLITE_OPEN_MAIN_DB);
76531
+ flags = db->openFlags;
76532
+ rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
76533
+ if( rc!=SQLITE_OK ){
76534
+ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
76535
+ sqlite3_result_error(context, zErr, -1);
76536
+ sqlite3_free(zErr);
76537
+ return;
76538
+ }
76539
+ assert( pVfs );
76540
+ flags |= SQLITE_OPEN_MAIN_DB;
76541
+ rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
76542
+ sqlite3_free( zPath );
7603176543
db->nDb++;
7603276544
if( rc==SQLITE_CONSTRAINT ){
7603376545
rc = SQLITE_ERROR;
7603476546
zErrDyn = sqlite3MPrintf(db, "database is already attached");
7603576547
}else if( rc==SQLITE_OK ){
@@ -80139,11 +80651,11 @@
8013980651
SQLITE_OPEN_CREATE |
8014080652
SQLITE_OPEN_EXCLUSIVE |
8014180653
SQLITE_OPEN_DELETEONCLOSE |
8014280654
SQLITE_OPEN_TEMP_DB;
8014380655
80144
- rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags);
80656
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
8014580657
if( rc!=SQLITE_OK ){
8014680658
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
8014780659
"file for storing temporary tables");
8014880660
pParse->rc = rc;
8014980661
return 1;
@@ -82329,10 +82841,25 @@
8232982841
UNUSED_PARAMETER2(NotUsed, NotUsed2);
8233082842
/* IMP: R-24470-31136 This function is an SQL wrapper around the
8233182843
** sqlite3_sourceid() C interface. */
8233282844
sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
8233382845
}
82846
+
82847
+/*
82848
+** Implementation of the sqlite_log() function. This is a wrapper around
82849
+** sqlite3_log(). The return value is NULL. The function exists purely for
82850
+** its side-effects.
82851
+*/
82852
+static void errlogFunc(
82853
+ sqlite3_context *context,
82854
+ int argc,
82855
+ sqlite3_value **argv
82856
+){
82857
+ UNUSED_PARAMETER(argc);
82858
+ UNUSED_PARAMETER(context);
82859
+ sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1]));
82860
+}
8233482861
8233582862
/*
8233682863
** Implementation of the sqlite_compileoption_used() function.
8233782864
** The result is an integer that identifies if the compiler option
8233882865
** was used to build SQLite.
@@ -83097,10 +83624,11 @@
8309783624
FUNCTION(random, 0, 0, 0, randomFunc ),
8309883625
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
8309983626
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
8310083627
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
8310183628
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
83629
+ FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
8310283630
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
8310383631
FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
8310483632
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
8310583633
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
8310683634
FUNCTION(quote, 1, 0, 0, quoteFunc ),
@@ -85309,10 +85837,11 @@
8530985837
#ifndef SQLITE_OMIT_VIRTUALTABLE
8531085838
if( IsVirtual(pTab) ){
8531185839
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
8531285840
sqlite3VtabMakeWritable(pParse, pTab);
8531385841
sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
85842
+ sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
8531485843
sqlite3MayAbort(pParse);
8531585844
}else
8531685845
#endif
8531785846
{
8531885847
int isReplace; /* Set to true if constraints may cause a replace */
@@ -86073,10 +86602,22 @@
8607386602
}
8607486603
#ifndef SQLITE_OMIT_CHECK
8607586604
if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
8607686605
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
8607786606
}
86607
+#endif
86608
+#ifndef SQLITE_OMIT_FOREIGN_KEY
86609
+ /* Disallow the transfer optimization if the destination table constains
86610
+ ** any foreign key constraints. This is more restrictive than necessary.
86611
+ ** But the main beneficiary of the transfer optimization is the VACUUM
86612
+ ** command, and the VACUUM command disables foreign key constraints. So
86613
+ ** the extra complication to make this rule less restrictive is probably
86614
+ ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
86615
+ */
86616
+ if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
86617
+ return 0;
86618
+ }
8607886619
#endif
8607986620
8608086621
/* If we get this far, it means either:
8608186622
**
8608286623
** * We can always do the transfer if the table contains an
@@ -87442,11 +87983,11 @@
8744287983
}
8744387984
8744487985
/*
8744587986
** Interpret the given string as a boolean value.
8744687987
*/
87447
-static u8 getBoolean(const char *z){
87988
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z){
8744887989
return getSafetyLevel(z)&1;
8744987990
}
8745087991
8745187992
/*
8745287993
** Interpret the given string as a locking mode value.
@@ -87612,11 +88153,11 @@
8761288153
/* Foreign key support may not be enabled or disabled while not
8761388154
** in auto-commit mode. */
8761488155
mask &= ~(SQLITE_ForeignKeys);
8761588156
}
8761688157
87617
- if( getBoolean(zRight) ){
88158
+ if( sqlite3GetBoolean(zRight) ){
8761888159
db->flags |= mask;
8761988160
}else{
8762088161
db->flags &= ~mask;
8762188162
}
8762288163
@@ -87826,11 +88367,11 @@
8782688367
if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
8782788368
Btree *pBt = pDb->pBt;
8782888369
int b = -1;
8782988370
assert( pBt!=0 );
8783088371
if( zRight ){
87831
- b = getBoolean(zRight);
88372
+ b = sqlite3GetBoolean(zRight);
8783288373
}
8783388374
if( pId2->n==0 && b>=0 ){
8783488375
int ii;
8783588376
for(ii=0; ii<db->nDb; ii++){
8783688377
sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
@@ -88426,11 +88967,11 @@
8842688967
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
8842788968
8842888969
#ifndef NDEBUG
8842988970
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
8843088971
if( zRight ){
88431
- if( getBoolean(zRight) ){
88972
+ if( sqlite3GetBoolean(zRight) ){
8843288973
sqlite3ParserTrace(stderr, "parser: ");
8843388974
}else{
8843488975
sqlite3ParserTrace(0, 0);
8843588976
}
8843688977
}
@@ -88440,11 +88981,11 @@
8844088981
/* Reinstall the LIKE and GLOB functions. The variant of LIKE
8844188982
** used will be case sensitive or not depending on the RHS.
8844288983
*/
8844388984
if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
8844488985
if( zRight ){
88445
- sqlite3RegisterLikeFunctions(db, getBoolean(zRight));
88986
+ sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight));
8844688987
}
8844788988
}else
8844888989
8844988990
#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
8845088991
# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
@@ -94017,16 +94558,18 @@
9401794558
** does, then we can assume that it consumes less space on disk and
9401894559
** will therefore be cheaper to scan to determine the query result.
9401994560
** In this case set iRoot to the root page number of the index b-tree
9402094561
** and pKeyInfo to the KeyInfo structure required to navigate the
9402194562
** index.
94563
+ **
94564
+ ** (2011-04-15) Do not do a full scan of an unordered index.
9402294565
**
9402394566
** In practice the KeyInfo structure will not be used. It is only
9402494567
** passed to keep OP_OpenRead happy.
9402594568
*/
9402694569
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
94027
- if( !pBest || pIdx->nColumn<pBest->nColumn ){
94570
+ if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
9402894571
pBest = pIdx;
9402994572
}
9403094573
}
9403194574
if( pBest && pBest->nColumn<pTab->nCol ){
9403294575
iRoot = pBest->tnum;
@@ -95579,11 +96122,12 @@
9557996122
SrcList *pSrc, /* The virtual table to be modified */
9558096123
Table *pTab, /* The virtual table */
9558196124
ExprList *pChanges, /* The columns to change in the UPDATE statement */
9558296125
Expr *pRowidExpr, /* Expression used to recompute the rowid */
9558396126
int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
95584
- Expr *pWhere /* WHERE clause of the UPDATE statement */
96127
+ Expr *pWhere, /* WHERE clause of the UPDATE statement */
96128
+ int onError /* ON CONFLICT strategy */
9558596129
);
9558696130
#endif /* SQLITE_OMIT_VIRTUALTABLE */
9558796131
9558896132
/*
9558996133
** The most recently coded instruction was an OP_Column to retrieve the
@@ -95823,11 +96367,11 @@
9582396367
9582496368
#ifndef SQLITE_OMIT_VIRTUALTABLE
9582596369
/* Virtual tables must be handled separately */
9582696370
if( IsVirtual(pTab) ){
9582796371
updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
95828
- pWhere);
96372
+ pWhere, onError);
9582996373
pWhere = 0;
9583096374
pTabList = 0;
9583196375
goto update_cleanup;
9583296376
}
9583396377
#endif
@@ -96153,11 +96697,12 @@
9615396697
SrcList *pSrc, /* The virtual table to be modified */
9615496698
Table *pTab, /* The virtual table */
9615596699
ExprList *pChanges, /* The columns to change in the UPDATE statement */
9615696700
Expr *pRowid, /* Expression used to recompute the rowid */
9615796701
int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
96158
- Expr *pWhere /* WHERE clause of the UPDATE statement */
96702
+ Expr *pWhere, /* WHERE clause of the UPDATE statement */
96703
+ int onError /* ON CONFLICT strategy */
9615996704
){
9616096705
Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
9616196706
ExprList *pEList = 0; /* The result set of the SELECT statement */
9616296707
Select *pSelect = 0; /* The SELECT statement */
9616396708
Expr *pExpr; /* Temporary expression */
@@ -96210,10 +96755,11 @@
9621096755
for(i=0; i<pTab->nCol; i++){
9621196756
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i);
9621296757
}
9621396758
sqlite3VtabMakeWritable(pParse, pTab);
9621496759
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
96760
+ sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
9621596761
sqlite3MayAbort(pParse);
9621696762
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1);
9621796763
sqlite3VdbeJumpHere(v, addr);
9621896764
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
9621996765
@@ -96583,10 +97129,22 @@
9658397129
*************************************************************************
9658497130
** This file contains code used to help implement virtual tables.
9658597131
*/
9658697132
#ifndef SQLITE_OMIT_VIRTUALTABLE
9658797133
97134
+/*
97135
+** Before a virtual table xCreate() or xConnect() method is invoked, the
97136
+** sqlite3.pVtabCtx member variable is set to point to an instance of
97137
+** this struct allocated on the stack. It is used by the implementation of
97138
+** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
97139
+** are invoked only from within xCreate and xConnect methods.
97140
+*/
97141
+struct VtabCtx {
97142
+ Table *pTab;
97143
+ VTable *pVTable;
97144
+};
97145
+
9658897146
/*
9658997147
** The actual function that does the work of creating a new module.
9659097148
** This function implements the sqlite3_create_module() and
9659197149
** sqlite3_create_module_v2() interfaces.
9659297150
*/
@@ -96611,17 +97169,17 @@
9661197169
pMod->pModule = pModule;
9661297170
pMod->pAux = pAux;
9661397171
pMod->xDestroy = xDestroy;
9661497172
pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
9661597173
if( pDel && pDel->xDestroy ){
97174
+ sqlite3ResetInternalSchema(db, -1);
9661697175
pDel->xDestroy(pDel->pAux);
9661797176
}
9661897177
sqlite3DbFree(db, pDel);
9661997178
if( pDel==pMod ){
9662097179
db->mallocFailed = 1;
9662197180
}
96622
- sqlite3ResetInternalSchema(db, -1);
9662397181
}else if( xDestroy ){
9662497182
xDestroy(pAux);
9662597183
}
9662697184
rc = sqlite3ApiExit(db, SQLITE_OK);
9662797185
sqlite3_mutex_leave(db->mutex);
@@ -97003,10 +97561,11 @@
9700397561
Table *pTab,
9700497562
Module *pMod,
9700597563
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
9700697564
char **pzErr
9700797565
){
97566
+ VtabCtx sCtx;
9700897567
VTable *pVTable;
9700997568
int rc;
9701097569
const char *const*azArg = (const char *const*)pTab->azModuleArg;
9701197570
int nArg = pTab->nModuleArg;
9701297571
char *zErr = 0;
@@ -97022,16 +97581,18 @@
9702297581
return SQLITE_NOMEM;
9702397582
}
9702497583
pVTable->db = db;
9702597584
pVTable->pMod = pMod;
9702697585
97027
- assert( !db->pVTab );
97586
+ /* Invoke the virtual table constructor */
97587
+ assert( &db->pVtabCtx );
9702897588
assert( xConstruct );
97029
- db->pVTab = pTab;
97030
-
97031
- /* Invoke the virtual table constructor */
97589
+ sCtx.pTab = pTab;
97590
+ sCtx.pVTable = pVTable;
97591
+ db->pVtabCtx = &sCtx;
9703297592
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
97593
+ db->pVtabCtx = 0;
9703397594
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
9703497595
9703597596
if( SQLITE_OK!=rc ){
9703697597
if( zErr==0 ){
9703797598
*pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
@@ -97043,11 +97604,11 @@
9704397604
}else if( ALWAYS(pVTable->pVtab) ){
9704497605
/* Justification of ALWAYS(): A correct vtab constructor must allocate
9704597606
** the sqlite3_vtab object if successful. */
9704697607
pVTable->pVtab->pModule = pMod->pModule;
9704797608
pVTable->nRef = 1;
97048
- if( db->pVTab ){
97609
+ if( sCtx.pTab ){
9704997610
const char *zFormat = "vtable constructor did not declare schema: %s";
9705097611
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
9705197612
sqlite3VtabUnlock(pVTable);
9705297613
rc = SQLITE_ERROR;
9705397614
}else{
@@ -97091,11 +97652,10 @@
9709197652
}
9709297653
}
9709397654
}
9709497655
9709597656
sqlite3DbFree(db, zModuleName);
97096
- db->pVTab = 0;
9709797657
return rc;
9709897658
}
9709997659
9710097660
/*
9710197661
** This function is invoked by the parser to call the xConnect() method
@@ -97211,12 +97771,11 @@
9721197771
int rc = SQLITE_OK;
9721297772
Table *pTab;
9721397773
char *zErr = 0;
9721497774
9721597775
sqlite3_mutex_enter(db->mutex);
97216
- pTab = db->pVTab;
97217
- if( !pTab ){
97776
+ if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
9721897777
sqlite3Error(db, SQLITE_MISUSE, 0);
9721997778
sqlite3_mutex_leave(db->mutex);
9722097779
return SQLITE_MISUSE_BKPT;
9722197780
}
9722297781
assert( (pTab->tabFlags & TF_Virtual)!=0 );
@@ -97239,11 +97798,11 @@
9723997798
pTab->aCol = pParse->pNewTable->aCol;
9724097799
pTab->nCol = pParse->pNewTable->nCol;
9724197800
pParse->pNewTable->nCol = 0;
9724297801
pParse->pNewTable->aCol = 0;
9724397802
}
97244
- db->pVTab = 0;
97803
+ db->pVtabCtx->pTab = 0;
9724597804
}else{
9724697805
sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
9724797806
sqlite3DbFree(db, zErr);
9724897807
rc = SQLITE_ERROR;
9724997808
}
@@ -97391,11 +97950,10 @@
9739197950
pModule = pVTab->pVtab->pModule;
9739297951
9739397952
if( pModule->xBegin ){
9739497953
int i;
9739597954
97396
-
9739797955
/* If pVtab is already in the aVTrans array, return early */
9739897956
for(i=0; i<db->nVTrans; i++){
9739997957
if( db->aVTrans[i]==pVTab ){
9740097958
return SQLITE_OK;
9740197959
}
@@ -97404,10 +97962,53 @@
9740497962
/* Invoke the xBegin method */
9740597963
rc = pModule->xBegin(pVTab->pVtab);
9740697964
if( rc==SQLITE_OK ){
9740797965
rc = addToVTrans(db, pVTab);
9740897966
}
97967
+ }
97968
+ return rc;
97969
+}
97970
+
97971
+/*
97972
+** Invoke either the xSavepoint, xRollbackTo or xRelease method of all
97973
+** virtual tables that currently have an open transaction. Pass iSavepoint
97974
+** as the second argument to the virtual table method invoked.
97975
+**
97976
+** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is
97977
+** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is
97978
+** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with
97979
+** an open transaction is invoked.
97980
+**
97981
+** If any virtual table method returns an error code other than SQLITE_OK,
97982
+** processing is abandoned and the error returned to the caller of this
97983
+** function immediately. If all calls to virtual table methods are successful,
97984
+** SQLITE_OK is returned.
97985
+*/
97986
+SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
97987
+ int rc = SQLITE_OK;
97988
+
97989
+ assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
97990
+ if( db->aVTrans ){
97991
+ int i;
97992
+ for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
97993
+ const sqlite3_module *pMod = db->aVTrans[i]->pMod->pModule;
97994
+ if( pMod->iVersion>=2 ){
97995
+ int (*xMethod)(sqlite3_vtab *, int);
97996
+ switch( op ){
97997
+ case SAVEPOINT_BEGIN:
97998
+ xMethod = pMod->xSavepoint;
97999
+ break;
98000
+ case SAVEPOINT_ROLLBACK:
98001
+ xMethod = pMod->xRollbackTo;
98002
+ break;
98003
+ default:
98004
+ xMethod = pMod->xRelease;
98005
+ break;
98006
+ }
98007
+ if( xMethod ) rc = xMethod(db->aVTrans[i]->pVtab, iSavepoint);
98008
+ }
98009
+ }
9740998010
}
9741098011
return rc;
9741198012
}
9741298013
9741398014
/*
@@ -97505,10 +98106,61 @@
9750598106
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
9750698107
}else{
9750798108
pToplevel->db->mallocFailed = 1;
9750898109
}
9750998110
}
98111
+
98112
+/*
98113
+** Return the ON CONFLICT resolution mode in effect for the virtual
98114
+** table update operation currently in progress.
98115
+**
98116
+** The results of this routine are undefined unless it is called from
98117
+** within an xUpdate method.
98118
+*/
98119
+SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){
98120
+ static const unsigned char aMap[] = {
98121
+ SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
98122
+ };
98123
+ assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
98124
+ assert( OE_Ignore==4 && OE_Replace==5 );
98125
+ assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
98126
+ return (int)aMap[db->vtabOnConflict-1];
98127
+}
98128
+
98129
+/*
98130
+** Call from within the xCreate() or xConnect() methods to provide
98131
+** the SQLite core with additional information about the behavior
98132
+** of the virtual table being implemented.
98133
+*/
98134
+SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
98135
+ va_list ap;
98136
+ int rc = SQLITE_OK;
98137
+
98138
+ sqlite3_mutex_enter(db->mutex);
98139
+
98140
+ va_start(ap, op);
98141
+ switch( op ){
98142
+ case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
98143
+ VtabCtx *p = db->pVtabCtx;
98144
+ if( !p ){
98145
+ rc = SQLITE_MISUSE_BKPT;
98146
+ }else{
98147
+ assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
98148
+ p->pVTable->bConstraint = (u8)va_arg(ap, int);
98149
+ }
98150
+ break;
98151
+ }
98152
+ default:
98153
+ rc = SQLITE_MISUSE_BKPT;
98154
+ break;
98155
+ }
98156
+ va_end(ap);
98157
+
98158
+ if( rc!=SQLITE_OK ) sqlite3Error(db, rc, 0);
98159
+ sqlite3_mutex_leave(db->mutex);
98160
+ return rc;
98161
+}
9751098162
9751198163
#endif /* SQLITE_OMIT_VIRTUALTABLE */
9751298164
9751398165
/************** End of vtab.c ************************************************/
9751498166
/************** Begin file where.c *******************************************/
@@ -107527,10 +108179,15 @@
107527108179
typedef void(*LOGFUNC_t)(void*,int,const char*);
107528108180
sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
107529108181
sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
107530108182
break;
107531108183
}
108184
+
108185
+ case SQLITE_CONFIG_URI: {
108186
+ sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
108187
+ break;
108188
+ }
107532108189
107533108190
default: {
107534108191
rc = SQLITE_ERROR;
107535108192
break;
107536108193
}
@@ -108886,25 +109543,257 @@
108886109543
}
108887109544
db->aLimit[limitId] = newLimit;
108888109545
}
108889109546
return oldLimit; /* IMP: R-53341-35419 */
108890109547
}
109548
+
109549
+/*
109550
+** This function is used to parse both URIs and non-URI filenames passed by the
109551
+** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
109552
+** URIs specified as part of ATTACH statements.
109553
+**
109554
+** The first argument to this function is the name of the VFS to use (or
109555
+** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
109556
+** query parameter. The second argument contains the URI (or non-URI filename)
109557
+** itself. When this function is called the *pFlags variable should contain
109558
+** the default flags to open the database handle with. The value stored in
109559
+** *pFlags may be updated before returning if the URI filename contains
109560
+** "cache=xxx" or "mode=xxx" query parameters.
109561
+**
109562
+** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
109563
+** the VFS that should be used to open the database file. *pzFile is set to
109564
+** point to a buffer containing the name of the file to open. It is the
109565
+** responsibility of the caller to eventually call sqlite3_free() to release
109566
+** this buffer.
109567
+**
109568
+** If an error occurs, then an SQLite error code is returned and *pzErrMsg
109569
+** may be set to point to a buffer containing an English language error
109570
+** message. It is the responsibility of the caller to eventually release
109571
+** this buffer by calling sqlite3_free().
109572
+*/
109573
+SQLITE_PRIVATE int sqlite3ParseUri(
109574
+ const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
109575
+ const char *zUri, /* Nul-terminated URI to parse */
109576
+ unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */
109577
+ sqlite3_vfs **ppVfs, /* OUT: VFS to use */
109578
+ char **pzFile, /* OUT: Filename component of URI */
109579
+ char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
109580
+){
109581
+ int rc = SQLITE_OK;
109582
+ unsigned int flags = *pFlags;
109583
+ const char *zVfs = zDefaultVfs;
109584
+ char *zFile;
109585
+ char c;
109586
+ int nUri = sqlite3Strlen30(zUri);
109587
+
109588
+ assert( *pzErrMsg==0 );
109589
+
109590
+ if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
109591
+ && nUri>=5 && memcmp(zUri, "file:", 5)==0
109592
+ ){
109593
+ char *zOpt;
109594
+ int eState; /* Parser state when parsing URI */
109595
+ int iIn; /* Input character index */
109596
+ int iOut = 0; /* Output character index */
109597
+ int nByte = nUri+2; /* Bytes of space to allocate */
109598
+
109599
+ /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
109600
+ ** method that there may be extra parameters following the file-name. */
109601
+ flags |= SQLITE_OPEN_URI;
109602
+
109603
+ for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
109604
+ zFile = sqlite3_malloc(nByte);
109605
+ if( !zFile ) return SQLITE_NOMEM;
109606
+
109607
+ /* Discard the scheme and authority segments of the URI. */
109608
+ if( zUri[5]=='/' && zUri[6]=='/' ){
109609
+ iIn = 7;
109610
+ while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
109611
+
109612
+ if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
109613
+ *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
109614
+ iIn-7, &zUri[7]);
109615
+ rc = SQLITE_ERROR;
109616
+ goto parse_uri_out;
109617
+ }
109618
+ }else{
109619
+ iIn = 5;
109620
+ }
109621
+
109622
+ /* Copy the filename and any query parameters into the zFile buffer.
109623
+ ** Decode %HH escape codes along the way.
109624
+ **
109625
+ ** Within this loop, variable eState may be set to 0, 1 or 2, depending
109626
+ ** on the parsing context. As follows:
109627
+ **
109628
+ ** 0: Parsing file-name.
109629
+ ** 1: Parsing name section of a name=value query parameter.
109630
+ ** 2: Parsing value section of a name=value query parameter.
109631
+ */
109632
+ eState = 0;
109633
+ while( (c = zUri[iIn])!=0 && c!='#' ){
109634
+ iIn++;
109635
+ if( c=='%'
109636
+ && sqlite3Isxdigit(zUri[iIn])
109637
+ && sqlite3Isxdigit(zUri[iIn+1])
109638
+ ){
109639
+ int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
109640
+ octet += sqlite3HexToInt(zUri[iIn++]);
109641
+
109642
+ assert( octet>=0 && octet<256 );
109643
+ if( octet==0 ){
109644
+ /* This branch is taken when "%00" appears within the URI. In this
109645
+ ** case we ignore all text in the remainder of the path, name or
109646
+ ** value currently being parsed. So ignore the current character
109647
+ ** and skip to the next "?", "=" or "&", as appropriate. */
109648
+ while( (c = zUri[iIn])!=0 && c!='#'
109649
+ && (eState!=0 || c!='?')
109650
+ && (eState!=1 || (c!='=' && c!='&'))
109651
+ && (eState!=2 || c!='&')
109652
+ ){
109653
+ iIn++;
109654
+ }
109655
+ continue;
109656
+ }
109657
+ c = octet;
109658
+ }else if( eState==1 && (c=='&' || c=='=') ){
109659
+ if( zFile[iOut-1]==0 ){
109660
+ /* An empty option name. Ignore this option altogether. */
109661
+ while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
109662
+ continue;
109663
+ }
109664
+ if( c=='&' ){
109665
+ zFile[iOut++] = '\0';
109666
+ }else{
109667
+ eState = 2;
109668
+ }
109669
+ c = 0;
109670
+ }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
109671
+ c = 0;
109672
+ eState = 1;
109673
+ }
109674
+ zFile[iOut++] = c;
109675
+ }
109676
+ if( eState==1 ) zFile[iOut++] = '\0';
109677
+ zFile[iOut++] = '\0';
109678
+ zFile[iOut++] = '\0';
109679
+
109680
+ /* Check if there were any options specified that should be interpreted
109681
+ ** here. Options that are interpreted here include "vfs" and those that
109682
+ ** correspond to flags that may be passed to the sqlite3_open_v2()
109683
+ ** method. */
109684
+ zOpt = &zFile[sqlite3Strlen30(zFile)+1];
109685
+ while( zOpt[0] ){
109686
+ int nOpt = sqlite3Strlen30(zOpt);
109687
+ char *zVal = &zOpt[nOpt+1];
109688
+ int nVal = sqlite3Strlen30(zVal);
109689
+
109690
+ if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
109691
+ zVfs = zVal;
109692
+ }else{
109693
+ struct OpenMode {
109694
+ const char *z;
109695
+ int mode;
109696
+ } *aMode = 0;
109697
+ char *zModeType;
109698
+ int mask;
109699
+ int limit;
109700
+
109701
+ if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
109702
+ static struct OpenMode aCacheMode[] = {
109703
+ { "shared", SQLITE_OPEN_SHAREDCACHE },
109704
+ { "private", SQLITE_OPEN_PRIVATECACHE },
109705
+ { 0, 0 }
109706
+ };
109707
+
109708
+ mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
109709
+ aMode = aCacheMode;
109710
+ limit = mask;
109711
+ zModeType = "cache";
109712
+ }
109713
+ if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
109714
+ static struct OpenMode aOpenMode[] = {
109715
+ { "ro", SQLITE_OPEN_READONLY },
109716
+ { "rw", SQLITE_OPEN_READWRITE },
109717
+ { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
109718
+ { 0, 0 }
109719
+ };
109720
+
109721
+ mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
109722
+ aMode = aOpenMode;
109723
+ limit = mask & flags;
109724
+ zModeType = "access";
109725
+ }
109726
+
109727
+ if( aMode ){
109728
+ int i;
109729
+ int mode = 0;
109730
+ for(i=0; aMode[i].z; i++){
109731
+ const char *z = aMode[i].z;
109732
+ if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
109733
+ mode = aMode[i].mode;
109734
+ break;
109735
+ }
109736
+ }
109737
+ if( mode==0 ){
109738
+ *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
109739
+ rc = SQLITE_ERROR;
109740
+ goto parse_uri_out;
109741
+ }
109742
+ if( mode>limit ){
109743
+ *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
109744
+ zModeType, zVal);
109745
+ rc = SQLITE_PERM;
109746
+ goto parse_uri_out;
109747
+ }
109748
+ flags = (flags & ~mask) | mode;
109749
+ }
109750
+ }
109751
+
109752
+ zOpt = &zVal[nVal+1];
109753
+ }
109754
+
109755
+ }else{
109756
+ zFile = sqlite3_malloc(nUri+2);
109757
+ if( !zFile ) return SQLITE_NOMEM;
109758
+ memcpy(zFile, zUri, nUri);
109759
+ zFile[nUri] = '\0';
109760
+ zFile[nUri+1] = '\0';
109761
+ }
109762
+
109763
+ *ppVfs = sqlite3_vfs_find(zVfs);
109764
+ if( *ppVfs==0 ){
109765
+ *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
109766
+ rc = SQLITE_ERROR;
109767
+ }
109768
+ parse_uri_out:
109769
+ if( rc!=SQLITE_OK ){
109770
+ sqlite3_free(zFile);
109771
+ zFile = 0;
109772
+ }
109773
+ *pFlags = flags;
109774
+ *pzFile = zFile;
109775
+ return rc;
109776
+}
109777
+
108891109778
108892109779
/*
108893109780
** This routine does the work of opening a database on behalf of
108894109781
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
108895109782
** is UTF-8 encoded.
108896109783
*/
108897109784
static int openDatabase(
108898109785
const char *zFilename, /* Database filename UTF-8 encoded */
108899109786
sqlite3 **ppDb, /* OUT: Returned database handle */
108900
- unsigned flags, /* Operational flags */
109787
+ unsigned int flags, /* Operational flags */
108901109788
const char *zVfs /* Name of the VFS to use */
108902109789
){
108903
- sqlite3 *db;
108904
- int rc;
108905
- int isThreadsafe;
109790
+ sqlite3 *db; /* Store allocated handle here */
109791
+ int rc; /* Return code */
109792
+ int isThreadsafe; /* True for threadsafe connections */
109793
+ char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
109794
+ char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
108906109795
108907109796
*ppDb = 0;
108908109797
#ifndef SQLITE_OMIT_AUTOINIT
108909109798
rc = sqlite3_initialize();
108910109799
if( rc ) return rc;
@@ -108924,11 +109813,11 @@
108924109813
assert( SQLITE_OPEN_READWRITE == 0x02 );
108925109814
assert( SQLITE_OPEN_CREATE == 0x04 );
108926109815
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
108927109816
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
108928109817
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
108929
- if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE;
109818
+ if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;
108930109819
108931109820
if( sqlite3GlobalConfig.bCoreMutex==0 ){
108932109821
isThreadsafe = 0;
108933109822
}else if( flags & SQLITE_OPEN_NOMUTEX ){
108934109823
isThreadsafe = 0;
@@ -109005,17 +109894,10 @@
109005109894
sqlite3HashInit(&db->aCollSeq);
109006109895
#ifndef SQLITE_OMIT_VIRTUALTABLE
109007109896
sqlite3HashInit(&db->aModule);
109008109897
#endif
109009109898
109010
- db->pVfs = sqlite3_vfs_find(zVfs);
109011
- if( !db->pVfs ){
109012
- rc = SQLITE_ERROR;
109013
- sqlite3Error(db, rc, "no such vfs: %s", zVfs);
109014
- goto opendb_out;
109015
- }
109016
-
109017109899
/* Add the default collation sequence BINARY. BINARY works for both UTF-8
109018109900
** and UTF-16, so add a version for each to avoid any unnecessary
109019109901
** conversions. The only error that can occur here is a malloc() failure.
109020109902
*/
109021109903
createCollation(db, "BINARY", SQLITE_UTF8, SQLITE_COLL_BINARY, 0,
@@ -109034,13 +109916,22 @@
109034109916
109035109917
/* Also add a UTF-8 case-insensitive collation sequence. */
109036109918
createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
109037109919
nocaseCollatingFunc, 0);
109038109920
109039
- /* Open the backend database driver */
109921
+ /* Parse the filename/URI argument. */
109040109922
db->openFlags = flags;
109041
- rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0,
109923
+ rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
109924
+ if( rc!=SQLITE_OK ){
109925
+ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
109926
+ sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
109927
+ sqlite3_free(zErrMsg);
109928
+ goto opendb_out;
109929
+ }
109930
+
109931
+ /* Open the backend database driver */
109932
+ rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
109042109933
flags | SQLITE_OPEN_MAIN_DB);
109043109934
if( rc!=SQLITE_OK ){
109044109935
if( rc==SQLITE_IOERR_NOMEM ){
109045109936
rc = SQLITE_NOMEM;
109046109937
}
@@ -109129,10 +110020,11 @@
109129110020
sqlite3GlobalConfig.nLookaside);
109130110021
109131110022
sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
109132110023
109133110024
opendb_out:
110025
+ sqlite3_free(zOpen);
109134110026
if( db ){
109135110027
assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
109136110028
sqlite3_mutex_leave(db->mutex);
109137110029
}
109138110030
rc = sqlite3_errcode(db);
@@ -109160,11 +110052,11 @@
109160110052
const char *filename, /* Database filename (UTF-8) */
109161110053
sqlite3 **ppDb, /* OUT: SQLite db handle */
109162110054
int flags, /* Flags */
109163110055
const char *zVfs /* Name of VFS module to use */
109164110056
){
109165
- return openDatabase(filename, ppDb, flags, zVfs);
110057
+ return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
109166110058
}
109167110059
109168110060
#ifndef SQLITE_OMIT_UTF16
109169110061
/*
109170110062
** Open a new database handle.
@@ -109770,10 +110662,32 @@
109770110662
}
109771110663
va_end(ap);
109772110664
#endif /* SQLITE_OMIT_BUILTIN_TEST */
109773110665
return rc;
109774110666
}
110667
+
110668
+/*
110669
+** This is a utility routine, useful to VFS implementations, that checks
110670
+** to see if a database file was a URI that contained a specific query
110671
+** parameter, and if so obtains the value of the query parameter.
110672
+**
110673
+** The zFilename argument is the filename pointer passed into the xOpen()
110674
+** method of a VFS implementation. The zParam argument is the name of the
110675
+** query parameter we seek. This routine returns the value of the zParam
110676
+** parameter if it exists. If the parameter does not exist, this routine
110677
+** returns a NULL pointer.
110678
+*/
110679
+SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
110680
+ zFilename += sqlite3Strlen30(zFilename) + 1;
110681
+ while( zFilename[0] ){
110682
+ int x = strcmp(zFilename, zParam);
110683
+ zFilename += sqlite3Strlen30(zFilename) + 1;
110684
+ if( x==0 ) return zFilename;
110685
+ zFilename += sqlite3Strlen30(zFilename) + 1;
110686
+ }
110687
+ return 0;
110688
+}
109775110689
109776110690
/************** End of main.c ************************************************/
109777110691
/************** Begin file notify.c ******************************************/
109778110692
/*
109779110693
** 2009 March 3
@@ -110851,10 +111765,11 @@
110851111765
Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
110852111766
sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
110853111767
char *pNextId; /* Pointer into the body of aDoclist */
110854111768
char *aDoclist; /* List of docids for full-text queries */
110855111769
int nDoclist; /* Size of buffer at aDoclist */
111770
+ int desc; /* True to sort in descending order */
110856111771
int eEvalmode; /* An FTS3_EVAL_XX constant */
110857111772
int nRowAvg; /* Average size of database rows, in pages */
110858111773
110859111774
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
110860111775
u32 *aMatchinfo; /* Information about most recent match */
@@ -111033,11 +111948,11 @@
111033111948
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
111034111949
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
111035111950
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
111036111951
SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
111037111952
111038
-SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int);
111953
+SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Cursor *, Fts3Expr *, sqlite3_int64, int);
111039111954
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *, Fts3Expr *);
111040111955
SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(Fts3Cursor *, Fts3Expr *, char **, int *);
111041111956
SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
111042111957
111043111958
/* fts3_tokenizer.c */
@@ -111060,10 +111975,11 @@
111060111975
char **, int, int, const char *, int, Fts3Expr **
111061111976
);
111062111977
SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
111063111978
#ifdef SQLITE_TEST
111064111979
SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
111980
+SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
111065111981
#endif
111066111982
111067111983
/* fts3_aux.c */
111068111984
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
111069111985
@@ -111180,10 +112096,38 @@
111180112096
static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
111181112097
sqlite3_int64 iVal;
111182112098
*pp += sqlite3Fts3GetVarint(*pp, &iVal);
111183112099
*pVal += iVal;
111184112100
}
112101
+
112102
+/*
112103
+** When this function is called, *pp points to the first byte following a
112104
+** varint that is part of a doclist (or position-list, or any other list
112105
+** of varints). This function moves *pp to point to the start of that varint,
112106
+** and decrements the value stored in *pVal by the varint value.
112107
+**
112108
+** Argument pStart points to the first byte of the doclist that the
112109
+** varint is part of.
112110
+*/
112111
+static void fts3GetReverseDeltaVarint(
112112
+ char **pp,
112113
+ char *pStart,
112114
+ sqlite3_int64 *pVal
112115
+){
112116
+ sqlite3_int64 iVal;
112117
+ char *p = *pp;
112118
+
112119
+ /* Pointer p now points at the first byte past the varint we are
112120
+ ** interested in. So, unless the doclist is corrupt, the 0x80 bit is
112121
+ ** clear on character p[-1]. */
112122
+ for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
112123
+ p++;
112124
+ *pp = p;
112125
+
112126
+ sqlite3Fts3GetVarint(p, &iVal);
112127
+ *pVal -= iVal;
112128
+}
111185112129
111186112130
/*
111187112131
** As long as *pp has not reached its end (pEnd), then do the same
111188112132
** as fts3GetDeltaVarint(): read a single varint and add it to *pVal.
111189112133
** But if we have reached the end of the varint, just set *pp=0 and
@@ -111285,10 +112229,12 @@
111285112229
if( *pRc==SQLITE_OK ){
111286112230
int i; /* Iterator variable */
111287112231
int rc; /* Return code */
111288112232
char *zSql; /* SQL statement passed to declare_vtab() */
111289112233
char *zCols; /* List of user defined columns */
112234
+
112235
+ sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
111290112236
111291112237
/* Create a list of user columns for the virtual table */
111292112238
zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
111293112239
for(i=1; zCols && i<p->nColumn; i++){
111294112240
zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
@@ -111854,10 +112800,26 @@
111854112800
111855112801
if( iCons>=0 ){
111856112802
pInfo->aConstraintUsage[iCons].argvIndex = 1;
111857112803
pInfo->aConstraintUsage[iCons].omit = 1;
111858112804
}
112805
+
112806
+ /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
112807
+ ** docid) order. Both ascending and descending are possible.
112808
+ */
112809
+ if( pInfo->nOrderBy==1 ){
112810
+ struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0];
112811
+ if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){
112812
+ if( pOrder->desc ){
112813
+ pInfo->idxStr = "DESC";
112814
+ }else{
112815
+ pInfo->idxStr = "ASC";
112816
+ }
112817
+ }
112818
+ pInfo->orderByConsumed = 1;
112819
+ }
112820
+
111859112821
return SQLITE_OK;
111860112822
}
111861112823
111862112824
/*
111863112825
** Implementation of xOpen method.
@@ -111911,11 +112873,11 @@
111911112873
if( rc==SQLITE_OK ){
111912112874
/* If no row was found and no error has occured, then the %_content
111913112875
** table is missing a row that is present in the full-text index.
111914112876
** The data structures are corrupt.
111915112877
*/
111916
- rc = SQLITE_CORRUPT;
112878
+ rc = SQLITE_CORRUPT_VTAB;
111917112879
}
111918112880
pCsr->isEof = 1;
111919112881
if( pContext ){
111920112882
sqlite3_result_error_code(pContext, rc);
111921112883
}
@@ -111971,11 +112933,11 @@
111971112933
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
111972112934
*/
111973112935
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
111974112936
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
111975112937
if( zCsr>zEnd ){
111976
- return SQLITE_CORRUPT;
112938
+ return SQLITE_CORRUPT_VTAB;
111977112939
}
111978112940
111979112941
while( zCsr<zEnd && (piFirst || piLast) ){
111980112942
int cmp; /* memcmp() result */
111981112943
int nSuffix; /* Size of term suffix */
@@ -111989,11 +112951,11 @@
111989112951
}
111990112952
isFirstTerm = 0;
111991112953
zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
111992112954
111993112955
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
111994
- rc = SQLITE_CORRUPT;
112956
+ rc = SQLITE_CORRUPT_VTAB;
111995112957
goto finish_scan;
111996112958
}
111997112959
if( nPrefix+nSuffix>nAlloc ){
111998112960
char *zNew;
111999112961
nAlloc = (nPrefix+nSuffix) * 2;
@@ -113758,16 +114720,24 @@
113758114720
rc = sqlite3_reset(pCsr->pStmt);
113759114721
break;
113760114722
}
113761114723
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
113762114724
}else{
113763
- if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
113764
- pCsr->isEof = 1;
113765
- break;
114725
+ if( pCsr->desc==0 ){
114726
+ if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
114727
+ pCsr->isEof = 1;
114728
+ break;
114729
+ }
114730
+ fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
114731
+ }else{
114732
+ fts3GetReverseDeltaVarint(&pCsr->pNextId,pCsr->aDoclist,&pCsr->iPrevId);
114733
+ if( pCsr->pNextId<=pCsr->aDoclist ){
114734
+ pCsr->isEof = 1;
114735
+ break;
114736
+ }
113766114737
}
113767114738
sqlite3_reset(pCsr->pStmt);
113768
- fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
113769114739
pCsr->isRequireSeek = 1;
113770114740
pCsr->isMatchinfoNeeded = 1;
113771114741
}
113772114742
}while( SQLITE_OK==(rc = fts3EvalDeferred(pCsr, &res)) && res==0 );
113773114743
@@ -113796,12 +114766,12 @@
113796114766
const char *idxStr, /* Unused */
113797114767
int nVal, /* Number of elements in apVal */
113798114768
sqlite3_value **apVal /* Arguments for the indexing scheme */
113799114769
){
113800114770
const char *azSql[] = {
113801
- "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?", /* non-full-scan */
113802
- "SELECT %s FROM %Q.'%q_content' AS x ", /* full-scan */
114771
+ "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?", /* non-full-scan */
114772
+ "SELECT %s FROM %Q.'%q_content' AS x ORDER BY docid %s", /* full-scan */
113803114773
};
113804114774
int rc; /* Return code */
113805114775
char *zSql; /* SQL statement used to access %_content */
113806114776
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
113807114777
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
@@ -113853,11 +114823,13 @@
113853114823
** statement loops through all rows of the %_content table. For a
113854114824
** full-text query or docid lookup, the statement retrieves a single
113855114825
** row by docid.
113856114826
*/
113857114827
zSql = (char *)azSql[idxNum==FTS3_FULLSCAN_SEARCH];
113858
- zSql = sqlite3_mprintf(zSql, p->zReadExprlist, p->zDb, p->zName);
114828
+ zSql = sqlite3_mprintf(
114829
+ zSql, p->zReadExprlist, p->zDb, p->zName, (idxStr ? idxStr : "ASC")
114830
+ );
113859114831
if( !zSql ){
113860114832
rc = SQLITE_NOMEM;
113861114833
}else{
113862114834
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
113863114835
sqlite3_free(zSql);
@@ -113865,11 +114837,26 @@
113865114837
if( rc==SQLITE_OK && idxNum==FTS3_DOCID_SEARCH ){
113866114838
rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
113867114839
}
113868114840
pCsr->eSearch = (i16)idxNum;
113869114841
114842
+ assert( pCsr->desc==0 );
113870114843
if( rc!=SQLITE_OK ) return rc;
114844
+ if( rc==SQLITE_OK && pCsr->nDoclist>0 && idxStr && idxStr[0]=='D' ){
114845
+ sqlite3_int64 iDocid = 0;
114846
+ char *csr = pCsr->aDoclist;
114847
+ while( csr<&pCsr->aDoclist[pCsr->nDoclist] ){
114848
+ fts3GetDeltaVarint(&csr, &iDocid);
114849
+ }
114850
+ pCsr->pNextId = csr;
114851
+ pCsr->iPrevId = iDocid;
114852
+ pCsr->desc = 1;
114853
+ pCsr->isRequireSeek = 1;
114854
+ pCsr->isMatchinfoNeeded = 1;
114855
+ pCsr->eEvalmode = FTS3_EVAL_NEXT;
114856
+ return SQLITE_OK;
114857
+ }
113871114858
return fts3NextMethod(pCursor);
113872114859
}
113873114860
113874114861
/*
113875114862
** This is the xEof method of the virtual table. SQLite calls this
@@ -114017,17 +115004,37 @@
114017115004
pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
114018115005
rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
114019115006
pCsr->eEvalmode = FTS3_EVAL_NEXT;
114020115007
return rc;
114021115008
}
115009
+
115010
+
115011
+/*
115012
+** When called, *ppPoslist must point to the byte immediately following the
115013
+** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
115014
+** moves *ppPoslist so that it instead points to the first byte of the
115015
+** same position list.
115016
+*/
115017
+static void fts3ReversePoslist(char *pStart, char **ppPoslist){
115018
+ char *p = &(*ppPoslist)[-3];
115019
+ char c = p[1];
115020
+ while( p>pStart && (*p & 0x80) | c ){
115021
+ c = *p--;
115022
+ }
115023
+ if( p>pStart ){ p = &p[2]; }
115024
+ while( *p++&0x80 );
115025
+ *ppPoslist = p;
115026
+}
115027
+
114022115028
114023115029
/*
114024115030
** After ExprLoadDoclist() (see above) has been called, this function is
114025115031
** used to iterate/search through the position lists that make up the doclist
114026115032
** stored in pExpr->aDoclist.
114027115033
*/
114028115034
SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
115035
+ Fts3Cursor *pCursor, /* Associate FTS3 cursor */
114029115036
Fts3Expr *pExpr, /* Access this expressions doclist */
114030115037
sqlite3_int64 iDocid, /* Docid associated with requested pos-list */
114031115038
int iCol /* Column of requested pos-list */
114032115039
){
114033115040
assert( pExpr->isLoaded );
@@ -114034,23 +115041,39 @@
114034115041
if( pExpr->aDoclist ){
114035115042
char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
114036115043
char *pCsr;
114037115044
114038115045
if( pExpr->pCurrent==0 ){
114039
- pExpr->pCurrent = pExpr->aDoclist;
114040
- pExpr->iCurrent = 0;
114041
- pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent);
115046
+ if( pCursor->desc==0 ){
115047
+ pExpr->pCurrent = pExpr->aDoclist;
115048
+ pExpr->iCurrent = 0;
115049
+ fts3GetDeltaVarint(&pExpr->pCurrent, &pExpr->iCurrent);
115050
+ }else{
115051
+ pCsr = pExpr->aDoclist;
115052
+ while( pCsr<pEnd ){
115053
+ fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
115054
+ fts3PoslistCopy(0, &pCsr);
115055
+ }
115056
+ fts3ReversePoslist(pExpr->aDoclist, &pCsr);
115057
+ pExpr->pCurrent = pCsr;
115058
+ }
114042115059
}
114043115060
pCsr = pExpr->pCurrent;
114044115061
assert( pCsr );
114045115062
114046
- while( pCsr<pEnd ){
114047
- if( pExpr->iCurrent<iDocid ){
115063
+ while( (pCursor->desc==0 && pCsr<pEnd)
115064
+ || (pCursor->desc && pCsr>pExpr->aDoclist)
115065
+ ){
115066
+ if( pCursor->desc==0 && pExpr->iCurrent<iDocid ){
114048115067
fts3PoslistCopy(0, &pCsr);
114049115068
if( pCsr<pEnd ){
114050115069
fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
114051115070
}
115071
+ pExpr->pCurrent = pCsr;
115072
+ }else if( pCursor->desc && pExpr->iCurrent>iDocid ){
115073
+ fts3GetReverseDeltaVarint(&pCsr, pExpr->aDoclist, &pExpr->iCurrent);
115074
+ fts3ReversePoslist(pExpr->aDoclist, &pCsr);
114052115075
pExpr->pCurrent = pCsr;
114053115076
}else{
114054115077
if( pExpr->iCurrent==iDocid ){
114055115078
int iThis = 0;
114056115079
if( iCol<0 ){
@@ -114303,13 +115326,24 @@
114303115326
"ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';",
114304115327
p->zDb, p->zName, zName
114305115328
);
114306115329
return rc;
114307115330
}
115331
+
115332
+static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
115333
+ return sqlite3Fts3PendingTermsFlush((Fts3Table *)pVtab);
115334
+}
115335
+static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
115336
+ return SQLITE_OK;
115337
+}
115338
+static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
115339
+ sqlite3Fts3PendingTermsClear((Fts3Table *)pVtab);
115340
+ return SQLITE_OK;
115341
+}
114308115342
114309115343
static const sqlite3_module fts3Module = {
114310
- /* iVersion */ 0,
115344
+ /* iVersion */ 2,
114311115345
/* xCreate */ fts3CreateMethod,
114312115346
/* xConnect */ fts3ConnectMethod,
114313115347
/* xBestIndex */ fts3BestIndexMethod,
114314115348
/* xDisconnect */ fts3DisconnectMethod,
114315115349
/* xDestroy */ fts3DestroyMethod,
@@ -114325,10 +115359,13 @@
114325115359
/* xSync */ fts3SyncMethod,
114326115360
/* xCommit */ fts3CommitMethod,
114327115361
/* xRollback */ fts3RollbackMethod,
114328115362
/* xFindFunction */ fts3FindFunctionMethod,
114329115363
/* xRename */ fts3RenameMethod,
115364
+ /* xSavepoint */ fts3SavepointMethod,
115365
+ /* xRelease */ fts3ReleaseMethod,
115366
+ /* xRollbackTo */ fts3RollbackToMethod,
114330115367
};
114331115368
114332115369
/*
114333115370
** This function is registered as the module destructor (called when an
114334115371
** FTS3 enabled database connection is closed). It frees the memory
@@ -114370,10 +115407,15 @@
114370115407
114371115408
#ifdef SQLITE_ENABLE_ICU
114372115409
const sqlite3_tokenizer_module *pIcu = 0;
114373115410
sqlite3Fts3IcuTokenizerModule(&pIcu);
114374115411
#endif
115412
+
115413
+#ifdef SQLITE_TEST
115414
+ rc = sqlite3Fts3InitTerm(db);
115415
+ if( rc!=SQLITE_OK ) return rc;
115416
+#endif
114375115417
114376115418
rc = sqlite3Fts3InitAux(db);
114377115419
if( rc!=SQLITE_OK ) return rc;
114378115420
114379115421
sqlite3Fts3SimpleTokenizerModule(&pSimple);
@@ -117891,11 +118933,11 @@
117891118933
sqlite3_bind_int64(pStmt, 1, iDocid);
117892118934
}
117893118935
rc = sqlite3_step(pStmt);
117894118936
if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
117895118937
rc = sqlite3_reset(pStmt);
117896
- if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT;
118938
+ if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT_VTAB;
117897118939
pStmt = 0;
117898118940
}else{
117899118941
rc = SQLITE_OK;
117900118942
}
117901118943
}
@@ -118141,10 +119183,18 @@
118141119183
sqlite3_tokenizer_cursor *pCsr;
118142119184
int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
118143119185
const char**,int*,int*,int*,int*);
118144119186
118145119187
assert( pTokenizer && pModule );
119188
+
119189
+ /* If the user has inserted a NULL value, this function may be called with
119190
+ ** zText==0. In this case, add zero token entries to the hash table and
119191
+ ** return early. */
119192
+ if( zText==0 ){
119193
+ *pnWord = 0;
119194
+ return SQLITE_OK;
119195
+ }
118146119196
118147119197
rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr);
118148119198
if( rc!=SQLITE_OK ){
118149119199
return rc;
118150119200
}
@@ -118232,15 +119282,13 @@
118232119282
*/
118233119283
static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
118234119284
int i; /* Iterator variable */
118235119285
for(i=2; i<p->nColumn+2; i++){
118236119286
const char *zText = (const char *)sqlite3_value_text(apVal[i]);
118237
- if( zText ){
118238
- int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
118239
- if( rc!=SQLITE_OK ){
118240
- return rc;
118241
- }
119287
+ int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
119288
+ if( rc!=SQLITE_OK ){
119289
+ return rc;
118242119290
}
118243119291
aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
118244119292
}
118245119293
return SQLITE_OK;
118246119294
}
@@ -118341,18 +119389,18 @@
118341119389
** full-text index.
118342119390
*/
118343119391
static void fts3DeleteTerms(
118344119392
int *pRC, /* Result code */
118345119393
Fts3Table *p, /* The FTS table to delete from */
118346
- sqlite3_value **apVal, /* apVal[] contains the docid to be deleted */
119394
+ sqlite3_value *pRowid, /* The docid to be deleted */
118347119395
u32 *aSz /* Sizes of deleted document written here */
118348119396
){
118349119397
int rc;
118350119398
sqlite3_stmt *pSelect;
118351119399
118352119400
if( *pRC ) return;
118353
- rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal);
119401
+ rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
118354119402
if( rc==SQLITE_OK ){
118355119403
if( SQLITE_ROW==sqlite3_step(pSelect) ){
118356119404
int i;
118357119405
for(i=1; i<=p->nColumn; i++){
118358119406
const char *zText = (const char *)sqlite3_column_text(pSelect, i);
@@ -118566,11 +119614,11 @@
118566119614
pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
118567119615
pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
118568119616
if( nPrefix<0 || nSuffix<=0
118569119617
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
118570119618
){
118571
- return SQLITE_CORRUPT;
119619
+ return SQLITE_CORRUPT_VTAB;
118572119620
}
118573119621
118574119622
if( nPrefix+nSuffix>pReader->nTermAlloc ){
118575119623
int nNew = (nPrefix+nSuffix)*2;
118576119624
char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
@@ -118592,11 +119640,11 @@
118592119640
** of these statements is untrue, then the data structure is corrupt.
118593119641
*/
118594119642
if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
118595119643
|| pReader->aDoclist[pReader->nDoclist-1]
118596119644
){
118597
- return SQLITE_CORRUPT;
119645
+ return SQLITE_CORRUPT_VTAB;
118598119646
}
118599119647
return SQLITE_OK;
118600119648
}
118601119649
118602119650
/*
@@ -118717,11 +119765,11 @@
118717119765
while( a<pEnd ){
118718119766
a += sqlite3Fts3GetVarint(a, &nByte);
118719119767
}
118720119768
if( nDoc==0 || nByte==0 ){
118721119769
sqlite3_reset(pStmt);
118722
- return SQLITE_CORRUPT;
119770
+ return SQLITE_CORRUPT_VTAB;
118723119771
}
118724119772
118725119773
pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
118726119774
assert( pCsr->nRowAvg>0 );
118727119775
rc = sqlite3_reset(pStmt);
@@ -119488,20 +120536,20 @@
119488120536
119489120537
/*
119490120538
** The first value in the apVal[] array is assumed to contain an integer.
119491120539
** This function tests if there exist any documents with docid values that
119492120540
** are different from that integer. i.e. if deleting the document with docid
119493
-** apVal[0] would mean the FTS3 table were empty.
120541
+** pRowid would mean the FTS3 table were empty.
119494120542
**
119495120543
** If successful, *pisEmpty is set to true if the table is empty except for
119496
-** document apVal[0], or false otherwise, and SQLITE_OK is returned. If an
120544
+** document pRowid, or false otherwise, and SQLITE_OK is returned. If an
119497120545
** error occurs, an SQLite error code is returned.
119498120546
*/
119499
-static int fts3IsEmpty(Fts3Table *p, sqlite3_value **apVal, int *pisEmpty){
120547
+static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){
119500120548
sqlite3_stmt *pStmt;
119501120549
int rc;
119502
- rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, apVal);
120550
+ rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid);
119503120551
if( rc==SQLITE_OK ){
119504120552
if( SQLITE_ROW==sqlite3_step(pStmt) ){
119505120553
*pisEmpty = sqlite3_column_int(pStmt, 0);
119506120554
}
119507120555
rc = sqlite3_reset(pStmt);
@@ -120221,10 +121269,44 @@
120221121269
pToken->pDeferred = pDeferred;
120222121270
120223121271
return SQLITE_OK;
120224121272
}
120225121273
121274
+/*
121275
+** SQLite value pRowid contains the rowid of a row that may or may not be
121276
+** present in the FTS3 table. If it is, delete it and adjust the contents
121277
+** of subsiduary data structures accordingly.
121278
+*/
121279
+static int fts3DeleteByRowid(
121280
+ Fts3Table *p,
121281
+ sqlite3_value *pRowid,
121282
+ int *pnDoc,
121283
+ u32 *aSzDel
121284
+){
121285
+ int isEmpty = 0;
121286
+ int rc = fts3IsEmpty(p, pRowid, &isEmpty);
121287
+ if( rc==SQLITE_OK ){
121288
+ if( isEmpty ){
121289
+ /* Deleting this row means the whole table is empty. In this case
121290
+ ** delete the contents of all three tables and throw away any
121291
+ ** data in the pendingTerms hash table. */
121292
+ rc = fts3DeleteAll(p);
121293
+ *pnDoc = *pnDoc - 1;
121294
+ }else{
121295
+ sqlite3_int64 iRemove = sqlite3_value_int64(pRowid);
121296
+ rc = fts3PendingTermsDocid(p, iRemove);
121297
+ fts3DeleteTerms(&rc, p, pRowid, aSzDel);
121298
+ fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
121299
+ if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
121300
+ if( p->bHasDocsize ){
121301
+ fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
121302
+ }
121303
+ }
121304
+ }
121305
+
121306
+ return rc;
121307
+}
120226121308
120227121309
/*
120228121310
** This function does the work for the xUpdate method of FTS3 virtual
120229121311
** tables.
120230121312
*/
@@ -120239,50 +121321,95 @@
120239121321
int isRemove = 0; /* True for an UPDATE or DELETE */
120240121322
sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
120241121323
u32 *aSzIns; /* Sizes of inserted documents */
120242121324
u32 *aSzDel; /* Sizes of deleted documents */
120243121325
int nChng = 0; /* Net change in number of documents */
121326
+ int bInsertDone = 0;
120244121327
120245121328
assert( p->pSegments==0 );
121329
+
121330
+ /* Check for a "special" INSERT operation. One of the form:
121331
+ **
121332
+ ** INSERT INTO xyz(xyz) VALUES('command');
121333
+ */
121334
+ if( nArg>1
121335
+ && sqlite3_value_type(apVal[0])==SQLITE_NULL
121336
+ && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
121337
+ ){
121338
+ return fts3SpecialInsert(p, apVal[p->nColumn+2]);
121339
+ }
120246121340
120247121341
/* Allocate space to hold the change in document sizes */
120248121342
aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
120249121343
if( aSzIns==0 ) return SQLITE_NOMEM;
120250121344
aSzDel = &aSzIns[p->nColumn+1];
120251121345
memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
121346
+
121347
+ /* If this is an INSERT operation, or an UPDATE that modifies the rowid
121348
+ ** value, then this operation requires constraint handling.
121349
+ **
121350
+ ** If the on-conflict mode is REPLACE, this means that the existing row
121351
+ ** should be deleted from the database before inserting the new row. Or,
121352
+ ** if the on-conflict mode is other than REPLACE, then this method must
121353
+ ** detect the conflict and return SQLITE_CONSTRAINT before beginning to
121354
+ ** modify the database file.
121355
+ */
121356
+ if( nArg>1 ){
121357
+ /* Find the value object that holds the new rowid value. */
121358
+ sqlite3_value *pNewRowid = apVal[3+p->nColumn];
121359
+ if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){
121360
+ pNewRowid = apVal[1];
121361
+ }
121362
+
121363
+ if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
121364
+ sqlite3_value_type(apVal[0])==SQLITE_NULL
121365
+ || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid)
121366
+ )){
121367
+ /* The new rowid is not NULL (in this case the rowid will be
121368
+ ** automatically assigned and there is no chance of a conflict), and
121369
+ ** the statement is either an INSERT or an UPDATE that modifies the
121370
+ ** rowid column. So if the conflict mode is REPLACE, then delete any
121371
+ ** existing row with rowid=pNewRowid.
121372
+ **
121373
+ ** Or, if the conflict mode is not REPLACE, insert the new record into
121374
+ ** the %_content table. If we hit the duplicate rowid constraint (or any
121375
+ ** other error) while doing so, return immediately.
121376
+ **
121377
+ ** This branch may also run if pNewRowid contains a value that cannot
121378
+ ** be losslessly converted to an integer. In this case, the eventual
121379
+ ** call to fts3InsertData() (either just below or further on in this
121380
+ ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
121381
+ ** invoked, it will delete zero rows (since no row will have
121382
+ ** docid=$pNewRowid if $pNewRowid is not an integer value).
121383
+ */
121384
+ if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){
121385
+ rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel);
121386
+ }else{
121387
+ rc = fts3InsertData(p, apVal, pRowid);
121388
+ bInsertDone = 1;
121389
+ }
121390
+ }
121391
+ }
121392
+ if( rc!=SQLITE_OK ){
121393
+ sqlite3_free(aSzIns);
121394
+ return rc;
121395
+ }
120252121396
120253121397
/* If this is a DELETE or UPDATE operation, remove the old record. */
120254121398
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
120255
- int isEmpty = 0;
120256
- rc = fts3IsEmpty(p, apVal, &isEmpty);
120257
- if( rc==SQLITE_OK ){
120258
- if( isEmpty ){
120259
- /* Deleting this row means the whole table is empty. In this case
120260
- ** delete the contents of all three tables and throw away any
120261
- ** data in the pendingTerms hash table.
120262
- */
120263
- rc = fts3DeleteAll(p);
120264
- }else{
120265
- isRemove = 1;
120266
- iRemove = sqlite3_value_int64(apVal[0]);
120267
- rc = fts3PendingTermsDocid(p, iRemove);
120268
- fts3DeleteTerms(&rc, p, apVal, aSzDel);
120269
- fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal);
120270
- if( p->bHasDocsize ){
120271
- fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal);
120272
- }
120273
- nChng--;
120274
- }
120275
- }
120276
- }else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){
120277
- sqlite3_free(aSzIns);
120278
- return fts3SpecialInsert(p, apVal[p->nColumn+2]);
121399
+ assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
121400
+ rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
121401
+ isRemove = 1;
121402
+ iRemove = sqlite3_value_int64(apVal[0]);
120279121403
}
120280121404
120281121405
/* If this is an INSERT or UPDATE operation, insert the new record. */
120282121406
if( nArg>1 && rc==SQLITE_OK ){
120283
- rc = fts3InsertData(p, apVal, pRowid);
121407
+ if( bInsertDone==0 ){
121408
+ rc = fts3InsertData(p, apVal, pRowid);
121409
+ if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT_VTAB;
121410
+ }
120284121411
if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
120285121412
rc = fts3PendingTermsDocid(p, *pRowid);
120286121413
}
120287121414
if( rc==SQLITE_OK ){
120288121415
rc = fts3InsertTerms(p, apVal, aSzIns);
@@ -120742,11 +121869,11 @@
120742121869
SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
120743121870
char *pCsr;
120744121871
120745121872
pPhrase->nToken = pExpr->pPhrase->nToken;
120746121873
120747
- pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol);
121874
+ pCsr = sqlite3Fts3FindPositions(p->pCsr, pExpr, p->pCsr->iPrevId, p->iCol);
120748121875
if( pCsr ){
120749121876
int iFirst = 0;
120750121877
pPhrase->pList = pCsr;
120751121878
fts3GetDeltaPosition(&pCsr, &iFirst);
120752121879
pPhrase->pHead = pCsr;
@@ -121215,11 +122342,11 @@
121215122342
for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0;
121216122343
121217122344
if( pExpr->aDoclist ){
121218122345
char *pCsr;
121219122346
121220
- pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1);
122347
+ pCsr = sqlite3Fts3FindPositions(p->pCursor, pExpr, p->pCursor->iPrevId, -1);
121221122348
if( pCsr ){
121222122349
fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0);
121223122350
}
121224122351
}
121225122352
@@ -121287,11 +122414,11 @@
121287122414
pStmt = *ppStmt;
121288122415
assert( sqlite3_data_count(pStmt)==1 );
121289122416
121290122417
a = sqlite3_column_blob(pStmt, 0);
121291122418
a += sqlite3Fts3GetVarint(a, &nDoc);
121292
- if( nDoc==0 ) return SQLITE_CORRUPT;
122419
+ if( nDoc==0 ) return SQLITE_CORRUPT_VTAB;
121293122420
*pnDoc = (u32)nDoc;
121294122421
121295122422
if( paLen ) *paLen = a;
121296122423
return SQLITE_OK;
121297122424
}
@@ -121382,11 +122509,11 @@
121382122509
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
121383122510
for(i=0; i<pInfo->nPhrase; i++){
121384122511
LcsIterator *pIter = &aIter[i];
121385122512
nToken -= pIter->pExpr->pPhrase->nToken;
121386122513
pIter->iPosOffset = nToken;
121387
- pIter->pRead = sqlite3Fts3FindPositions(pIter->pExpr, pCsr->iPrevId, -1);
122514
+ pIter->pRead = sqlite3Fts3FindPositions(pCsr,pIter->pExpr,pCsr->iPrevId,-1);
121388122515
if( pIter->pRead ){
121389122516
pIter->iPos = pIter->iPosOffset;
121390122517
fts3LcsIteratorAdvance(&aIter[i]);
121391122518
}else{
121392122519
pIter->iCol = LCS_ITERATOR_FINISHED;
@@ -121735,10 +122862,11 @@
121735122862
int iPos; /* Position just read from pList */
121736122863
int iOff; /* Offset of this term from read positions */
121737122864
};
121738122865
121739122866
struct TermOffsetCtx {
122867
+ Fts3Cursor *pCsr;
121740122868
int iCol; /* Column of table to populate aTerm for */
121741122869
int iTerm;
121742122870
sqlite3_int64 iDocid;
121743122871
TermOffset *aTerm;
121744122872
};
@@ -121752,11 +122880,11 @@
121752122880
int iTerm; /* For looping through nTerm phrase terms */
121753122881
char *pList; /* Pointer to position list for phrase */
121754122882
int iPos = 0; /* First position in position-list */
121755122883
121756122884
UNUSED_PARAMETER(iPhrase);
121757
- pList = sqlite3Fts3FindPositions(pExpr, p->iDocid, p->iCol);
122885
+ pList = sqlite3Fts3FindPositions(p->pCsr, pExpr, p->iDocid, p->iCol);
121758122886
nTerm = pExpr->pPhrase->nToken;
121759122887
if( pList ){
121760122888
fts3GetDeltaPosition(&pList, &iPos);
121761122889
assert( iPos>=0 );
121762122890
}
@@ -121805,10 +122933,11 @@
121805122933
if( 0==sCtx.aTerm ){
121806122934
rc = SQLITE_NOMEM;
121807122935
goto offsets_out;
121808122936
}
121809122937
sCtx.iDocid = pCsr->iPrevId;
122938
+ sCtx.pCsr = pCsr;
121810122939
121811122940
/* Loop through the table columns, appending offset information to
121812122941
** string-buffer res for each column.
121813122942
*/
121814122943
for(iCol=0; iCol<pTab->nColumn; iCol++){
@@ -121880,11 +123009,11 @@
121880123009
sqlite3_snprintf(sizeof(aBuffer), aBuffer,
121881123010
"%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
121882123011
);
121883123012
rc = fts3StringAppend(&res, aBuffer, -1);
121884123013
}else if( rc==SQLITE_DONE ){
121885
- rc = SQLITE_CORRUPT;
123014
+ rc = SQLITE_CORRUPT_VTAB;
121886123015
}
121887123016
}
121888123017
}
121889123018
if( rc==SQLITE_DONE ){
121890123019
rc = SQLITE_OK;
@@ -122468,29 +123597,29 @@
122468123597
** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
122469123598
*/
122470123599
if( pNode && iNode==1 ){
122471123600
pRtree->iDepth = readInt16(pNode->zData);
122472123601
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
122473
- rc = SQLITE_CORRUPT;
123602
+ rc = SQLITE_CORRUPT_VTAB;
122474123603
}
122475123604
}
122476123605
122477123606
/* If no error has occurred so far, check if the "number of entries"
122478123607
** field on the node is too large. If so, set the return code to
122479
- ** SQLITE_CORRUPT.
123608
+ ** SQLITE_CORRUPT_VTAB.
122480123609
*/
122481123610
if( pNode && rc==SQLITE_OK ){
122482123611
if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
122483
- rc = SQLITE_CORRUPT;
123612
+ rc = SQLITE_CORRUPT_VTAB;
122484123613
}
122485123614
}
122486123615
122487123616
if( rc==SQLITE_OK ){
122488123617
if( pNode!=0 ){
122489123618
nodeHashInsert(pRtree, pNode);
122490123619
}else{
122491
- rc = SQLITE_CORRUPT;
123620
+ rc = SQLITE_CORRUPT_VTAB;
122492123621
}
122493123622
*ppNode = pNode;
122494123623
}else{
122495123624
sqlite3_free(pNode);
122496123625
*ppNode = 0;
@@ -123013,11 +124142,11 @@
123013124142
if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
123014124143
*piIndex = ii;
123015124144
return SQLITE_OK;
123016124145
}
123017124146
}
123018
- return SQLITE_CORRUPT;
124147
+ return SQLITE_CORRUPT_VTAB;
123019124148
}
123020124149
123021124150
/*
123022124151
** Return the index of the cell containing a pointer to node pNode
123023124152
** in its parent. If pNode is the root node, return -1.
@@ -123608,11 +124737,11 @@
123608124737
RtreeNode *pParent = p->pParent;
123609124738
RtreeCell cell;
123610124739
int iCell;
123611124740
123612124741
if( nodeParentIndex(pRtree, p, &iCell) ){
123613
- return SQLITE_CORRUPT;
124742
+ return SQLITE_CORRUPT_VTAB;
123614124743
}
123615124744
123616124745
nodeGetCell(pRtree, pParent, iCell, &cell);
123617124746
if( !cellContains(pRtree, &cell, pCell) ){
123618124747
cellUnion(pRtree, &cell, pCell);
@@ -124280,11 +125409,11 @@
124280125409
rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
124281125410
}
124282125411
}
124283125412
rc = sqlite3_reset(pRtree->pReadParent);
124284125413
if( rc==SQLITE_OK ) rc = rc2;
124285
- if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT;
125414
+ if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
124286125415
pChild = pChild->pParent;
124287125416
}
124288125417
return rc;
124289125418
}
124290125419
@@ -124575,10 +125704,94 @@
124575125704
sqlite3_step(pRtree->pWriteRowid);
124576125705
rc = sqlite3_reset(pRtree->pWriteRowid);
124577125706
*piRowid = sqlite3_last_insert_rowid(pRtree->db);
124578125707
return rc;
124579125708
}
125709
+
125710
+/*
125711
+** Remove the entry with rowid=iDelete from the r-tree structure.
125712
+*/
125713
+static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
125714
+ int rc; /* Return code */
125715
+ RtreeNode *pLeaf; /* Leaf node containing record iDelete */
125716
+ int iCell; /* Index of iDelete cell in pLeaf */
125717
+ RtreeNode *pRoot; /* Root node of rtree structure */
125718
+
125719
+
125720
+ /* Obtain a reference to the root node to initialise Rtree.iDepth */
125721
+ rc = nodeAcquire(pRtree, 1, 0, &pRoot);
125722
+
125723
+ /* Obtain a reference to the leaf node that contains the entry
125724
+ ** about to be deleted.
125725
+ */
125726
+ if( rc==SQLITE_OK ){
125727
+ rc = findLeafNode(pRtree, iDelete, &pLeaf);
125728
+ }
125729
+
125730
+ /* Delete the cell in question from the leaf node. */
125731
+ if( rc==SQLITE_OK ){
125732
+ int rc2;
125733
+ rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
125734
+ if( rc==SQLITE_OK ){
125735
+ rc = deleteCell(pRtree, pLeaf, iCell, 0);
125736
+ }
125737
+ rc2 = nodeRelease(pRtree, pLeaf);
125738
+ if( rc==SQLITE_OK ){
125739
+ rc = rc2;
125740
+ }
125741
+ }
125742
+
125743
+ /* Delete the corresponding entry in the <rtree>_rowid table. */
125744
+ if( rc==SQLITE_OK ){
125745
+ sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
125746
+ sqlite3_step(pRtree->pDeleteRowid);
125747
+ rc = sqlite3_reset(pRtree->pDeleteRowid);
125748
+ }
125749
+
125750
+ /* Check if the root node now has exactly one child. If so, remove
125751
+ ** it, schedule the contents of the child for reinsertion and
125752
+ ** reduce the tree height by one.
125753
+ **
125754
+ ** This is equivalent to copying the contents of the child into
125755
+ ** the root node (the operation that Gutman's paper says to perform
125756
+ ** in this scenario).
125757
+ */
125758
+ if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
125759
+ int rc2;
125760
+ RtreeNode *pChild;
125761
+ i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
125762
+ rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
125763
+ if( rc==SQLITE_OK ){
125764
+ rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
125765
+ }
125766
+ rc2 = nodeRelease(pRtree, pChild);
125767
+ if( rc==SQLITE_OK ) rc = rc2;
125768
+ if( rc==SQLITE_OK ){
125769
+ pRtree->iDepth--;
125770
+ writeInt16(pRoot->zData, pRtree->iDepth);
125771
+ pRoot->isDirty = 1;
125772
+ }
125773
+ }
125774
+
125775
+ /* Re-insert the contents of any underfull nodes removed from the tree. */
125776
+ for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
125777
+ if( rc==SQLITE_OK ){
125778
+ rc = reinsertNodeContent(pRtree, pLeaf);
125779
+ }
125780
+ pRtree->pDeleted = pLeaf->pNext;
125781
+ sqlite3_free(pLeaf);
125782
+ }
125783
+
125784
+ /* Release the reference to the root node. */
125785
+ if( rc==SQLITE_OK ){
125786
+ rc = nodeRelease(pRtree, pRoot);
125787
+ }else{
125788
+ nodeRelease(pRtree, pRoot);
125789
+ }
125790
+
125791
+ return rc;
125792
+}
124580125793
124581125794
/*
124582125795
** The xUpdate method for rtree module virtual tables.
124583125796
*/
124584125797
static int rtreeUpdate(
@@ -124587,107 +125800,29 @@
124587125800
sqlite3_value **azData,
124588125801
sqlite_int64 *pRowid
124589125802
){
124590125803
Rtree *pRtree = (Rtree *)pVtab;
124591125804
int rc = SQLITE_OK;
125805
+ RtreeCell cell; /* New cell to insert if nData>1 */
125806
+ int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
124592125807
124593125808
rtreeReference(pRtree);
124594
-
124595125809
assert(nData>=1);
124596125810
124597
- /* If azData[0] is not an SQL NULL value, it is the rowid of a
124598
- ** record to delete from the r-tree table. The following block does
124599
- ** just that.
124600
- */
124601
- if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
124602
- i64 iDelete; /* The rowid to delete */
124603
- RtreeNode *pLeaf; /* Leaf node containing record iDelete */
124604
- int iCell; /* Index of iDelete cell in pLeaf */
124605
- RtreeNode *pRoot;
124606
-
124607
- /* Obtain a reference to the root node to initialise Rtree.iDepth */
124608
- rc = nodeAcquire(pRtree, 1, 0, &pRoot);
124609
-
124610
- /* Obtain a reference to the leaf node that contains the entry
124611
- ** about to be deleted.
124612
- */
124613
- if( rc==SQLITE_OK ){
124614
- iDelete = sqlite3_value_int64(azData[0]);
124615
- rc = findLeafNode(pRtree, iDelete, &pLeaf);
124616
- }
124617
-
124618
- /* Delete the cell in question from the leaf node. */
124619
- if( rc==SQLITE_OK ){
124620
- int rc2;
124621
- rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
124622
- if( rc==SQLITE_OK ){
124623
- rc = deleteCell(pRtree, pLeaf, iCell, 0);
124624
- }
124625
- rc2 = nodeRelease(pRtree, pLeaf);
124626
- if( rc==SQLITE_OK ){
124627
- rc = rc2;
124628
- }
124629
- }
124630
-
124631
- /* Delete the corresponding entry in the <rtree>_rowid table. */
124632
- if( rc==SQLITE_OK ){
124633
- sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
124634
- sqlite3_step(pRtree->pDeleteRowid);
124635
- rc = sqlite3_reset(pRtree->pDeleteRowid);
124636
- }
124637
-
124638
- /* Check if the root node now has exactly one child. If so, remove
124639
- ** it, schedule the contents of the child for reinsertion and
124640
- ** reduce the tree height by one.
124641
- **
124642
- ** This is equivalent to copying the contents of the child into
124643
- ** the root node (the operation that Gutman's paper says to perform
124644
- ** in this scenario).
124645
- */
124646
- if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
124647
- int rc2;
124648
- RtreeNode *pChild;
124649
- i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
124650
- rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
124651
- if( rc==SQLITE_OK ){
124652
- rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
124653
- }
124654
- rc2 = nodeRelease(pRtree, pChild);
124655
- if( rc==SQLITE_OK ) rc = rc2;
124656
- if( rc==SQLITE_OK ){
124657
- pRtree->iDepth--;
124658
- writeInt16(pRoot->zData, pRtree->iDepth);
124659
- pRoot->isDirty = 1;
124660
- }
124661
- }
124662
-
124663
- /* Re-insert the contents of any underfull nodes removed from the tree. */
124664
- for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
124665
- if( rc==SQLITE_OK ){
124666
- rc = reinsertNodeContent(pRtree, pLeaf);
124667
- }
124668
- pRtree->pDeleted = pLeaf->pNext;
124669
- sqlite3_free(pLeaf);
124670
- }
124671
-
124672
- /* Release the reference to the root node. */
124673
- if( rc==SQLITE_OK ){
124674
- rc = nodeRelease(pRtree, pRoot);
124675
- }else{
124676
- nodeRelease(pRtree, pRoot);
124677
- }
124678
- }
124679
-
124680
- /* If the azData[] array contains more than one element, elements
124681
- ** (azData[2]..azData[argc-1]) contain a new record to insert into
124682
- ** the r-tree structure.
124683
- */
124684
- if( rc==SQLITE_OK && nData>1 ){
124685
- /* Insert a new record into the r-tree */
124686
- RtreeCell cell;
124687
- int ii;
124688
- RtreeNode *pLeaf;
125811
+ /* Constraint handling. A write operation on an r-tree table may return
125812
+ ** SQLITE_CONSTRAINT for two reasons:
125813
+ **
125814
+ ** 1. A duplicate rowid value, or
125815
+ ** 2. The supplied data violates the "x2>=x1" constraint.
125816
+ **
125817
+ ** In the first case, if the conflict-handling mode is REPLACE, then
125818
+ ** the conflicting row can be removed before proceeding. In the second
125819
+ ** case, SQLITE_CONSTRAINT must be returned regardless of the
125820
+ ** conflict-handling mode specified by the user.
125821
+ */
125822
+ if( nData>1 ){
125823
+ int ii;
124689125824
124690125825
/* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
124691125826
assert( nData==(pRtree->nDim*2 + 3) );
124692125827
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
124693125828
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
@@ -124707,22 +125842,53 @@
124707125842
goto constraint;
124708125843
}
124709125844
}
124710125845
}
124711125846
124712
- /* Figure out the rowid of the new row. */
124713
- if( sqlite3_value_type(azData[2])==SQLITE_NULL ){
124714
- rc = newRowid(pRtree, &cell.iRowid);
124715
- }else{
125847
+ /* If a rowid value was supplied, check if it is already present in
125848
+ ** the table. If so, the constraint has failed. */
125849
+ if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){
124716125850
cell.iRowid = sqlite3_value_int64(azData[2]);
124717
- sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
124718
- if( SQLITE_ROW==sqlite3_step(pRtree->pReadRowid) ){
124719
- sqlite3_reset(pRtree->pReadRowid);
124720
- rc = SQLITE_CONSTRAINT;
124721
- goto constraint;
125851
+ if( sqlite3_value_type(azData[0])==SQLITE_NULL
125852
+ || sqlite3_value_int64(azData[0])!=cell.iRowid
125853
+ ){
125854
+ int steprc;
125855
+ sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
125856
+ steprc = sqlite3_step(pRtree->pReadRowid);
125857
+ rc = sqlite3_reset(pRtree->pReadRowid);
125858
+ if( SQLITE_ROW==steprc ){
125859
+ if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){
125860
+ rc = rtreeDeleteRowid(pRtree, cell.iRowid);
125861
+ }else{
125862
+ rc = SQLITE_CONSTRAINT;
125863
+ goto constraint;
125864
+ }
125865
+ }
124722125866
}
124723
- rc = sqlite3_reset(pRtree->pReadRowid);
125867
+ bHaveRowid = 1;
125868
+ }
125869
+ }
125870
+
125871
+ /* If azData[0] is not an SQL NULL value, it is the rowid of a
125872
+ ** record to delete from the r-tree table. The following block does
125873
+ ** just that.
125874
+ */
125875
+ if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
125876
+ rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0]));
125877
+ }
125878
+
125879
+ /* If the azData[] array contains more than one element, elements
125880
+ ** (azData[2]..azData[argc-1]) contain a new record to insert into
125881
+ ** the r-tree structure.
125882
+ */
125883
+ if( rc==SQLITE_OK && nData>1 ){
125884
+ /* Insert the new record into the r-tree */
125885
+ RtreeNode *pLeaf;
125886
+
125887
+ /* Figure out the rowid of the new row. */
125888
+ if( bHaveRowid==0 ){
125889
+ rc = newRowid(pRtree, &cell.iRowid);
124724125890
}
124725125891
*pRowid = cell.iRowid;
124726125892
124727125893
if( rc==SQLITE_OK ){
124728125894
rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf);
@@ -124958,10 +126124,12 @@
124958126124
int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
124959126125
if( aErrMsg[iErr] ){
124960126126
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
124961126127
return SQLITE_ERROR;
124962126128
}
126129
+
126130
+ sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
124963126131
124964126132
/* Allocate the sqlite3_vtab structure */
124965126133
nDb = strlen(argv[1]);
124966126134
nName = strlen(argv[2]);
124967126135
pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
124968126136
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.7.6. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -648,13 +648,13 @@
648 **
649 ** See also: [sqlite3_libversion()],
650 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651 ** [sqlite_version()] and [sqlite_source_id()].
652 */
653 #define SQLITE_VERSION "3.7.6"
654 #define SQLITE_VERSION_NUMBER 3007006
655 #define SQLITE_SOURCE_ID "2011-04-12 01:58:40 f9d43fa363d54beab6f45db005abac0a7c0c47a7"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -916,11 +916,12 @@
916 ** Many SQLite functions return an integer result code from the set shown
917 ** here in order to indicates success or failure.
918 **
919 ** New error codes may be added in future versions of SQLite.
920 **
921 ** See also: [SQLITE_IOERR_READ | extended result codes]
 
922 */
923 #define SQLITE_OK 0 /* Successful result */
924 /* beginning-of-error-codes */
925 #define SQLITE_ERROR 1 /* SQL error or missing database */
926 #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -993,28 +994,31 @@
993 #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
994 #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
995 #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
996 #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
997 #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
 
 
998 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
999 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
1000 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
 
1001
1002 /*
1003 ** CAPI3REF: Flags For File Open Operations
1004 **
1005 ** These bit values are intended for use in the
1006 ** 3rd parameter to the [sqlite3_open_v2()] interface and
1007 ** in the 4th parameter to the xOpen method of the
1008 ** [sqlite3_vfs] object.
1009 */
1010 #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
1011 #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
1012 #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
1013 #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
1014 #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
1015 #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
 
1016 #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
1017 #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
1018 #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
1019 #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
1020 #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
@@ -1121,21 +1125,22 @@
1121 };
1122
1123 /*
1124 ** CAPI3REF: OS Interface File Virtual Methods Object
1125 **
1126 ** Every file opened by the [sqlite3_vfs] xOpen method populates an
1127 ** [sqlite3_file] object (or, more commonly, a subclass of the
1128 ** [sqlite3_file] object) with a pointer to an instance of this object.
1129 ** This object defines the methods used to perform various operations
1130 ** against the open file represented by the [sqlite3_file] object.
1131 **
1132 ** If the xOpen method sets the sqlite3_file.pMethods element
1133 ** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
1134 ** may be invoked even if the xOpen reported that it failed. The
1135 ** only way to prevent a call to xClose following a failed xOpen
1136 ** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
 
1137 **
1138 ** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
1139 ** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
1140 ** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
1141 ** flag may be ORed in to indicate that only the data of the file
@@ -1300,10 +1305,11 @@
1300 */
1301 typedef struct sqlite3_mutex sqlite3_mutex;
1302
1303 /*
1304 ** CAPI3REF: OS Interface Object
 
1305 **
1306 ** An instance of the sqlite3_vfs object defines the interface between
1307 ** the SQLite core and the underlying operating system. The "vfs"
1308 ** in the name of the object stands for "virtual file system".
1309 **
@@ -1332,10 +1338,11 @@
1332 ** object once the object has been registered.
1333 **
1334 ** The zName field holds the name of the VFS module. The name must
1335 ** be unique across all VFS modules.
1336 **
 
1337 ** ^SQLite guarantees that the zFilename parameter to xOpen
1338 ** is either a NULL pointer or string obtained
1339 ** from xFullPathname() with an optional suffix added.
1340 ** ^If a suffix is added to the zFilename parameter, it will
1341 ** consist of a single "-" character followed by no more than
@@ -1409,10 +1416,11 @@
1409 ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
1410 ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
1411 ** element will be valid after xOpen returns regardless of the success
1412 ** or failure of the xOpen call.
1413 **
 
1414 ** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
1415 ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
1416 ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
1417 ** to test whether a file is at least readable. The file can be a
1418 ** directory.
@@ -1655,13 +1663,13 @@
1655 ** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
1656 ** Note, however, that ^sqlite3_config() can be called as part of the
1657 ** implementation of an application-defined [sqlite3_os_init()].
1658 **
1659 ** The first argument to sqlite3_config() is an integer
1660 ** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
1661 ** what property of SQLite is to be configured. Subsequent arguments
1662 ** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
1663 ** in the first argument.
1664 **
1665 ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
1666 ** ^If the option is unknown or SQLite is unable to set the option
1667 ** then this routine returns a non-zero [error code].
@@ -1767,10 +1775,11 @@
1767 void *pAppData; /* Argument to xInit() and xShutdown() */
1768 };
1769
1770 /*
1771 ** CAPI3REF: Configuration Options
 
1772 **
1773 ** These constants are the available integer configuration options that
1774 ** can be passed as the first argument to the [sqlite3_config()] interface.
1775 **
1776 ** New configuration options may be added in future releases of SQLite.
@@ -1779,11 +1788,11 @@
1779 ** the call worked. The [sqlite3_config()] interface will return a
1780 ** non-zero [error code] if a discontinued or unsupported configuration option
1781 ** is invoked.
1782 **
1783 ** <dl>
1784 ** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
1785 ** <dd>There are no arguments to this option. ^This option sets the
1786 ** [threading mode] to Single-thread. In other words, it disables
1787 ** all mutexing and puts SQLite into a mode where it can only be used
1788 ** by a single thread. ^If SQLite is compiled with
1789 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
@@ -1790,11 +1799,11 @@
1790 ** it is not possible to change the [threading mode] from its default
1791 ** value of Single-thread and so [sqlite3_config()] will return
1792 ** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
1793 ** configuration option.</dd>
1794 **
1795 ** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
1796 ** <dd>There are no arguments to this option. ^This option sets the
1797 ** [threading mode] to Multi-thread. In other words, it disables
1798 ** mutexing on [database connection] and [prepared statement] objects.
1799 ** The application is responsible for serializing access to
1800 ** [database connections] and [prepared statements]. But other mutexes
@@ -1804,11 +1813,11 @@
1804 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1805 ** it is not possible to set the Multi-thread [threading mode] and
1806 ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
1807 ** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
1808 **
1809 ** <dt>SQLITE_CONFIG_SERIALIZED</dt>
1810 ** <dd>There are no arguments to this option. ^This option sets the
1811 ** [threading mode] to Serialized. In other words, this option enables
1812 ** all mutexes including the recursive
1813 ** mutexes on [database connection] and [prepared statement] objects.
1814 ** In this mode (which is the default when SQLite is compiled with
@@ -1820,27 +1829,27 @@
1820 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1821 ** it is not possible to set the Serialized [threading mode] and
1822 ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
1823 ** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
1824 **
1825 ** <dt>SQLITE_CONFIG_MALLOC</dt>
1826 ** <dd> ^(This option takes a single argument which is a pointer to an
1827 ** instance of the [sqlite3_mem_methods] structure. The argument specifies
1828 ** alternative low-level memory allocation routines to be used in place of
1829 ** the memory allocation routines built into SQLite.)^ ^SQLite makes
1830 ** its own private copy of the content of the [sqlite3_mem_methods] structure
1831 ** before the [sqlite3_config()] call returns.</dd>
1832 **
1833 ** <dt>SQLITE_CONFIG_GETMALLOC</dt>
1834 ** <dd> ^(This option takes a single argument which is a pointer to an
1835 ** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
1836 ** structure is filled with the currently defined memory allocation routines.)^
1837 ** This option can be used to overload the default memory allocation
1838 ** routines with a wrapper that simulations memory allocation failure or
1839 ** tracks memory usage, for example. </dd>
1840 **
1841 ** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
1842 ** <dd> ^This option takes single argument of type int, interpreted as a
1843 ** boolean, which enables or disables the collection of memory allocation
1844 ** statistics. ^(When memory allocation statistics are disabled, the
1845 ** following SQLite interfaces become non-operational:
1846 ** <ul>
@@ -1852,11 +1861,11 @@
1852 ** ^Memory allocation statistics are enabled by default unless SQLite is
1853 ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
1854 ** allocation statistics are disabled by default.
1855 ** </dd>
1856 **
1857 ** <dt>SQLITE_CONFIG_SCRATCH</dt>
1858 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1859 ** scratch memory. There are three arguments: A pointer an 8-byte
1860 ** aligned memory buffer from which the scratch allocations will be
1861 ** drawn, the size of each scratch allocation (sz),
1862 ** and the maximum number of scratch allocations (N). The sz
@@ -1868,11 +1877,11 @@
1868 ** ^SQLite will never require a scratch buffer that is more than 6
1869 ** times the database page size. ^If SQLite needs needs additional
1870 ** scratch memory beyond what is provided by this configuration option, then
1871 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
1872 **
1873 ** <dt>SQLITE_CONFIG_PAGECACHE</dt>
1874 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1875 ** the database page cache with the default page cache implemenation.
1876 ** This configuration should not be used if an application-define page
1877 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
1878 ** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1889,11 +1898,11 @@
1889 ** SQLite goes to [sqlite3_malloc()] for the additional storage space.
1890 ** The pointer in the first argument must
1891 ** be aligned to an 8-byte boundary or subsequent behavior of SQLite
1892 ** will be undefined.</dd>
1893 **
1894 ** <dt>SQLITE_CONFIG_HEAP</dt>
1895 ** <dd> ^This option specifies a static memory buffer that SQLite will use
1896 ** for all of its dynamic memory allocation needs beyond those provided
1897 ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
1898 ** There are three arguments: An 8-byte aligned pointer to the memory,
1899 ** the number of bytes in the memory buffer, and the minimum allocation size.
@@ -1906,11 +1915,11 @@
1906 ** The first pointer (the memory pointer) must be aligned to an 8-byte
1907 ** boundary or subsequent behavior of SQLite will be undefined.
1908 ** The minimum allocation size is capped at 2^12. Reasonable values
1909 ** for the minimum allocation size are 2^5 through 2^8.</dd>
1910 **
1911 ** <dt>SQLITE_CONFIG_MUTEX</dt>
1912 ** <dd> ^(This option takes a single argument which is a pointer to an
1913 ** instance of the [sqlite3_mutex_methods] structure. The argument specifies
1914 ** alternative low-level mutex routines to be used in place
1915 ** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
1916 ** content of the [sqlite3_mutex_methods] structure before the call to
@@ -1918,11 +1927,11 @@
1918 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1919 ** the entire mutexing subsystem is omitted from the build and hence calls to
1920 ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
1921 ** return [SQLITE_ERROR].</dd>
1922 **
1923 ** <dt>SQLITE_CONFIG_GETMUTEX</dt>
1924 ** <dd> ^(This option takes a single argument which is a pointer to an
1925 ** instance of the [sqlite3_mutex_methods] structure. The
1926 ** [sqlite3_mutex_methods]
1927 ** structure is filled with the currently defined mutex routines.)^
1928 ** This option can be used to overload the default mutex allocation
@@ -1931,32 +1940,32 @@
1931 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1932 ** the entire mutexing subsystem is omitted from the build and hence calls to
1933 ** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
1934 ** return [SQLITE_ERROR].</dd>
1935 **
1936 ** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
1937 ** <dd> ^(This option takes two arguments that determine the default
1938 ** memory allocation for the lookaside memory allocator on each
1939 ** [database connection]. The first argument is the
1940 ** size of each lookaside buffer slot and the second is the number of
1941 ** slots allocated to each database connection.)^ ^(This option sets the
1942 ** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
1943 ** verb to [sqlite3_db_config()] can be used to change the lookaside
1944 ** configuration on individual connections.)^ </dd>
1945 **
1946 ** <dt>SQLITE_CONFIG_PCACHE</dt>
1947 ** <dd> ^(This option takes a single argument which is a pointer to
1948 ** an [sqlite3_pcache_methods] object. This object specifies the interface
1949 ** to a custom page cache implementation.)^ ^SQLite makes a copy of the
1950 ** object and uses it for page cache memory allocations.</dd>
1951 **
1952 ** <dt>SQLITE_CONFIG_GETPCACHE</dt>
1953 ** <dd> ^(This option takes a single argument which is a pointer to an
1954 ** [sqlite3_pcache_methods] object. SQLite copies of the current
1955 ** page cache implementation into that object.)^ </dd>
1956 **
1957 ** <dt>SQLITE_CONFIG_LOG</dt>
1958 ** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
1959 ** function with a call signature of void(*)(void*,int,const char*),
1960 ** and a pointer to void. ^If the function pointer is not NULL, it is
1961 ** invoked by [sqlite3_log()] to process each logging event. ^If the
1962 ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
@@ -1970,10 +1979,22 @@
1970 ** The SQLite logging interface is not reentrant; the logger function
1971 ** supplied by the application must not invoke any SQLite interface.
1972 ** In a multi-threaded application, the application-defined logger
1973 ** function must be threadsafe. </dd>
1974 **
 
 
 
 
 
 
 
 
 
 
 
 
1975 ** </dl>
1976 */
1977 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1978 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1979 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1988,10 +2009,11 @@
1988 /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
1989 #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
1990 #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
1991 #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
1992 #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
 
1993
1994 /*
1995 ** CAPI3REF: Database Connection Configuration Options
1996 **
1997 ** These constants are the available integer configuration options that
@@ -2073,17 +2095,21 @@
2073 ** the table has a column of type [INTEGER PRIMARY KEY] then that column
2074 ** is another alias for the rowid.
2075 **
2076 ** ^This routine returns the [rowid] of the most recent
2077 ** successful [INSERT] into the database from the [database connection]
2078 ** in the first argument. ^If no successful [INSERT]s
 
 
2079 ** have ever occurred on that database connection, zero is returned.
2080 **
2081 ** ^(If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
2082 ** row is returned by this routine as long as the trigger is running.
2083 ** But once the trigger terminates, the value returned by this routine
2084 ** reverts to the last value inserted before the trigger fired.)^
 
 
2085 **
2086 ** ^An [INSERT] that fails due to a constraint violation is not a
2087 ** successful [INSERT] and does not change the value returned by this
2088 ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
2089 ** and INSERT OR ABORT make no changes to the return value of this
@@ -2742,10 +2768,13 @@
2742 ** The [sqlite3_set_authorizer | authorizer callback function] must
2743 ** return either [SQLITE_OK] or one of these two constants in order
2744 ** to signal SQLite whether or not the action is permitted. See the
2745 ** [sqlite3_set_authorizer | authorizer documentation] for additional
2746 ** information.
 
 
 
2747 */
2748 #define SQLITE_DENY 1 /* Abort the SQL statement with an error */
2749 #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
2750
2751 /*
@@ -2864,11 +2893,11 @@
2864 SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
2865
2866 /*
2867 ** CAPI3REF: Opening A New Database Connection
2868 **
2869 ** ^These routines open an SQLite database file whose name is given by the
2870 ** filename argument. ^The filename argument is interpreted as UTF-8 for
2871 ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
2872 ** order for sqlite3_open16(). ^(A [database connection] handle is usually
2873 ** returned in *ppDb, even if an error occurs. The only exception is that
2874 ** if SQLite is unable to allocate memory to hold the [sqlite3] object,
@@ -2891,11 +2920,11 @@
2891 ** except that it accepts two additional parameters for additional control
2892 ** over the new database connection. ^(The flags parameter to
2893 ** sqlite3_open_v2() can take one of
2894 ** the following three values, optionally combined with the
2895 ** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
2896 ** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
2897 **
2898 ** <dl>
2899 ** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
2900 ** <dd>The database is opened in read-only mode. If the database does not
2901 ** already exist, an error is returned.</dd>)^
@@ -2910,13 +2939,12 @@
2910 ** it does not already exist. This is the behavior that is always used for
2911 ** sqlite3_open() and sqlite3_open16().</dd>)^
2912 ** </dl>
2913 **
2914 ** If the 3rd parameter to sqlite3_open_v2() is not one of the
2915 ** combinations shown above or one of the combinations shown above combined
2916 ** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX],
2917 ** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags,
2918 ** then the behavior is undefined.
2919 **
2920 ** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
2921 ** opens in the multi-thread [threading mode] as long as the single-thread
2922 ** mode has not been set at compile-time or start-time. ^If the
@@ -2926,10 +2954,15 @@
2926 ** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
2927 ** eligible to use [shared cache mode], regardless of whether or not shared
2928 ** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
2929 ** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
2930 ** participate in [shared cache mode] even if it is enabled.
 
 
 
 
 
2931 **
2932 ** ^If the filename is ":memory:", then a private, temporary in-memory database
2933 ** is created for the connection. ^This in-memory database will vanish when
2934 ** the database connection is closed. Future versions of SQLite might
2935 ** make use of additional special filenames that begin with the ":" character.
@@ -2939,14 +2972,115 @@
2939 **
2940 ** ^If the filename is an empty string, then a private, temporary
2941 ** on-disk database will be created. ^This private database will be
2942 ** automatically deleted as soon as the database connection is closed.
2943 **
2944 ** ^The fourth parameter to sqlite3_open_v2() is the name of the
2945 ** [sqlite3_vfs] object that defines the operating system interface that
2946 ** the new database connection should use. ^If the fourth parameter is
2947 ** a NULL pointer then the default [sqlite3_vfs] object is used.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2948 **
2949 ** <b>Note to Windows users:</b> The encoding used for the filename argument
2950 ** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
2951 ** codepage is currently defined. Filenames containing international
2952 ** characters must be converted to UTF-8 prior to passing them into
@@ -2964,10 +3098,30 @@
2964 const char *filename, /* Database filename (UTF-8) */
2965 sqlite3 **ppDb, /* OUT: SQLite db handle */
2966 int flags, /* Flags */
2967 const char *zVfs /* Name of VFS module to use */
2968 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2969
2970 /*
2971 ** CAPI3REF: Error Codes And Messages
2972 **
2973 ** ^The sqlite3_errcode() interface returns the numeric [result code] or
@@ -3080,47 +3234,49 @@
3080 ** that can be lowered at run-time using [sqlite3_limit()].
3081 ** The synopsis of the meanings of the various limits is shown below.
3082 ** Additional information is available at [limits | Limits in SQLite].
3083 **
3084 ** <dl>
3085 ** ^(<dt>SQLITE_LIMIT_LENGTH</dt>
3086 ** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
3087 **
3088 ** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
3089 ** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
3090 **
3091 ** ^(<dt>SQLITE_LIMIT_COLUMN</dt>
3092 ** <dd>The maximum number of columns in a table definition or in the
3093 ** result set of a [SELECT] or the maximum number of columns in an index
3094 ** or in an ORDER BY or GROUP BY clause.</dd>)^
3095 **
3096 ** ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
3097 ** <dd>The maximum depth of the parse tree on any expression.</dd>)^
3098 **
3099 ** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
3100 ** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
3101 **
3102 ** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
3103 ** <dd>The maximum number of instructions in a virtual machine program
3104 ** used to implement an SQL statement. This limit is not currently
3105 ** enforced, though that might be added in some future release of
3106 ** SQLite.</dd>)^
3107 **
3108 ** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
3109 ** <dd>The maximum number of arguments on a function.</dd>)^
3110 **
3111 ** ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
3112 ** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
3113 **
 
3114 ** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
3115 ** <dd>The maximum length of the pattern argument to the [LIKE] or
3116 ** [GLOB] operators.</dd>)^
3117 **
 
3118 ** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
3119 ** <dd>The maximum index number of any [parameter] in an SQL statement.)^
3120 **
3121 ** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
3122 ** <dd>The maximum depth of recursion for triggers.</dd>)^
3123 ** </dl>
3124 */
3125 #define SQLITE_LIMIT_LENGTH 0
3126 #define SQLITE_LIMIT_SQL_LENGTH 1
@@ -5151,10 +5307,15 @@
5151 int (*xRollback)(sqlite3_vtab *pVTab);
5152 int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
5153 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
5154 void **ppArg);
5155 int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
 
 
 
 
 
5156 };
5157
5158 /*
5159 ** CAPI3REF: Virtual Table Indexing Information
5160 ** KEYWORDS: sqlite3_index_info
@@ -5965,11 +6126,11 @@
5965 **
5966 ** ^This interface is used to retrieve runtime status information
5967 ** about the performance of SQLite, and optionally to reset various
5968 ** highwater marks. ^The first argument is an integer code for
5969 ** the specific parameter to measure. ^(Recognized integer codes
5970 ** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
5971 ** ^The current value of the parameter is returned into *pCurrent.
5972 ** ^The highest recorded value is returned in *pHighwater. ^If the
5973 ** resetFlag is true, then the highest record value is reset after
5974 ** *pHighwater is written. ^(Some parameters do not record the highest
5975 ** value. For those parameters
@@ -5992,82 +6153,84 @@
5992 SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
5993
5994
5995 /*
5996 ** CAPI3REF: Status Parameters
 
5997 **
5998 ** These integer constants designate various run-time status parameters
5999 ** that can be returned by [sqlite3_status()].
6000 **
6001 ** <dl>
6002 ** ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
6003 ** <dd>This parameter is the current amount of memory checked out
6004 ** using [sqlite3_malloc()], either directly or indirectly. The
6005 ** figure includes calls made to [sqlite3_malloc()] by the application
6006 ** and internal memory usage by the SQLite library. Scratch memory
6007 ** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
6008 ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
6009 ** this parameter. The amount returned is the sum of the allocation
6010 ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
6011 **
6012 ** ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
6013 ** <dd>This parameter records the largest memory allocation request
6014 ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
6015 ** internal equivalents). Only the value returned in the
6016 ** *pHighwater parameter to [sqlite3_status()] is of interest.
6017 ** The value written into the *pCurrent parameter is undefined.</dd>)^
6018 **
6019 ** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
6020 ** <dd>This parameter records the number of separate memory allocations
6021 ** currently checked out.</dd>)^
6022 **
6023 ** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
6024 ** <dd>This parameter returns the number of pages used out of the
6025 ** [pagecache memory allocator] that was configured using
6026 ** [SQLITE_CONFIG_PAGECACHE]. The
6027 ** value returned is in pages, not in bytes.</dd>)^
6028 **
 
6029 ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
6030 ** <dd>This parameter returns the number of bytes of page cache
6031 ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
6032 ** buffer and where forced to overflow to [sqlite3_malloc()]. The
6033 ** returned value includes allocations that overflowed because they
6034 ** where too large (they were larger than the "sz" parameter to
6035 ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
6036 ** no space was left in the page cache.</dd>)^
6037 **
6038 ** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
6039 ** <dd>This parameter records the largest memory allocation request
6040 ** handed to [pagecache memory allocator]. Only the value returned in the
6041 ** *pHighwater parameter to [sqlite3_status()] is of interest.
6042 ** The value written into the *pCurrent parameter is undefined.</dd>)^
6043 **
6044 ** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
6045 ** <dd>This parameter returns the number of allocations used out of the
6046 ** [scratch memory allocator] configured using
6047 ** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
6048 ** in bytes. Since a single thread may only have one scratch allocation
6049 ** outstanding at time, this parameter also reports the number of threads
6050 ** using scratch memory at the same time.</dd>)^
6051 **
6052 ** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
6053 ** <dd>This parameter returns the number of bytes of scratch memory
6054 ** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
6055 ** buffer and where forced to overflow to [sqlite3_malloc()]. The values
6056 ** returned include overflows because the requested allocation was too
6057 ** larger (that is, because the requested allocation was larger than the
6058 ** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
6059 ** slots were available.
6060 ** </dd>)^
6061 **
6062 ** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
6063 ** <dd>This parameter records the largest memory allocation request
6064 ** handed to [scratch memory allocator]. Only the value returned in the
6065 ** *pHighwater parameter to [sqlite3_status()] is of interest.
6066 ** The value written into the *pCurrent parameter is undefined.</dd>)^
6067 **
6068 ** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
6069 ** <dd>This parameter records the deepest parser stack. It is only
6070 ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
6071 ** </dl>
6072 **
6073 ** New status parameters may be added from time to time.
@@ -6088,13 +6251,13 @@
6088 **
6089 ** ^This interface is used to retrieve runtime status information
6090 ** about a single [database connection]. ^The first argument is the
6091 ** database connection object to be interrogated. ^The second argument
6092 ** is an integer constant, taken from the set of
6093 ** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
6094 ** determines the parameter to interrogate. The set of
6095 ** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
6096 ** to grow in future releases of SQLite.
6097 **
6098 ** ^The current value of the requested parameter is written into *pCur
6099 ** and the highest instantaneous value is written into *pHiwtr. ^If
6100 ** the resetFlg is true, then the highest instantaneous value is
@@ -6107,10 +6270,11 @@
6107 */
6108 SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
6109
6110 /*
6111 ** CAPI3REF: Status Parameters for database connections
 
6112 **
6113 ** These constants are the available integer "verbs" that can be passed as
6114 ** the second argument to the [sqlite3_db_status()] interface.
6115 **
6116 ** New verbs may be added in future releases of SQLite. Existing verbs
@@ -6118,48 +6282,50 @@
6118 ** [sqlite3_db_status()] to make sure that the call worked.
6119 ** The [sqlite3_db_status()] interface will return a non-zero error code
6120 ** if a discontinued or unsupported verb is invoked.
6121 **
6122 ** <dl>
6123 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
6124 ** <dd>This parameter returns the number of lookaside memory slots currently
6125 ** checked out.</dd>)^
6126 **
6127 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
6128 ** <dd>This parameter returns the number malloc attempts that were
6129 ** satisfied using lookaside memory. Only the high-water value is meaningful;
6130 ** the current value is always zero.)^
6131 **
 
6132 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
6133 ** <dd>This parameter returns the number malloc attempts that might have
6134 ** been satisfied using lookaside memory but failed due to the amount of
6135 ** memory requested being larger than the lookaside slot size.
6136 ** Only the high-water value is meaningful;
6137 ** the current value is always zero.)^
6138 **
 
6139 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
6140 ** <dd>This parameter returns the number malloc attempts that might have
6141 ** been satisfied using lookaside memory but failed due to all lookaside
6142 ** memory already being in use.
6143 ** Only the high-water value is meaningful;
6144 ** the current value is always zero.)^
6145 **
6146 ** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
6147 ** <dd>This parameter returns the approximate number of of bytes of heap
6148 ** memory used by all pager caches associated with the database connection.)^
6149 ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
6150 **
6151 ** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
6152 ** <dd>This parameter returns the approximate number of of bytes of heap
6153 ** memory used to store the schema for all databases associated
6154 ** with the connection - main, temp, and any [ATTACH]-ed databases.)^
6155 ** ^The full amount of memory used by the schemas is reported, even if the
6156 ** schema memory is shared with other database connections due to
6157 ** [shared cache mode] being enabled.
6158 ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
6159 **
6160 ** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
6161 ** <dd>This parameter returns the approximate number of of bytes of heap
6162 ** and lookaside memory used by all prepared statements associated with
6163 ** the database connection.)^
6164 ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
6165 ** </dd>
@@ -6177,11 +6343,11 @@
6177
6178 /*
6179 ** CAPI3REF: Prepared Statement Status
6180 **
6181 ** ^(Each prepared statement maintains various
6182 ** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
6183 ** of times it has performed specific operations.)^ These counters can
6184 ** be used to monitor the performance characteristics of the prepared
6185 ** statements. For example, if the number of table steps greatly exceeds
6186 ** the number of table searches or result rows, that would tend to indicate
6187 ** that the prepared statement is using a full table scan rather than
@@ -6188,11 +6354,11 @@
6188 ** an index.
6189 **
6190 ** ^(This interface is used to retrieve and reset counter values from
6191 ** a [prepared statement]. The first argument is the prepared statement
6192 ** object to be interrogated. The second argument
6193 ** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
6194 ** to be interrogated.)^
6195 ** ^The current value of the requested counter is returned.
6196 ** ^If the resetFlg is true, then the counter is reset to zero after this
6197 ** interface call returns.
6198 **
@@ -6200,28 +6366,29 @@
6200 */
6201 SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
6202
6203 /*
6204 ** CAPI3REF: Status Parameters for prepared statements
 
6205 **
6206 ** These preprocessor macros define integer codes that name counter
6207 ** values associated with the [sqlite3_stmt_status()] interface.
6208 ** The meanings of the various counters are as follows:
6209 **
6210 ** <dl>
6211 ** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
6212 ** <dd>^This is the number of times that SQLite has stepped forward in
6213 ** a table as part of a full table scan. Large numbers for this counter
6214 ** may indicate opportunities for performance improvement through
6215 ** careful use of indices.</dd>
6216 **
6217 ** <dt>SQLITE_STMTSTATUS_SORT</dt>
6218 ** <dd>^This is the number of sort operations that have occurred.
6219 ** A non-zero value in this counter may indicate an opportunity to
6220 ** improvement performance through careful use of indices.</dd>
6221 **
6222 ** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
6223 ** <dd>^This is the number of rows inserted into transient indices that
6224 ** were created automatically in order to help joins run faster.
6225 ** A non-zero value in this counter may indicate an opportunity to
6226 ** improvement performance by adding permanent indices that do not
6227 ** need to be reinitialized each time the statement is run.</dd>
@@ -6268,10 +6435,11 @@
6268 ** ^(The contents of the sqlite3_pcache_methods structure are copied to an
6269 ** internal buffer by SQLite within the call to [sqlite3_config]. Hence
6270 ** the application may discard the parameter after the call to
6271 ** [sqlite3_config()] returns.)^
6272 **
 
6273 ** ^(The xInit() method is called once for each effective
6274 ** call to [sqlite3_initialize()])^
6275 ** (usually only once during the lifetime of the process). ^(The xInit()
6276 ** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^
6277 ** The intent of the xInit() method is to set up global data structures
@@ -6278,10 +6446,11 @@
6278 ** required by the custom page cache implementation.
6279 ** ^(If the xInit() method is NULL, then the
6280 ** built-in default page cache is used instead of the application defined
6281 ** page cache.)^
6282 **
 
6283 ** ^The xShutdown() method is called by [sqlite3_shutdown()].
6284 ** It can be used to clean up
6285 ** any outstanding resources before process shutdown, if required.
6286 ** ^The xShutdown() method may be NULL.
6287 **
@@ -6292,10 +6461,11 @@
6292 ** in multithreaded applications.
6293 **
6294 ** ^SQLite will never invoke xInit() more than once without an intervening
6295 ** call to xShutdown().
6296 **
 
6297 ** ^SQLite invokes the xCreate() method to construct a new cache instance.
6298 ** SQLite will typically create one cache instance for each open database file,
6299 ** though this is not guaranteed. ^The
6300 ** first parameter, szPage, is the size in bytes of the pages that must
6301 ** be allocated by the cache. ^szPage will not be a power of two. ^szPage
@@ -6316,20 +6486,23 @@
6316 ** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
6317 ** false will always have the "discard" flag set to true.
6318 ** ^Hence, a cache created with bPurgeable false will
6319 ** never contain any unpinned pages.
6320 **
 
6321 ** ^(The xCachesize() method may be called at any time by SQLite to set the
6322 ** suggested maximum cache-size (number of pages stored by) the cache
6323 ** instance passed as the first argument. This is the value configured using
6324 ** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
6325 ** parameter, the implementation is not required to do anything with this
6326 ** value; it is advisory only.
6327 **
 
6328 ** The xPagecount() method must return the number of pages currently
6329 ** stored in the cache, both pinned and unpinned.
6330 **
 
6331 ** The xFetch() method locates a page in the cache and returns a pointer to
6332 ** the page, or a NULL pointer.
6333 ** A "page", in this context, means a buffer of szPage bytes aligned at an
6334 ** 8-byte boundary. The page to be fetched is determined by the key. ^The
6335 ** mimimum key value is 1. After it has been retrieved using xFetch, the page
@@ -6354,10 +6527,11 @@
6354 ** will only use a createFlag of 2 after a prior call with a createFlag of 1
6355 ** failed.)^ In between the to xFetch() calls, SQLite may
6356 ** attempt to unpin one or more cache pages by spilling the content of
6357 ** pinned pages to disk and synching the operating system disk cache.
6358 **
 
6359 ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
6360 ** as its second argument. If the third parameter, discard, is non-zero,
6361 ** then the page must be evicted from the cache.
6362 ** ^If the discard parameter is
6363 ** zero, then the page may be discarded or retained at the discretion of
@@ -6366,10 +6540,11 @@
6366 **
6367 ** The cache must not perform any reference counting. A single
6368 ** call to xUnpin() unpins the page regardless of the number of prior calls
6369 ** to xFetch().
6370 **
 
6371 ** The xRekey() method is used to change the key value associated with the
6372 ** page passed as the second argument. If the cache
6373 ** previously contains an entry associated with newKey, it must be
6374 ** discarded. ^Any prior cache entry associated with newKey is guaranteed not
6375 ** to be pinned.
@@ -6378,10 +6553,11 @@
6378 ** existing cache entries with page numbers (keys) greater than or equal
6379 ** to the value of the iLimit parameter passed to xTruncate(). If any
6380 ** of these pages are pinned, they are implicitly unpinned, meaning that
6381 ** they can be safely discarded.
6382 **
 
6383 ** ^The xDestroy() method is used to delete a cache allocated by xCreate().
6384 ** All resources associated with the specified cache should be freed. ^After
6385 ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
6386 ** handle invalid, and will not use it with any other sqlite3_pcache_methods
6387 ** functions.
@@ -6440,11 +6616,11 @@
6440 ** associated with the backup operation.
6441 ** </ol>)^
6442 ** There should be exactly one call to sqlite3_backup_finish() for each
6443 ** successful call to sqlite3_backup_init().
6444 **
6445 ** <b>sqlite3_backup_init()</b>
6446 **
6447 ** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
6448 ** [database connection] associated with the destination database
6449 ** and the database name, respectively.
6450 ** ^The database name is "main" for the main database, "temp" for the
@@ -6467,11 +6643,11 @@
6467 ** [sqlite3_backup] object.
6468 ** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
6469 ** sqlite3_backup_finish() functions to perform the specified backup
6470 ** operation.
6471 **
6472 ** <b>sqlite3_backup_step()</b>
6473 **
6474 ** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
6475 ** the source and destination databases specified by [sqlite3_backup] object B.
6476 ** ^If N is negative, all remaining source pages are copied.
6477 ** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
@@ -6524,11 +6700,11 @@
6524 ** restarted by the next call to sqlite3_backup_step(). ^If the source
6525 ** database is modified by the using the same database connection as is used
6526 ** by the backup operation, then the backup database is automatically
6527 ** updated at the same time.
6528 **
6529 ** <b>sqlite3_backup_finish()</b>
6530 **
6531 ** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
6532 ** application wishes to abandon the backup operation, the application
6533 ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
6534 ** ^The sqlite3_backup_finish() interfaces releases all
@@ -6547,11 +6723,12 @@
6547 **
6548 ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
6549 ** is not a permanent error and does not affect the return value of
6550 ** sqlite3_backup_finish().
6551 **
6552 ** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b>
 
6553 **
6554 ** ^Each call to sqlite3_backup_step() sets two values inside
6555 ** the [sqlite3_backup] object: the number of pages still to be backed
6556 ** up and the total number of pages in the source database file.
6557 ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
@@ -6932,10 +7109,97 @@
6932 ** each of these values.
6933 */
6934 #define SQLITE_CHECKPOINT_PASSIVE 0
6935 #define SQLITE_CHECKPOINT_FULL 1
6936 #define SQLITE_CHECKPOINT_RESTART 2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6937
6938
6939 /*
6940 ** Undo the hack that converts floating point types to integer for
6941 ** builds on processors without floating point support.
@@ -7599,10 +7863,11 @@
7599 typedef struct Trigger Trigger;
7600 typedef struct TriggerPrg TriggerPrg;
7601 typedef struct TriggerStep TriggerStep;
7602 typedef struct UnpackedRecord UnpackedRecord;
7603 typedef struct VTable VTable;
 
7604 typedef struct Walker Walker;
7605 typedef struct WherePlan WherePlan;
7606 typedef struct WhereInfo WhereInfo;
7607 typedef struct WhereLevel WhereLevel;
7608
@@ -7655,10 +7920,11 @@
7655 typedef struct BtCursor BtCursor;
7656 typedef struct BtShared BtShared;
7657
7658
7659 SQLITE_PRIVATE int sqlite3BtreeOpen(
 
7660 const char *zFilename, /* Name of database file to open */
7661 sqlite3 *db, /* Associated database connection */
7662 Btree **ppBtree, /* Return open Btree* here */
7663 int flags, /* Flags */
7664 int vfsFlags /* Flags passed through to VFS open */
@@ -9134,19 +9400,20 @@
9134 struct sqlite3 {
9135 sqlite3_vfs *pVfs; /* OS Interface */
9136 int nDb; /* Number of backends currently in use */
9137 Db *aDb; /* All backends */
9138 int flags; /* Miscellaneous flags. See below */
9139 int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
9140 int errCode; /* Most recent error code (SQLITE_*) */
9141 int errMask; /* & result codes with this before returning */
9142 u8 autoCommit; /* The auto-commit flag. */
9143 u8 temp_store; /* 1: file 2: memory 0: default */
9144 u8 mallocFailed; /* True if we have seen a malloc failure */
9145 u8 dfltLockMode; /* Default locking-mode for attached dbs */
9146 signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
9147 u8 suppressErr; /* Do not issue error messages if true */
 
9148 int nextPagesize; /* Pagesize after VACUUM if >0 */
9149 int nTable; /* Number of tables in the database */
9150 CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
9151 i64 lastRowid; /* ROWID of most recent insert (see above) */
9152 u32 magic; /* Magic number for detect library misuse */
@@ -9201,11 +9468,11 @@
9201 void *pProgressArg; /* Argument to the progress callback */
9202 int nProgressOps; /* Number of opcodes for progress callback */
9203 #endif
9204 #ifndef SQLITE_OMIT_VIRTUALTABLE
9205 Hash aModule; /* populated by sqlite3_create_module() */
9206 Table *pVTab; /* vtab with active Connect/Create method */
9207 VTable **aVTrans; /* Virtual tables with open transactions */
9208 int nVTrans; /* Allocated size of aVTrans */
9209 VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
9210 #endif
9211 FuncDefHash aFunc; /* Hash table of connection functions */
@@ -9564,10 +9831,11 @@
9564 struct VTable {
9565 sqlite3 *db; /* Database connection associated with this table */
9566 Module *pMod; /* Pointer to module implementation */
9567 sqlite3_vtab *pVtab; /* Pointer to vtab instance */
9568 int nRef; /* Number of pointers to this structure */
 
9569 VTable *pNext; /* Next in linked list (see above) */
9570 };
9571
9572 /*
9573 ** Each SQL table is represented in memory by an instance of the
@@ -10752,10 +11020,11 @@
10752 */
10753 struct Sqlite3Config {
10754 int bMemstat; /* True to enable memory status */
10755 int bCoreMutex; /* True to enable core mutexing */
10756 int bFullMutex; /* True to enable full mutexing */
 
10757 int mxStrlen; /* Maximum string length */
10758 int szLookaside; /* Default lookaside buffer size */
10759 int nLookaside; /* Default lookaside buffer count */
10760 sqlite3_mem_methods m; /* Low-level memory allocation interface */
10761 sqlite3_mutex_methods mutex; /* Low-level mutex interface */
@@ -11001,10 +11270,12 @@
11001 SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
11002 SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
11003 SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
11004 SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
11005 SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
 
 
11006
11007 SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
11008 SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
11009 SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
11010 SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*);
@@ -11251,10 +11522,11 @@
11251 SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
11252 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
11253 SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
11254 SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
11255 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
 
11256 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
11257 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
11258 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
11259 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
11260 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
@@ -11266,10 +11538,16 @@
11266 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
11267 SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
11268 SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
11269 SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
11270 SQLITE_PRIVATE int sqlite3AbsInt32(int);
 
 
 
 
 
 
11271
11272 SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
11273 SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
11274 SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
11275 void(*)(void*));
@@ -11375,18 +11653,20 @@
11375 # define sqlite3VtabCommit(X)
11376 # define sqlite3VtabInSync(db) 0
11377 # define sqlite3VtabLock(X)
11378 # define sqlite3VtabUnlock(X)
11379 # define sqlite3VtabUnlockList(X)
 
11380 #else
11381 SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*);
11382 SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **);
11383 SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
11384 SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
11385 SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
11386 SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
11387 SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
 
11388 # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
11389 #endif
11390 SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
11391 SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
11392 SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
@@ -11689,20 +11969,23 @@
11689 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
11690 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
11691 };
11692 #endif
11693
11694
 
 
11695
11696 /*
11697 ** The following singleton contains the global configuration for
11698 ** the SQLite library.
11699 */
11700 SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
11701 SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
11702 1, /* bCoreMutex */
11703 SQLITE_THREADSAFE==1, /* bFullMutex */
 
11704 0x7ffffffe, /* mxStrlen */
11705 100, /* szLookaside */
11706 500, /* nLookaside */
11707 {0,0,0,0,0,0,0,0}, /* m */
11708 {0,0,0,0,0,0,0,0,0}, /* mutex */
@@ -17948,11 +18231,11 @@
17948 assert( sqlite3_mutex_held(mem0.mutex) );
17949 nFull = sqlite3GlobalConfig.m.xRoundup(n);
17950 sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
17951 if( mem0.alarmCallback!=0 ){
17952 int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
17953 if( nUsed+nFull >= mem0.alarmThreshold ){
17954 mem0.nearlyFull = 1;
17955 sqlite3MallocAlarm(nFull);
17956 }else{
17957 mem0.nearlyFull = 0;
17958 }
@@ -18189,11 +18472,11 @@
18189
18190 /*
18191 ** Change the size of an existing memory allocation
18192 */
18193 SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
18194 int nOld, nNew;
18195 void *pNew;
18196 if( pOld==0 ){
18197 return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
18198 }
18199 if( nBytes<=0 ){
@@ -18212,13 +18495,14 @@
18212 if( nOld==nNew ){
18213 pNew = pOld;
18214 }else if( sqlite3GlobalConfig.bMemstat ){
18215 sqlite3_mutex_enter(mem0.mutex);
18216 sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
18217 if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >=
18218 mem0.alarmThreshold ){
18219 sqlite3MallocAlarm(nNew-nOld);
 
18220 }
18221 assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
18222 assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
18223 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
18224 if( pNew==0 && mem0.alarmCallback ){
@@ -21180,27 +21464,25 @@
21180 p[3] = (u8)v;
21181 }
21182
21183
21184
21185 #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
21186 /*
21187 ** Translate a single byte of Hex into an integer.
21188 ** This routine only works if h really is a valid hexadecimal
21189 ** character: 0..9a..fA..F
21190 */
21191 static u8 hexToInt(int h){
21192 assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
21193 #ifdef SQLITE_ASCII
21194 h += 9*(1&(h>>6));
21195 #endif
21196 #ifdef SQLITE_EBCDIC
21197 h += 9*(1&~(h>>4));
21198 #endif
21199 return (u8)(h & 0xf);
21200 }
21201 #endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
21202
21203 #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
21204 /*
21205 ** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
21206 ** value. Return a pointer to its binary value. Space to hold the
@@ -21213,11 +21495,11 @@
21213
21214 zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
21215 n--;
21216 if( zBlob ){
21217 for(i=0; i<n; i+=2){
21218 zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
21219 }
21220 zBlob[i/2] = 0;
21221 }
21222 return zBlob;
21223 }
@@ -21345,10 +21627,36 @@
21345 SQLITE_PRIVATE int sqlite3AbsInt32(int x){
21346 if( x>=0 ) return x;
21347 if( x==(int)0x80000000 ) return 0x7fffffff;
21348 return -x;
21349 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21350
21351 /************** End of util.c ************************************************/
21352 /************** Begin file hash.c ********************************************/
21353 /*
21354 ** 2001 September 22
@@ -24398,10 +24706,22 @@
24398 #if SQLITE_THREADSAFE
24399 #define threadid pthread_self()
24400 #else
24401 #define threadid 0
24402 #endif
 
 
 
 
 
 
 
 
 
 
 
 
24403
24404 /*
24405 ** Many system calls are accessed through pointer-to-functions so that
24406 ** they may be overridden at runtime to facilitate fault injection during
24407 ** testing and sandboxing. The following array holds the names and pointers
@@ -24410,11 +24730,11 @@
24410 static struct unix_syscall {
24411 const char *zName; /* Name of the sytem call */
24412 sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
24413 sqlite3_syscall_ptr pDefault; /* Default value */
24414 } aSyscall[] = {
24415 { "open", (sqlite3_syscall_ptr)open, 0 },
24416 #define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
24417
24418 { "close", (sqlite3_syscall_ptr)close, 0 },
24419 #define osClose ((int(*)(int))aSyscall[1].pCurrent)
24420
@@ -24448,11 +24768,11 @@
24448 #define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
24449
24450 { "read", (sqlite3_syscall_ptr)read, 0 },
24451 #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
24452
24453 #if defined(USE_PREAD) || defined(SQLITE_ENABLE_LOCKING_STYLE)
24454 { "pread", (sqlite3_syscall_ptr)pread, 0 },
24455 #else
24456 { "pread", (sqlite3_syscall_ptr)0, 0 },
24457 #endif
24458 #define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -24465,11 +24785,11 @@
24465 #define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
24466
24467 { "write", (sqlite3_syscall_ptr)write, 0 },
24468 #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
24469
24470 #if defined(USE_PREAD) || defined(SQLITE_ENABLE_LOCKING_STYLE)
24471 { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
24472 #else
24473 { "pwrite", (sqlite3_syscall_ptr)0, 0 },
24474 #endif
24475 #define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -24483,12 +24803,14 @@
24483 #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
24484 aSyscall[13].pCurrent)
24485
24486 #if SQLITE_ENABLE_LOCKING_STYLE
24487 { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
 
 
 
24488 #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
24489 #endif
24490
24491 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
24492 { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
24493 #else
24494 { "fallocate", (sqlite3_syscall_ptr)0, 0 },
@@ -25049,11 +25371,11 @@
25049 unixShmNode *pShmNode; /* Shared memory associated with this inode */
25050 int nLock; /* Number of outstanding file locks */
25051 UnixUnusedFd *pUnused; /* Unused file descriptors to close */
25052 unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
25053 unixInodeInfo *pPrev; /* .... doubly linked */
25054 #if defined(SQLITE_ENABLE_LOCKING_STYLE)
25055 unsigned long long sharedByte; /* for AFP simulated shared lock */
25056 #endif
25057 #if OS_VXWORKS
25058 sem_t *pSem; /* Named POSIX semaphore */
25059 char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
@@ -27206,11 +27528,11 @@
27206 }
27207 SimulateIOError(( wrote=(-1), amt=1 ));
27208 SimulateDiskfullError(( wrote=0, amt=1 ));
27209
27210 if( amt>0 ){
27211 if( wrote<0 ){
27212 /* lastErrno set by seekAndWrite */
27213 return SQLITE_IOERR_WRITE;
27214 }else{
27215 pFile->lastErrno = 0; /* not a system error */
27216 return SQLITE_FULL;
@@ -27873,10 +28195,11 @@
27873 sqlite3_snprintf(nShmFilename, zShmFilename,
27874 SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
27875 (u32)sStat.st_ino, (u32)sStat.st_dev);
27876 #else
27877 sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
 
27878 #endif
27879 pShmNode->h = -1;
27880 pDbFd->pInode->pShmNode = pShmNode;
27881 pShmNode->pInode = pDbFd->pInode;
27882 pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
@@ -28031,11 +28354,11 @@
28031 if( pShmNode->h>=0 ){
28032 pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
28033 MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
28034 );
28035 if( pMem==MAP_FAILED ){
28036 rc = SQLITE_IOERR;
28037 goto shmpage_out;
28038 }
28039 }else{
28040 pMem = sqlite3_malloc(szRegion);
28041 if( pMem==0 ){
@@ -28906,17 +29229,23 @@
28906 ** Finally, if the file being opened is a WAL or regular journal file, then
28907 ** this function queries the file-system for the permissions on the
28908 ** corresponding database file and sets *pMode to this value. Whenever
28909 ** possible, WAL and journal files are created using the same permissions
28910 ** as the associated database file.
 
 
 
 
 
28911 */
28912 static int findCreateFileMode(
28913 const char *zPath, /* Path of file (possibly) being created */
28914 int flags, /* Flags passed as 4th argument to xOpen() */
28915 mode_t *pMode /* OUT: Permissions to open file with */
28916 ){
28917 int rc = SQLITE_OK; /* Return Code */
 
28918 if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
28919 char zDb[MAX_PATHNAME+1]; /* Database file path */
28920 int nDb; /* Number of valid bytes in zDb */
28921 struct stat sStat; /* Output of stat() on database file */
28922
@@ -28924,19 +29253,19 @@
28924 ** the path to the associated database file from zPath. This block handles
28925 ** the following naming conventions:
28926 **
28927 ** "<path to db>-journal"
28928 ** "<path to db>-wal"
28929 ** "<path to db>-journal-NNNN"
28930 ** "<path to db>-wal-NNNN"
28931 **
28932 ** where NNNN is a 4 digit decimal number. The NNNN naming schemes are
28933 ** used by the test_multiplex.c module.
28934 */
28935 nDb = sqlite3Strlen30(zPath) - 1;
28936 while( nDb>0 && zPath[nDb]!='l' ) nDb--;
28937 nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7);
28938 memcpy(zDb, zPath, nDb);
28939 zDb[nDb] = '\0';
28940
28941 if( 0==stat(zDb, &sStat) ){
28942 *pMode = sStat.st_mode & 0777;
@@ -28943,12 +29272,10 @@
28943 }else{
28944 rc = SQLITE_IOERR_FSTAT;
28945 }
28946 }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
28947 *pMode = 0600;
28948 }else{
28949 *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
28950 }
28951 return rc;
28952 }
28953
28954 /*
@@ -30801,10 +31128,14 @@
30801 UNIXVFS("unix-nfs", nfsIoFinder ),
30802 UNIXVFS("unix-proxy", proxyIoFinder ),
30803 #endif
30804 };
30805 unsigned int i; /* Loop counter */
 
 
 
 
30806
30807 /* Register all VFSes defined in the aVfs[] array */
30808 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
30809 sqlite3_vfs_register(&aVfs[i], i==0);
30810 }
@@ -31147,10 +31478,11 @@
31147 HANDLE hShared; /* Shared memory segment used for locking */
31148 winceLock local; /* Locks obtained by this instance of winFile */
31149 winceLock *shared; /* Global shared lock memory for the file */
31150 #endif
31151 };
 
31152
31153 /*
31154 ** Forward prototypes.
31155 */
31156 static int getSectorSize(
@@ -31315,11 +31647,11 @@
31315
31316 /*
31317 ** Convert UTF-8 to multibyte character string. Space to hold the
31318 ** returned string is obtained from malloc().
31319 */
31320 static char *utf8ToMbcs(const char *zFilename){
31321 char *zFilenameMbcs;
31322 WCHAR *zTmpWide;
31323
31324 zTmpWide = utf8ToUnicode(zFilename);
31325 if( zTmpWide==0 ){
@@ -31328,10 +31660,113 @@
31328 zFilenameMbcs = unicodeToMbcs(zTmpWide);
31329 free(zTmpWide);
31330 return zFilenameMbcs;
31331 }
31332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31333 #if SQLITE_OS_WINCE
31334 /*************************************************************************
31335 ** This section contains code for WinCE only.
31336 */
31337 /*
@@ -31404,10 +31839,11 @@
31404
31405 /* Create/open the named mutex */
31406 pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
31407 if (!pFile->hMutex){
31408 pFile->lastErrno = GetLastError();
 
31409 free(zName);
31410 return FALSE;
31411 }
31412
31413 /* Acquire the mutex before continuing */
@@ -31435,10 +31871,11 @@
31435 pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
31436 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
31437 /* If mapping failed, close the shared memory handle and erase it */
31438 if (!pFile->shared){
31439 pFile->lastErrno = GetLastError();
 
31440 CloseHandle(pFile->hShared);
31441 pFile->hShared = NULL;
31442 }
31443 }
31444
@@ -31680,10 +32117,11 @@
31680 ** GetLastError().
31681 */
31682 dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
31683 if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){
31684 pFile->lastErrno = GetLastError();
 
31685 return 1;
31686 }
31687
31688 return 0;
31689 }
@@ -31725,11 +32163,12 @@
31725 free(pFile->zDeleteOnClose);
31726 }
31727 #endif
31728 OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
31729 OpenCounter(-1);
31730 return rc ? SQLITE_OK : SQLITE_IOERR;
 
31731 }
31732
31733 /*
31734 ** Read data from a file into a buffer. Return SQLITE_OK if all
31735 ** bytes were read successfully and SQLITE_IOERR if anything goes
@@ -31751,11 +32190,11 @@
31751 if( seekWinFile(pFile, offset) ){
31752 return SQLITE_FULL;
31753 }
31754 if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
31755 pFile->lastErrno = GetLastError();
31756 return SQLITE_IOERR_READ;
31757 }
31758 if( nRead<(DWORD)amt ){
31759 /* Unread parts of the buffer must be zero-filled */
31760 memset(&((char*)pBuf)[nRead], 0, amt-nRead);
31761 return SQLITE_IOERR_SHORT_READ;
@@ -31802,11 +32241,11 @@
31802
31803 if( rc ){
31804 if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
31805 return SQLITE_FULL;
31806 }
31807 return SQLITE_IOERR_WRITE;
31808 }
31809 return SQLITE_OK;
31810 }
31811
31812 /*
@@ -31830,14 +32269,14 @@
31830 nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
31831 }
31832
31833 /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
31834 if( seekWinFile(pFile, nByte) ){
31835 rc = SQLITE_IOERR_TRUNCATE;
31836 }else if( 0==SetEndOfFile(pFile->h) ){
31837 pFile->lastErrno = GetLastError();
31838 rc = SQLITE_IOERR_TRUNCATE;
31839 }
31840
31841 OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
31842 return rc;
31843 }
@@ -31855,10 +32294,11 @@
31855 ** Make sure all writes to a particular file are committed to disk.
31856 */
31857 static int winSync(sqlite3_file *id, int flags){
31858 #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
31859 winFile *pFile = (winFile*)id;
 
31860 #else
31861 UNUSED_PARAMETER(id);
31862 #endif
31863
31864 assert( pFile );
@@ -31867,36 +32307,37 @@
31867 || (flags&0x0F)==SQLITE_SYNC_FULL
31868 );
31869
31870 OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
31871
 
 
 
 
 
31872 #ifndef SQLITE_TEST
31873 UNUSED_PARAMETER(flags);
31874 #else
31875 if( flags & SQLITE_SYNC_FULL ){
31876 sqlite3_fullsync_count++;
31877 }
31878 sqlite3_sync_count++;
31879 #endif
31880
31881 /* Unix cannot, but some systems may return SQLITE_FULL from here. This
31882 ** line is to test that doing so does not cause any problems.
31883 */
31884 SimulateDiskfullError( return SQLITE_FULL );
31885 SimulateIOError( return SQLITE_IOERR; );
31886
31887 /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
31888 ** no-op
31889 */
31890 #ifdef SQLITE_NO_SYNC
31891 return SQLITE_OK;
31892 #else
31893 if( FlushFileBuffers(pFile->h) ){
 
 
31894 return SQLITE_OK;
31895 }else{
31896 pFile->lastErrno = GetLastError();
31897 return SQLITE_IOERR;
31898 }
31899 #endif
31900 }
31901
31902 /*
@@ -31913,11 +32354,11 @@
31913 lowerBits = GetFileSize(pFile->h, &upperBits);
31914 if( (lowerBits == INVALID_FILE_SIZE)
31915 && ((error = GetLastError()) != NO_ERROR) )
31916 {
31917 pFile->lastErrno = error;
31918 return SQLITE_IOERR_FSTAT;
31919 }
31920 *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
31921 return SQLITE_OK;
31922 }
31923
@@ -31952,10 +32393,11 @@
31952 res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
31953 #endif
31954 }
31955 if( res == 0 ){
31956 pFile->lastErrno = GetLastError();
 
31957 }
31958 return res;
31959 }
31960
31961 /*
@@ -31970,12 +32412,13 @@
31970 #if SQLITE_OS_WINCE==0
31971 }else{
31972 res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
31973 #endif
31974 }
31975 if( res == 0 ){
31976 pFile->lastErrno = GetLastError();
 
31977 }
31978 return res;
31979 }
31980
31981 /*
@@ -32172,11 +32615,11 @@
32172 if( type>=EXCLUSIVE_LOCK ){
32173 UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
32174 if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
32175 /* This should never happen. We should always be able to
32176 ** reacquire the read lock */
32177 rc = SQLITE_IOERR_UNLOCK;
32178 }
32179 }
32180 if( type>=RESERVED_LOCK ){
32181 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
32182 }
@@ -32487,10 +32930,11 @@
32487 return SQLITE_NOMEM;
32488 }
32489 memset(pNew, 0, sizeof(*pNew));
32490 pNew->zFilename = (char*)&pNew[1];
32491 sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
 
32492
32493 /* Look to see if there is an existing winShmNode that can be used.
32494 ** If no matching winShmNode currently exists, create a new one.
32495 */
32496 winShmEnterMutex();
@@ -32529,11 +32973,11 @@
32529 ** If not, truncate the file to zero length.
32530 */
32531 if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
32532 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
32533 if( rc!=SQLITE_OK ){
32534 rc = SQLITE_IOERR_SHMOPEN;
32535 }
32536 }
32537 if( rc==SQLITE_OK ){
32538 winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
32539 rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
@@ -32788,11 +33232,11 @@
32788 ** Check to see if it has been allocated (i.e. if the wal-index file is
32789 ** large enough to contain the requested region).
32790 */
32791 rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
32792 if( rc!=SQLITE_OK ){
32793 rc = SQLITE_IOERR_SHMSIZE;
32794 goto shmpage_out;
32795 }
32796
32797 if( sz<nByte ){
32798 /* The requested memory region does not exist. If isWrite is set to
@@ -32802,11 +33246,11 @@
32802 ** the requested memory region.
32803 */
32804 if( !isWrite ) goto shmpage_out;
32805 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
32806 if( rc!=SQLITE_OK ){
32807 rc = SQLITE_IOERR_SHMSIZE;
32808 goto shmpage_out;
32809 }
32810 }
32811
32812 /* Map the requested memory region into this processes address space. */
@@ -32839,11 +33283,11 @@
32839 (int)GetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion,
32840 pMap ? "ok" : "failed"));
32841 }
32842 if( !pMap ){
32843 pShmNode->lastErrno = GetLastError();
32844 rc = SQLITE_IOERR;
32845 if( hMap ) CloseHandle(hMap);
32846 goto shmpage_out;
32847 }
32848
32849 pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
@@ -32921,11 +33365,11 @@
32921 zConverted = utf8ToUnicode(zFilename);
32922 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
32923 */
32924 #if SQLITE_OS_WINCE==0
32925 }else{
32926 zConverted = utf8ToMbcs(zFilename);
32927 #endif
32928 }
32929 /* caller will handle out of memory */
32930 return zConverted;
32931 }
@@ -33001,72 +33445,10 @@
33001
33002 OSTRACE(("TEMP FILENAME: %s\n", zBuf));
33003 return SQLITE_OK;
33004 }
33005
33006 /*
33007 ** The return value of getLastErrorMsg
33008 ** is zero if the error message fits in the buffer, or non-zero
33009 ** otherwise (if the message was truncated).
33010 */
33011 static int getLastErrorMsg(int nBuf, char *zBuf){
33012 /* FormatMessage returns 0 on failure. Otherwise it
33013 ** returns the number of TCHARs written to the output
33014 ** buffer, excluding the terminating null char.
33015 */
33016 DWORD error = GetLastError();
33017 DWORD dwLen = 0;
33018 char *zOut = 0;
33019
33020 if( isNT() ){
33021 WCHAR *zTempWide = NULL;
33022 dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
33023 NULL,
33024 error,
33025 0,
33026 (LPWSTR) &zTempWide,
33027 0,
33028 0);
33029 if( dwLen > 0 ){
33030 /* allocate a buffer and convert to UTF8 */
33031 zOut = unicodeToUtf8(zTempWide);
33032 /* free the system buffer allocated by FormatMessage */
33033 LocalFree(zTempWide);
33034 }
33035 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
33036 ** Since the ASCII version of these Windows API do not exist for WINCE,
33037 ** it's important to not reference them for WINCE builds.
33038 */
33039 #if SQLITE_OS_WINCE==0
33040 }else{
33041 char *zTemp = NULL;
33042 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
33043 NULL,
33044 error,
33045 0,
33046 (LPSTR) &zTemp,
33047 0,
33048 0);
33049 if( dwLen > 0 ){
33050 /* allocate a buffer and convert to UTF8 */
33051 zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
33052 /* free the system buffer allocated by FormatMessage */
33053 LocalFree(zTemp);
33054 }
33055 #endif
33056 }
33057 if( 0 == dwLen ){
33058 sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
33059 }else{
33060 /* copy a maximum of nBuf chars to output buffer */
33061 sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
33062 /* free the UTF8 buffer */
33063 free(zOut);
33064 }
33065 return 0;
33066 }
33067
33068 /*
33069 ** Open a file.
33070 */
33071 static int winOpen(
33072 sqlite3_vfs *pVfs, /* Not used */
@@ -33234,10 +33616,11 @@
33234 h, zName, dwDesiredAccess,
33235 h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
33236
33237 if( h==INVALID_HANDLE_VALUE ){
33238 pFile->lastErrno = GetLastError();
 
33239 free(zConverted);
33240 if( isReadWrite ){
33241 return winOpen(pVfs, zName, id,
33242 ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
33243 }else{
@@ -33337,11 +33720,12 @@
33337 OSTRACE(("DELETE \"%s\" %s\n", zFilename,
33338 ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
33339 "ok" : "failed" ));
33340
33341 return ( (rc == INVALID_FILE_ATTRIBUTES)
33342 && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
 
33343 }
33344
33345 /*
33346 ** Check the existance and status of a file.
33347 */
@@ -33377,10 +33761,11 @@
33377 }else{
33378 attr = sAttrData.dwFileAttributes;
33379 }
33380 }else{
33381 if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
 
33382 free(zConverted);
33383 return SQLITE_IOERR_ACCESS;
33384 }else{
33385 attr = INVALID_FILE_ATTRIBUTES;
33386 }
@@ -33440,10 +33825,17 @@
33440
33441 #if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
33442 int nByte;
33443 void *zConverted;
33444 char *zOut;
 
 
 
 
 
 
 
33445
33446 /* It's odd to simulate an io-error here, but really this is just
33447 ** using the io-error infrastructure to test that SQLite handles this
33448 ** function failing. This function could fail if, for example, the
33449 ** current working directory has been unlinked.
@@ -36252,10 +36644,11 @@
36252 #define _WAL_H_
36253
36254
36255 #ifdef SQLITE_OMIT_WAL
36256 # define sqlite3WalOpen(x,y,z) 0
 
36257 # define sqlite3WalClose(w,x,y,z) 0
36258 # define sqlite3WalBeginReadTransaction(y,z) 0
36259 # define sqlite3WalEndReadTransaction(z)
36260 # define sqlite3WalRead(v,w,x,y,z) 0
36261 # define sqlite3WalDbsize(y) 0
@@ -36277,13 +36670,16 @@
36277 ** There is one object of this type for each pager.
36278 */
36279 typedef struct Wal Wal;
36280
36281 /* Open and close a connection to a write-ahead log. */
36282 SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, int, Wal**);
36283 SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
36284
 
 
 
36285 /* Used by readers to open (lock) and close (unlock) a snapshot. A
36286 ** snapshot is like a read-transaction. It is the state of the database
36287 ** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
36288 ** preserves the current state even if the other threads or processes
36289 ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
@@ -40628,10 +41024,12 @@
40628 int nPathname = 0; /* Number of bytes in zPathname */
40629 int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
40630 int noReadlock = (flags & PAGER_NO_READLOCK)!=0; /* True to omit read-lock */
40631 int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
40632 u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
 
 
40633
40634 /* Figure out how much space is required for each journal file-handle
40635 ** (there are two of them, the main journal and the sub-journal). This
40636 ** is the maximum space required for an in-memory journal file handle
40637 ** and a regular journal file-handle. Note that a "regular journal-handle"
@@ -40658,18 +41056,25 @@
40658 /* Compute and store the full pathname in an allocated buffer pointed
40659 ** to by zPathname, length nPathname. Or, if this is a temporary file,
40660 ** leave both nPathname and zPathname set to 0.
40661 */
40662 if( zFilename && zFilename[0] ){
 
40663 nPathname = pVfs->mxPathname+1;
40664 zPathname = sqlite3Malloc(nPathname*2);
40665 if( zPathname==0 ){
40666 return SQLITE_NOMEM;
40667 }
40668 zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
40669 rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
40670 nPathname = sqlite3Strlen30(zPathname);
 
 
 
 
 
 
40671 if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
40672 /* This branch is taken when the journal path required by
40673 ** the database being opened will be more than pVfs->mxPathname
40674 ** bytes in length. This means the database cannot be opened,
40675 ** as it will not be possible to open the journal file or even
@@ -40698,11 +41103,11 @@
40698 pPtr = (u8 *)sqlite3MallocZero(
40699 ROUND8(sizeof(*pPager)) + /* Pager structure */
40700 ROUND8(pcacheSize) + /* PCache object */
40701 ROUND8(pVfs->szOsFile) + /* The main db file */
40702 journalFileSize * 2 + /* The two journal files */
40703 nPathname + 1 + /* zFilename */
40704 nPathname + 8 + 1 /* zJournal */
40705 #ifndef SQLITE_OMIT_WAL
40706 + nPathname + 4 + 1 /* zWal */
40707 #endif
40708 );
@@ -40720,18 +41125,21 @@
40720 assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
40721
40722 /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
40723 if( zPathname ){
40724 assert( nPathname>0 );
40725 pPager->zJournal = (char*)(pPtr += nPathname + 1);
40726 memcpy(pPager->zFilename, zPathname, nPathname);
 
40727 memcpy(pPager->zJournal, zPathname, nPathname);
40728 memcpy(&pPager->zJournal[nPathname], "-journal", 8);
 
40729 #ifndef SQLITE_OMIT_WAL
40730 pPager->zWal = &pPager->zJournal[nPathname+8+1];
40731 memcpy(pPager->zWal, zPathname, nPathname);
40732 memcpy(&pPager->zWal[nPathname], "-wal", 4);
 
40733 #endif
40734 sqlite3_free(zPathname);
40735 }
40736 pPager->pVfs = pVfs;
40737 pPager->vfsFlags = vfsFlags;
@@ -42064,15 +42472,25 @@
42064 */
42065 sqlite3BackupRestart(pPager->pBackup);
42066 }else{
42067 if( pagerUseWal(pPager) ){
42068 PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
42069 if( pList ){
 
 
 
 
 
 
 
 
 
42070 rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1,
42071 (pPager->fullSync ? pPager->syncFlags : 0)
42072 );
42073 }
 
42074 if( rc==SQLITE_OK ){
42075 sqlite3PcacheCleanAll(pPager->pPCache);
42076 }
42077 }else{
42078 /* The following block updates the change-counter. Exactly how it
@@ -42926,10 +43344,11 @@
42926 ** An attempt to set a limit smaller than -1 is a no-op.
42927 */
42928 SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
42929 if( iLimit>=-1 ){
42930 pPager->journalSizeLimit = iLimit;
 
42931 }
42932 return pPager->journalSizeLimit;
42933 }
42934
42935 /*
@@ -43017,11 +43436,12 @@
43017 /* Open the connection to the log file. If this operation fails,
43018 ** (e.g. due to malloc() failure), return an error code.
43019 */
43020 if( rc==SQLITE_OK ){
43021 rc = sqlite3WalOpen(pPager->pVfs,
43022 pPager->fd, pPager->zWal, pPager->exclusiveMode, &pPager->pWal
 
43023 );
43024 }
43025
43026 return rc;
43027 }
@@ -43549,10 +43969,11 @@
43549 struct Wal {
43550 sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
43551 sqlite3_file *pDbFd; /* File handle for the database file */
43552 sqlite3_file *pWalFd; /* File handle for WAL file */
43553 u32 iCallback; /* Value to pass to log callback (or 0) */
 
43554 int nWiData; /* Size of array apWiData */
43555 volatile u32 **apWiData; /* Pointer to wal-index content in memory */
43556 u32 szPage; /* Database page size */
43557 i16 readLock; /* Which read lock is being held. -1 for none */
43558 u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
@@ -44371,10 +44792,11 @@
44371 SQLITE_PRIVATE int sqlite3WalOpen(
44372 sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
44373 sqlite3_file *pDbFd, /* The open database file */
44374 const char *zWalName, /* Name of the WAL file */
44375 int bNoShm, /* True to run in heap-memory mode */
 
44376 Wal **ppWal /* OUT: Allocated Wal handle */
44377 ){
44378 int rc; /* Return Code */
44379 Wal *pRet; /* Object to allocate and return */
44380 int flags; /* Flags passed to OsOpen() */
@@ -44403,10 +44825,11 @@
44403
44404 pRet->pVfs = pVfs;
44405 pRet->pWalFd = (sqlite3_file *)&pRet[1];
44406 pRet->pDbFd = pDbFd;
44407 pRet->readLock = -1;
 
44408 pRet->zWalName = zWalName;
44409 pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
44410
44411 /* Open file handle on the write-ahead log file. */
44412 flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
@@ -44423,10 +44846,17 @@
44423 *ppWal = pRet;
44424 WALTRACE(("WAL%d: opened\n", pRet));
44425 }
44426 return rc;
44427 }
 
 
 
 
 
 
 
44428
44429 /*
44430 ** Find the smallest page number out of all pages held in the WAL that
44431 ** has not been returned by any prior invocation of this method on the
44432 ** same WalIterator object. Write into *piFrame the frame index where
@@ -45659,10 +46089,26 @@
45659 ** safe and means there is no special case for sqlite3WalUndo()
45660 ** to handle if this transaction is rolled back.
45661 */
45662 int i; /* Loop counter */
45663 u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45664 pWal->nCkpt++;
45665 pWal->hdr.mxFrame = 0;
45666 sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
45667 aSalt[1] = salt1;
45668 walIndexWriteHdr(pWal);
@@ -47764,10 +48210,11 @@
47764 offset = PTRMAP_PTROFFSET(iPtrmap, key);
47765 if( offset<0 ){
47766 *pRC = SQLITE_CORRUPT_BKPT;
47767 goto ptrmap_exit;
47768 }
 
47769 pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
47770
47771 if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
47772 TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));
47773 *pRC= rc = sqlite3PagerWrite(pDbPage);
@@ -47803,10 +48250,15 @@
47803 return rc;
47804 }
47805 pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
47806
47807 offset = PTRMAP_PTROFFSET(iPtrmap, key);
 
 
 
 
 
47808 assert( pEType!=0 );
47809 *pEType = pPtrmap[offset];
47810 if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
47811
47812 sqlite3PagerUnref(pDbPage);
@@ -48664,17 +49116,17 @@
48664 ** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
48665 ** objects in the same database connection since doing so will lead
48666 ** to problems with locking.
48667 */
48668 SQLITE_PRIVATE int sqlite3BtreeOpen(
 
48669 const char *zFilename, /* Name of the file containing the BTree database */
48670 sqlite3 *db, /* Associated database handle */
48671 Btree **ppBtree, /* Pointer to new Btree object written here */
48672 int flags, /* Options */
48673 int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */
48674 ){
48675 sqlite3_vfs *pVfs; /* The VFS to use for this btree */
48676 BtShared *pBt = 0; /* Shared part of btree structure */
48677 Btree *p; /* Handle to return */
48678 sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */
48679 int rc = SQLITE_OK; /* Result code from this function */
48680 u8 nReserve; /* Byte of unused space on each page */
@@ -48692,10 +49144,11 @@
48692 const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
48693 || (isTempDb && sqlite3TempInMemory(db));
48694 #endif
48695
48696 assert( db!=0 );
 
48697 assert( sqlite3_mutex_held(db->mutex) );
48698 assert( (flags&0xff)==flags ); /* flags fit in 8 bits */
48699
48700 /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
48701 assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
@@ -48710,11 +49163,10 @@
48710 flags |= BTREE_MEMORY;
48711 }
48712 if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
48713 vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
48714 }
48715 pVfs = db->pVfs;
48716 p = sqlite3MallocZero(sizeof(Btree));
48717 if( !p ){
48718 return SQLITE_NOMEM;
48719 }
48720 p->inTrans = TRANS_NONE;
@@ -58781,10 +59233,11 @@
58781 sqlite3_randomness(sizeof(iRandom), &iRandom);
58782 zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, iRandom&0x7fffffff);
58783 if( !zMaster ){
58784 return SQLITE_NOMEM;
58785 }
 
58786 rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
58787 }while( rc==SQLITE_OK && res );
58788 if( rc==SQLITE_OK ){
58789 /* Open the master journal. */
58790 rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
@@ -58994,10 +59447,19 @@
58994 }
58995 }
58996 }
58997 db->nStatement--;
58998 p->iStatement = 0;
 
 
 
 
 
 
 
 
 
58999
59000 /* If the statement transaction is being rolled back, also restore the
59001 ** database handles deferred constraint counter to the value it had when
59002 ** the statement transaction was opened. */
59003 if( eOp==SAVEPOINT_ROLLBACK ){
@@ -59911,11 +60373,11 @@
59911 /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
59912 VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
59913
59914 /* Compilers may complain that mem1.u.i is potentially uninitialized.
59915 ** We could initialize it, as shown here, to silence those complaints.
59916 ** But in fact, mem1.u.i will never actually be used initialized, and doing
59917 ** the unnecessary initialization has a measurable negative performance
59918 ** impact, since this routine is a very high runner. And so, we choose
59919 ** to ignore the compiler warnings and leave this variable uninitialized.
59920 */
59921 /* mem1.u.i = 0; // not needed, here to silence compiler warning */
@@ -62326,10 +62788,11 @@
62326 Mem *pIn2 = 0; /* 2nd input operand */
62327 Mem *pIn3 = 0; /* 3rd input operand */
62328 Mem *pOut = 0; /* Output operand */
62329 int iCompare = 0; /* Result of last OP_Compare operation */
62330 int *aPermute = 0; /* Permutation of columns for OP_Compare */
 
62331 #ifdef VDBE_PROFILE
62332 u64 start; /* CPU clock count at start of opcode */
62333 int origPc; /* Program counter at start of opcode */
62334 #endif
62335 /********************************************************************
@@ -63004,10 +63467,11 @@
63004 VdbeFrame *pFrame = p->pFrame;
63005 p->pFrame = pFrame->pParent;
63006 p->nFrame--;
63007 sqlite3VdbeSetChanges(db, p->nChange);
63008 pc = sqlite3VdbeFrameRestore(pFrame);
 
63009 if( pOp->p2==OE_Ignore ){
63010 /* Instruction pc is the OP_Program that invoked the sub-program
63011 ** currently being halted. If the p2 instruction of this OP_Halt
63012 ** instruction is set to OE_Ignore, then the sub-program is throwing
63013 ** an IGNORE exception. In this case jump to the address specified
@@ -63576,11 +64040,13 @@
63576 assert( pOp>aOp );
63577 assert( pOp[-1].p4type==P4_COLLSEQ );
63578 assert( pOp[-1].opcode==OP_CollSeq );
63579 u.ag.ctx.pColl = pOp[-1].p4.pColl;
63580 }
 
63581 (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); /* IMP: R-24505-23230 */
 
63582 if( db->mallocFailed ){
63583 /* Even though a malloc() has failed, the implementation of the
63584 ** user function may have called an sqlite3_result_XXX() function
63585 ** to return a value. The following call releases any resources
63586 ** associated with such a value.
@@ -64783,10 +65249,18 @@
64783 "SQL statements in progress");
64784 rc = SQLITE_BUSY;
64785 }else{
64786 u.aq.nName = sqlite3Strlen30(u.aq.zName);
64787
 
 
 
 
 
 
 
 
64788 /* Create a new savepoint structure. */
64789 u.aq.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.aq.nName+1);
64790 if( u.aq.pNew ){
64791 u.aq.pNew->zName = (char *)&u.aq.pNew[1];
64792 memcpy(u.aq.pNew->zName, u.aq.zName, u.aq.nName+1);
@@ -64889,10 +65363,15 @@
64889 db->nSavepoint--;
64890 }
64891 }else{
64892 db->nDeferredCons = u.aq.pSavepoint->nDeferredCons;
64893 }
 
 
 
 
 
64894 }
64895 }
64896
64897 break;
64898 }
@@ -65028,11 +65507,15 @@
65028 if( p->iStatement==0 ){
65029 assert( db->nStatement>=0 && db->nSavepoint>=0 );
65030 db->nStatement++;
65031 p->iStatement = db->nSavepoint + db->nStatement;
65032 }
65033 rc = sqlite3BtreeBeginStmt(u.as.pBt, p->iStatement);
 
 
 
 
65034
65035 /* Store the current value of the database handles deferred constraint
65036 ** counter. If the statement transaction needs to be rolled back,
65037 ** the value of this counter needs to be restored too. */
65038 p->nStmtDefCons = db->nDeferredCons;
@@ -65349,11 +65832,11 @@
65349
65350 assert( pOp->p1>=0 );
65351 u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
65352 if( u.ax.pCx==0 ) goto no_mem;
65353 u.ax.pCx->nullRow = 1;
65354 rc = sqlite3BtreeOpen(0, db, &u.ax.pCx->pBt,
65355 BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
65356 if( rc==SQLITE_OK ){
65357 rc = sqlite3BtreeBeginTrans(u.ax.pCx->pBt, 1);
65358 }
65359 if( rc==SQLITE_OK ){
@@ -66023,11 +66506,11 @@
66023 ** engine starts picking positive candidate ROWIDs at random until
66024 ** it finds one that is not previously used. */
66025 assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
66026 ** an AUTOINCREMENT table. */
66027 /* on the first attempt, simply do one more than previous */
66028 u.be.v = db->lastRowid;
66029 u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
66030 u.be.v++; /* ensure non-zero */
66031 u.be.cnt = 0;
66032 while( ((rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v,
66033 0, &u.be.res))==SQLITE_OK)
@@ -66135,11 +66618,11 @@
66135 assert( pOp->opcode==OP_InsertInt );
66136 u.bf.iKey = pOp->p3;
66137 }
66138
66139 if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
66140 if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = u.bf.iKey;
66141 if( u.bf.pData->flags & MEM_Null ){
66142 u.bf.pData->z = 0;
66143 u.bf.pData->n = 0;
66144 }else{
66145 assert( u.bf.pData->flags & (MEM_Blob|MEM_Str) );
@@ -67261,11 +67744,11 @@
67261 assert( pc==u.by.pFrame->pc );
67262 }
67263
67264 p->nFrame++;
67265 u.by.pFrame->pParent = p->pFrame;
67266 u.by.pFrame->lastRowid = db->lastRowid;
67267 u.by.pFrame->nChange = p->nChange;
67268 p->nChange = 0;
67269 p->pFrame = u.by.pFrame;
67270 p->aMem = aMem = &VdbeFrameMem(u.by.pFrame)[-1];
67271 p->nMem = u.by.pFrame->nChildMem;
@@ -68072,31 +68555,45 @@
68072 sqlite_int64 rowid;
68073 Mem **apArg;
68074 Mem *pX;
68075 #endif /* local variables moved into u.cm */
68076
 
 
 
68077 u.cm.pVtab = pOp->p4.pVtab->pVtab;
68078 u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
68079 u.cm.nArg = pOp->p2;
68080 assert( pOp->p4type==P4_VTAB );
68081 if( ALWAYS(u.cm.pModule->xUpdate) ){
 
68082 u.cm.apArg = p->apArg;
68083 u.cm.pX = &aMem[pOp->p3];
68084 for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){
68085 assert( memIsValid(u.cm.pX) );
68086 memAboutToChange(p, u.cm.pX);
68087 sqlite3VdbeMemStoreType(u.cm.pX);
68088 u.cm.apArg[u.cm.i] = u.cm.pX;
68089 u.cm.pX++;
68090 }
 
68091 rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
 
68092 importVtabErrMsg(p, u.cm.pVtab);
68093 if( rc==SQLITE_OK && pOp->p1 ){
68094 assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) );
68095 db->lastRowid = u.cm.rowid;
68096 }
68097 p->nChange++;
 
 
 
 
 
 
 
 
68098 }
68099 break;
68100 }
68101 #endif /* SQLITE_OMIT_VIRTUALTABLE */
68102
@@ -68242,10 +68739,11 @@
68242
68243 /* This is the only way out of this procedure. We have to
68244 ** release the mutexes on btrees that were acquired at the
68245 ** top. */
68246 vdbe_return:
 
68247 sqlite3VdbeLeave(p);
68248 return rc;
68249
68250 /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
68251 ** is encountered.
@@ -75970,12 +76468,16 @@
75970 int i;
75971 int rc = 0;
75972 sqlite3 *db = sqlite3_context_db_handle(context);
75973 const char *zName;
75974 const char *zFile;
 
 
 
75975 Db *aNew;
75976 char *zErrDyn = 0;
 
75977
75978 UNUSED_PARAMETER(NotUsed);
75979
75980 zFile = (const char *)sqlite3_value_text(argv[0]);
75981 zName = (const char *)sqlite3_value_text(argv[1]);
@@ -76024,12 +76526,22 @@
76024
76025 /* Open the database file. If the btree is successfully opened, use
76026 ** it to obtain the database schema. At this point the schema may
76027 ** or may not be initialised.
76028 */
76029 rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0,
76030 db->openFlags | SQLITE_OPEN_MAIN_DB);
 
 
 
 
 
 
 
 
 
 
76031 db->nDb++;
76032 if( rc==SQLITE_CONSTRAINT ){
76033 rc = SQLITE_ERROR;
76034 zErrDyn = sqlite3MPrintf(db, "database is already attached");
76035 }else if( rc==SQLITE_OK ){
@@ -80139,11 +80651,11 @@
80139 SQLITE_OPEN_CREATE |
80140 SQLITE_OPEN_EXCLUSIVE |
80141 SQLITE_OPEN_DELETEONCLOSE |
80142 SQLITE_OPEN_TEMP_DB;
80143
80144 rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags);
80145 if( rc!=SQLITE_OK ){
80146 sqlite3ErrorMsg(pParse, "unable to open a temporary database "
80147 "file for storing temporary tables");
80148 pParse->rc = rc;
80149 return 1;
@@ -82329,10 +82841,25 @@
82329 UNUSED_PARAMETER2(NotUsed, NotUsed2);
82330 /* IMP: R-24470-31136 This function is an SQL wrapper around the
82331 ** sqlite3_sourceid() C interface. */
82332 sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
82333 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82334
82335 /*
82336 ** Implementation of the sqlite_compileoption_used() function.
82337 ** The result is an integer that identifies if the compiler option
82338 ** was used to build SQLite.
@@ -83097,10 +83624,11 @@
83097 FUNCTION(random, 0, 0, 0, randomFunc ),
83098 FUNCTION(randomblob, 1, 0, 0, randomBlob ),
83099 FUNCTION(nullif, 2, 0, 1, nullifFunc ),
83100 FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
83101 FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
 
83102 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
83103 FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
83104 FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
83105 #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
83106 FUNCTION(quote, 1, 0, 0, quoteFunc ),
@@ -85309,10 +85837,11 @@
85309 #ifndef SQLITE_OMIT_VIRTUALTABLE
85310 if( IsVirtual(pTab) ){
85311 const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
85312 sqlite3VtabMakeWritable(pParse, pTab);
85313 sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
 
85314 sqlite3MayAbort(pParse);
85315 }else
85316 #endif
85317 {
85318 int isReplace; /* Set to true if constraints may cause a replace */
@@ -86073,10 +86602,22 @@
86073 }
86074 #ifndef SQLITE_OMIT_CHECK
86075 if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
86076 return 0; /* Tables have different CHECK constraints. Ticket #2252 */
86077 }
 
 
 
 
 
 
 
 
 
 
 
 
86078 #endif
86079
86080 /* If we get this far, it means either:
86081 **
86082 ** * We can always do the transfer if the table contains an
@@ -87442,11 +87983,11 @@
87442 }
87443
87444 /*
87445 ** Interpret the given string as a boolean value.
87446 */
87447 static u8 getBoolean(const char *z){
87448 return getSafetyLevel(z)&1;
87449 }
87450
87451 /*
87452 ** Interpret the given string as a locking mode value.
@@ -87612,11 +88153,11 @@
87612 /* Foreign key support may not be enabled or disabled while not
87613 ** in auto-commit mode. */
87614 mask &= ~(SQLITE_ForeignKeys);
87615 }
87616
87617 if( getBoolean(zRight) ){
87618 db->flags |= mask;
87619 }else{
87620 db->flags &= ~mask;
87621 }
87622
@@ -87826,11 +88367,11 @@
87826 if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
87827 Btree *pBt = pDb->pBt;
87828 int b = -1;
87829 assert( pBt!=0 );
87830 if( zRight ){
87831 b = getBoolean(zRight);
87832 }
87833 if( pId2->n==0 && b>=0 ){
87834 int ii;
87835 for(ii=0; ii<db->nDb; ii++){
87836 sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
@@ -88426,11 +88967,11 @@
88426 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
88427
88428 #ifndef NDEBUG
88429 if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
88430 if( zRight ){
88431 if( getBoolean(zRight) ){
88432 sqlite3ParserTrace(stderr, "parser: ");
88433 }else{
88434 sqlite3ParserTrace(0, 0);
88435 }
88436 }
@@ -88440,11 +88981,11 @@
88440 /* Reinstall the LIKE and GLOB functions. The variant of LIKE
88441 ** used will be case sensitive or not depending on the RHS.
88442 */
88443 if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
88444 if( zRight ){
88445 sqlite3RegisterLikeFunctions(db, getBoolean(zRight));
88446 }
88447 }else
88448
88449 #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
88450 # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
@@ -94017,16 +94558,18 @@
94017 ** does, then we can assume that it consumes less space on disk and
94018 ** will therefore be cheaper to scan to determine the query result.
94019 ** In this case set iRoot to the root page number of the index b-tree
94020 ** and pKeyInfo to the KeyInfo structure required to navigate the
94021 ** index.
 
 
94022 **
94023 ** In practice the KeyInfo structure will not be used. It is only
94024 ** passed to keep OP_OpenRead happy.
94025 */
94026 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
94027 if( !pBest || pIdx->nColumn<pBest->nColumn ){
94028 pBest = pIdx;
94029 }
94030 }
94031 if( pBest && pBest->nColumn<pTab->nCol ){
94032 iRoot = pBest->tnum;
@@ -95579,11 +96122,12 @@
95579 SrcList *pSrc, /* The virtual table to be modified */
95580 Table *pTab, /* The virtual table */
95581 ExprList *pChanges, /* The columns to change in the UPDATE statement */
95582 Expr *pRowidExpr, /* Expression used to recompute the rowid */
95583 int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
95584 Expr *pWhere /* WHERE clause of the UPDATE statement */
 
95585 );
95586 #endif /* SQLITE_OMIT_VIRTUALTABLE */
95587
95588 /*
95589 ** The most recently coded instruction was an OP_Column to retrieve the
@@ -95823,11 +96367,11 @@
95823
95824 #ifndef SQLITE_OMIT_VIRTUALTABLE
95825 /* Virtual tables must be handled separately */
95826 if( IsVirtual(pTab) ){
95827 updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
95828 pWhere);
95829 pWhere = 0;
95830 pTabList = 0;
95831 goto update_cleanup;
95832 }
95833 #endif
@@ -96153,11 +96697,12 @@
96153 SrcList *pSrc, /* The virtual table to be modified */
96154 Table *pTab, /* The virtual table */
96155 ExprList *pChanges, /* The columns to change in the UPDATE statement */
96156 Expr *pRowid, /* Expression used to recompute the rowid */
96157 int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
96158 Expr *pWhere /* WHERE clause of the UPDATE statement */
 
96159 ){
96160 Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
96161 ExprList *pEList = 0; /* The result set of the SELECT statement */
96162 Select *pSelect = 0; /* The SELECT statement */
96163 Expr *pExpr; /* Temporary expression */
@@ -96210,10 +96755,11 @@
96210 for(i=0; i<pTab->nCol; i++){
96211 sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i);
96212 }
96213 sqlite3VtabMakeWritable(pParse, pTab);
96214 sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
 
96215 sqlite3MayAbort(pParse);
96216 sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1);
96217 sqlite3VdbeJumpHere(v, addr);
96218 sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
96219
@@ -96583,10 +97129,22 @@
96583 *************************************************************************
96584 ** This file contains code used to help implement virtual tables.
96585 */
96586 #ifndef SQLITE_OMIT_VIRTUALTABLE
96587
 
 
 
 
 
 
 
 
 
 
 
 
96588 /*
96589 ** The actual function that does the work of creating a new module.
96590 ** This function implements the sqlite3_create_module() and
96591 ** sqlite3_create_module_v2() interfaces.
96592 */
@@ -96611,17 +97169,17 @@
96611 pMod->pModule = pModule;
96612 pMod->pAux = pAux;
96613 pMod->xDestroy = xDestroy;
96614 pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
96615 if( pDel && pDel->xDestroy ){
 
96616 pDel->xDestroy(pDel->pAux);
96617 }
96618 sqlite3DbFree(db, pDel);
96619 if( pDel==pMod ){
96620 db->mallocFailed = 1;
96621 }
96622 sqlite3ResetInternalSchema(db, -1);
96623 }else if( xDestroy ){
96624 xDestroy(pAux);
96625 }
96626 rc = sqlite3ApiExit(db, SQLITE_OK);
96627 sqlite3_mutex_leave(db->mutex);
@@ -97003,10 +97561,11 @@
97003 Table *pTab,
97004 Module *pMod,
97005 int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
97006 char **pzErr
97007 ){
 
97008 VTable *pVTable;
97009 int rc;
97010 const char *const*azArg = (const char *const*)pTab->azModuleArg;
97011 int nArg = pTab->nModuleArg;
97012 char *zErr = 0;
@@ -97022,16 +97581,18 @@
97022 return SQLITE_NOMEM;
97023 }
97024 pVTable->db = db;
97025 pVTable->pMod = pMod;
97026
97027 assert( !db->pVTab );
 
97028 assert( xConstruct );
97029 db->pVTab = pTab;
97030
97031 /* Invoke the virtual table constructor */
97032 rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
 
97033 if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
97034
97035 if( SQLITE_OK!=rc ){
97036 if( zErr==0 ){
97037 *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
@@ -97043,11 +97604,11 @@
97043 }else if( ALWAYS(pVTable->pVtab) ){
97044 /* Justification of ALWAYS(): A correct vtab constructor must allocate
97045 ** the sqlite3_vtab object if successful. */
97046 pVTable->pVtab->pModule = pMod->pModule;
97047 pVTable->nRef = 1;
97048 if( db->pVTab ){
97049 const char *zFormat = "vtable constructor did not declare schema: %s";
97050 *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
97051 sqlite3VtabUnlock(pVTable);
97052 rc = SQLITE_ERROR;
97053 }else{
@@ -97091,11 +97652,10 @@
97091 }
97092 }
97093 }
97094
97095 sqlite3DbFree(db, zModuleName);
97096 db->pVTab = 0;
97097 return rc;
97098 }
97099
97100 /*
97101 ** This function is invoked by the parser to call the xConnect() method
@@ -97211,12 +97771,11 @@
97211 int rc = SQLITE_OK;
97212 Table *pTab;
97213 char *zErr = 0;
97214
97215 sqlite3_mutex_enter(db->mutex);
97216 pTab = db->pVTab;
97217 if( !pTab ){
97218 sqlite3Error(db, SQLITE_MISUSE, 0);
97219 sqlite3_mutex_leave(db->mutex);
97220 return SQLITE_MISUSE_BKPT;
97221 }
97222 assert( (pTab->tabFlags & TF_Virtual)!=0 );
@@ -97239,11 +97798,11 @@
97239 pTab->aCol = pParse->pNewTable->aCol;
97240 pTab->nCol = pParse->pNewTable->nCol;
97241 pParse->pNewTable->nCol = 0;
97242 pParse->pNewTable->aCol = 0;
97243 }
97244 db->pVTab = 0;
97245 }else{
97246 sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
97247 sqlite3DbFree(db, zErr);
97248 rc = SQLITE_ERROR;
97249 }
@@ -97391,11 +97950,10 @@
97391 pModule = pVTab->pVtab->pModule;
97392
97393 if( pModule->xBegin ){
97394 int i;
97395
97396
97397 /* If pVtab is already in the aVTrans array, return early */
97398 for(i=0; i<db->nVTrans; i++){
97399 if( db->aVTrans[i]==pVTab ){
97400 return SQLITE_OK;
97401 }
@@ -97404,10 +97962,53 @@
97404 /* Invoke the xBegin method */
97405 rc = pModule->xBegin(pVTab->pVtab);
97406 if( rc==SQLITE_OK ){
97407 rc = addToVTrans(db, pVTab);
97408 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97409 }
97410 return rc;
97411 }
97412
97413 /*
@@ -97505,10 +98106,61 @@
97505 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
97506 }else{
97507 pToplevel->db->mallocFailed = 1;
97508 }
97509 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97510
97511 #endif /* SQLITE_OMIT_VIRTUALTABLE */
97512
97513 /************** End of vtab.c ************************************************/
97514 /************** Begin file where.c *******************************************/
@@ -107527,10 +108179,15 @@
107527 typedef void(*LOGFUNC_t)(void*,int,const char*);
107528 sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
107529 sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
107530 break;
107531 }
 
 
 
 
 
107532
107533 default: {
107534 rc = SQLITE_ERROR;
107535 break;
107536 }
@@ -108886,25 +109543,257 @@
108886 }
108887 db->aLimit[limitId] = newLimit;
108888 }
108889 return oldLimit; /* IMP: R-53341-35419 */
108890 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108891
108892 /*
108893 ** This routine does the work of opening a database on behalf of
108894 ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
108895 ** is UTF-8 encoded.
108896 */
108897 static int openDatabase(
108898 const char *zFilename, /* Database filename UTF-8 encoded */
108899 sqlite3 **ppDb, /* OUT: Returned database handle */
108900 unsigned flags, /* Operational flags */
108901 const char *zVfs /* Name of the VFS to use */
108902 ){
108903 sqlite3 *db;
108904 int rc;
108905 int isThreadsafe;
 
 
108906
108907 *ppDb = 0;
108908 #ifndef SQLITE_OMIT_AUTOINIT
108909 rc = sqlite3_initialize();
108910 if( rc ) return rc;
@@ -108924,11 +109813,11 @@
108924 assert( SQLITE_OPEN_READWRITE == 0x02 );
108925 assert( SQLITE_OPEN_CREATE == 0x04 );
108926 testcase( (1<<(flags&7))==0x02 ); /* READONLY */
108927 testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
108928 testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
108929 if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE;
108930
108931 if( sqlite3GlobalConfig.bCoreMutex==0 ){
108932 isThreadsafe = 0;
108933 }else if( flags & SQLITE_OPEN_NOMUTEX ){
108934 isThreadsafe = 0;
@@ -109005,17 +109894,10 @@
109005 sqlite3HashInit(&db->aCollSeq);
109006 #ifndef SQLITE_OMIT_VIRTUALTABLE
109007 sqlite3HashInit(&db->aModule);
109008 #endif
109009
109010 db->pVfs = sqlite3_vfs_find(zVfs);
109011 if( !db->pVfs ){
109012 rc = SQLITE_ERROR;
109013 sqlite3Error(db, rc, "no such vfs: %s", zVfs);
109014 goto opendb_out;
109015 }
109016
109017 /* Add the default collation sequence BINARY. BINARY works for both UTF-8
109018 ** and UTF-16, so add a version for each to avoid any unnecessary
109019 ** conversions. The only error that can occur here is a malloc() failure.
109020 */
109021 createCollation(db, "BINARY", SQLITE_UTF8, SQLITE_COLL_BINARY, 0,
@@ -109034,13 +109916,22 @@
109034
109035 /* Also add a UTF-8 case-insensitive collation sequence. */
109036 createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
109037 nocaseCollatingFunc, 0);
109038
109039 /* Open the backend database driver */
109040 db->openFlags = flags;
109041 rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0,
 
 
 
 
 
 
 
 
 
109042 flags | SQLITE_OPEN_MAIN_DB);
109043 if( rc!=SQLITE_OK ){
109044 if( rc==SQLITE_IOERR_NOMEM ){
109045 rc = SQLITE_NOMEM;
109046 }
@@ -109129,10 +110020,11 @@
109129 sqlite3GlobalConfig.nLookaside);
109130
109131 sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
109132
109133 opendb_out:
 
109134 if( db ){
109135 assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
109136 sqlite3_mutex_leave(db->mutex);
109137 }
109138 rc = sqlite3_errcode(db);
@@ -109160,11 +110052,11 @@
109160 const char *filename, /* Database filename (UTF-8) */
109161 sqlite3 **ppDb, /* OUT: SQLite db handle */
109162 int flags, /* Flags */
109163 const char *zVfs /* Name of VFS module to use */
109164 ){
109165 return openDatabase(filename, ppDb, flags, zVfs);
109166 }
109167
109168 #ifndef SQLITE_OMIT_UTF16
109169 /*
109170 ** Open a new database handle.
@@ -109770,10 +110662,32 @@
109770 }
109771 va_end(ap);
109772 #endif /* SQLITE_OMIT_BUILTIN_TEST */
109773 return rc;
109774 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109775
109776 /************** End of main.c ************************************************/
109777 /************** Begin file notify.c ******************************************/
109778 /*
109779 ** 2009 March 3
@@ -110851,10 +111765,11 @@
110851 Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
110852 sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
110853 char *pNextId; /* Pointer into the body of aDoclist */
110854 char *aDoclist; /* List of docids for full-text queries */
110855 int nDoclist; /* Size of buffer at aDoclist */
 
110856 int eEvalmode; /* An FTS3_EVAL_XX constant */
110857 int nRowAvg; /* Average size of database rows, in pages */
110858
110859 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
110860 u32 *aMatchinfo; /* Information about most recent match */
@@ -111033,11 +111948,11 @@
111033 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
111034 SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
111035 SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
111036 SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
111037
111038 SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int);
111039 SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *, Fts3Expr *);
111040 SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(Fts3Cursor *, Fts3Expr *, char **, int *);
111041 SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
111042
111043 /* fts3_tokenizer.c */
@@ -111060,10 +111975,11 @@
111060 char **, int, int, const char *, int, Fts3Expr **
111061 );
111062 SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
111063 #ifdef SQLITE_TEST
111064 SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
 
111065 #endif
111066
111067 /* fts3_aux.c */
111068 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
111069
@@ -111180,10 +112096,38 @@
111180 static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
111181 sqlite3_int64 iVal;
111182 *pp += sqlite3Fts3GetVarint(*pp, &iVal);
111183 *pVal += iVal;
111184 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111185
111186 /*
111187 ** As long as *pp has not reached its end (pEnd), then do the same
111188 ** as fts3GetDeltaVarint(): read a single varint and add it to *pVal.
111189 ** But if we have reached the end of the varint, just set *pp=0 and
@@ -111285,10 +112229,12 @@
111285 if( *pRc==SQLITE_OK ){
111286 int i; /* Iterator variable */
111287 int rc; /* Return code */
111288 char *zSql; /* SQL statement passed to declare_vtab() */
111289 char *zCols; /* List of user defined columns */
 
 
111290
111291 /* Create a list of user columns for the virtual table */
111292 zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
111293 for(i=1; zCols && i<p->nColumn; i++){
111294 zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
@@ -111854,10 +112800,26 @@
111854
111855 if( iCons>=0 ){
111856 pInfo->aConstraintUsage[iCons].argvIndex = 1;
111857 pInfo->aConstraintUsage[iCons].omit = 1;
111858 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111859 return SQLITE_OK;
111860 }
111861
111862 /*
111863 ** Implementation of xOpen method.
@@ -111911,11 +112873,11 @@
111911 if( rc==SQLITE_OK ){
111912 /* If no row was found and no error has occured, then the %_content
111913 ** table is missing a row that is present in the full-text index.
111914 ** The data structures are corrupt.
111915 */
111916 rc = SQLITE_CORRUPT;
111917 }
111918 pCsr->isEof = 1;
111919 if( pContext ){
111920 sqlite3_result_error_code(pContext, rc);
111921 }
@@ -111971,11 +112933,11 @@
111971 ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
111972 */
111973 zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
111974 zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
111975 if( zCsr>zEnd ){
111976 return SQLITE_CORRUPT;
111977 }
111978
111979 while( zCsr<zEnd && (piFirst || piLast) ){
111980 int cmp; /* memcmp() result */
111981 int nSuffix; /* Size of term suffix */
@@ -111989,11 +112951,11 @@
111989 }
111990 isFirstTerm = 0;
111991 zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
111992
111993 if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
111994 rc = SQLITE_CORRUPT;
111995 goto finish_scan;
111996 }
111997 if( nPrefix+nSuffix>nAlloc ){
111998 char *zNew;
111999 nAlloc = (nPrefix+nSuffix) * 2;
@@ -113758,16 +114720,24 @@
113758 rc = sqlite3_reset(pCsr->pStmt);
113759 break;
113760 }
113761 pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
113762 }else{
113763 if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
113764 pCsr->isEof = 1;
113765 break;
 
 
 
 
 
 
 
 
 
113766 }
113767 sqlite3_reset(pCsr->pStmt);
113768 fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
113769 pCsr->isRequireSeek = 1;
113770 pCsr->isMatchinfoNeeded = 1;
113771 }
113772 }while( SQLITE_OK==(rc = fts3EvalDeferred(pCsr, &res)) && res==0 );
113773
@@ -113796,12 +114766,12 @@
113796 const char *idxStr, /* Unused */
113797 int nVal, /* Number of elements in apVal */
113798 sqlite3_value **apVal /* Arguments for the indexing scheme */
113799 ){
113800 const char *azSql[] = {
113801 "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?", /* non-full-scan */
113802 "SELECT %s FROM %Q.'%q_content' AS x ", /* full-scan */
113803 };
113804 int rc; /* Return code */
113805 char *zSql; /* SQL statement used to access %_content */
113806 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
113807 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
@@ -113853,11 +114823,13 @@
113853 ** statement loops through all rows of the %_content table. For a
113854 ** full-text query or docid lookup, the statement retrieves a single
113855 ** row by docid.
113856 */
113857 zSql = (char *)azSql[idxNum==FTS3_FULLSCAN_SEARCH];
113858 zSql = sqlite3_mprintf(zSql, p->zReadExprlist, p->zDb, p->zName);
 
 
113859 if( !zSql ){
113860 rc = SQLITE_NOMEM;
113861 }else{
113862 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
113863 sqlite3_free(zSql);
@@ -113865,11 +114837,26 @@
113865 if( rc==SQLITE_OK && idxNum==FTS3_DOCID_SEARCH ){
113866 rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
113867 }
113868 pCsr->eSearch = (i16)idxNum;
113869
 
113870 if( rc!=SQLITE_OK ) return rc;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113871 return fts3NextMethod(pCursor);
113872 }
113873
113874 /*
113875 ** This is the xEof method of the virtual table. SQLite calls this
@@ -114017,17 +115004,37 @@
114017 pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
114018 rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
114019 pCsr->eEvalmode = FTS3_EVAL_NEXT;
114020 return rc;
114021 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114022
114023 /*
114024 ** After ExprLoadDoclist() (see above) has been called, this function is
114025 ** used to iterate/search through the position lists that make up the doclist
114026 ** stored in pExpr->aDoclist.
114027 */
114028 SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
 
114029 Fts3Expr *pExpr, /* Access this expressions doclist */
114030 sqlite3_int64 iDocid, /* Docid associated with requested pos-list */
114031 int iCol /* Column of requested pos-list */
114032 ){
114033 assert( pExpr->isLoaded );
@@ -114034,23 +115041,39 @@
114034 if( pExpr->aDoclist ){
114035 char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
114036 char *pCsr;
114037
114038 if( pExpr->pCurrent==0 ){
114039 pExpr->pCurrent = pExpr->aDoclist;
114040 pExpr->iCurrent = 0;
114041 pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent);
 
 
 
 
 
 
 
 
 
 
114042 }
114043 pCsr = pExpr->pCurrent;
114044 assert( pCsr );
114045
114046 while( pCsr<pEnd ){
114047 if( pExpr->iCurrent<iDocid ){
 
 
114048 fts3PoslistCopy(0, &pCsr);
114049 if( pCsr<pEnd ){
114050 fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
114051 }
 
 
 
 
114052 pExpr->pCurrent = pCsr;
114053 }else{
114054 if( pExpr->iCurrent==iDocid ){
114055 int iThis = 0;
114056 if( iCol<0 ){
@@ -114303,13 +115326,24 @@
114303 "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';",
114304 p->zDb, p->zName, zName
114305 );
114306 return rc;
114307 }
 
 
 
 
 
 
 
 
 
 
 
114308
114309 static const sqlite3_module fts3Module = {
114310 /* iVersion */ 0,
114311 /* xCreate */ fts3CreateMethod,
114312 /* xConnect */ fts3ConnectMethod,
114313 /* xBestIndex */ fts3BestIndexMethod,
114314 /* xDisconnect */ fts3DisconnectMethod,
114315 /* xDestroy */ fts3DestroyMethod,
@@ -114325,10 +115359,13 @@
114325 /* xSync */ fts3SyncMethod,
114326 /* xCommit */ fts3CommitMethod,
114327 /* xRollback */ fts3RollbackMethod,
114328 /* xFindFunction */ fts3FindFunctionMethod,
114329 /* xRename */ fts3RenameMethod,
 
 
 
114330 };
114331
114332 /*
114333 ** This function is registered as the module destructor (called when an
114334 ** FTS3 enabled database connection is closed). It frees the memory
@@ -114370,10 +115407,15 @@
114370
114371 #ifdef SQLITE_ENABLE_ICU
114372 const sqlite3_tokenizer_module *pIcu = 0;
114373 sqlite3Fts3IcuTokenizerModule(&pIcu);
114374 #endif
 
 
 
 
 
114375
114376 rc = sqlite3Fts3InitAux(db);
114377 if( rc!=SQLITE_OK ) return rc;
114378
114379 sqlite3Fts3SimpleTokenizerModule(&pSimple);
@@ -117891,11 +118933,11 @@
117891 sqlite3_bind_int64(pStmt, 1, iDocid);
117892 }
117893 rc = sqlite3_step(pStmt);
117894 if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
117895 rc = sqlite3_reset(pStmt);
117896 if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT;
117897 pStmt = 0;
117898 }else{
117899 rc = SQLITE_OK;
117900 }
117901 }
@@ -118141,10 +119183,18 @@
118141 sqlite3_tokenizer_cursor *pCsr;
118142 int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
118143 const char**,int*,int*,int*,int*);
118144
118145 assert( pTokenizer && pModule );
 
 
 
 
 
 
 
 
118146
118147 rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr);
118148 if( rc!=SQLITE_OK ){
118149 return rc;
118150 }
@@ -118232,15 +119282,13 @@
118232 */
118233 static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
118234 int i; /* Iterator variable */
118235 for(i=2; i<p->nColumn+2; i++){
118236 const char *zText = (const char *)sqlite3_value_text(apVal[i]);
118237 if( zText ){
118238 int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
118239 if( rc!=SQLITE_OK ){
118240 return rc;
118241 }
118242 }
118243 aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
118244 }
118245 return SQLITE_OK;
118246 }
@@ -118341,18 +119389,18 @@
118341 ** full-text index.
118342 */
118343 static void fts3DeleteTerms(
118344 int *pRC, /* Result code */
118345 Fts3Table *p, /* The FTS table to delete from */
118346 sqlite3_value **apVal, /* apVal[] contains the docid to be deleted */
118347 u32 *aSz /* Sizes of deleted document written here */
118348 ){
118349 int rc;
118350 sqlite3_stmt *pSelect;
118351
118352 if( *pRC ) return;
118353 rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal);
118354 if( rc==SQLITE_OK ){
118355 if( SQLITE_ROW==sqlite3_step(pSelect) ){
118356 int i;
118357 for(i=1; i<=p->nColumn; i++){
118358 const char *zText = (const char *)sqlite3_column_text(pSelect, i);
@@ -118566,11 +119614,11 @@
118566 pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
118567 pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
118568 if( nPrefix<0 || nSuffix<=0
118569 || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
118570 ){
118571 return SQLITE_CORRUPT;
118572 }
118573
118574 if( nPrefix+nSuffix>pReader->nTermAlloc ){
118575 int nNew = (nPrefix+nSuffix)*2;
118576 char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
@@ -118592,11 +119640,11 @@
118592 ** of these statements is untrue, then the data structure is corrupt.
118593 */
118594 if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
118595 || pReader->aDoclist[pReader->nDoclist-1]
118596 ){
118597 return SQLITE_CORRUPT;
118598 }
118599 return SQLITE_OK;
118600 }
118601
118602 /*
@@ -118717,11 +119765,11 @@
118717 while( a<pEnd ){
118718 a += sqlite3Fts3GetVarint(a, &nByte);
118719 }
118720 if( nDoc==0 || nByte==0 ){
118721 sqlite3_reset(pStmt);
118722 return SQLITE_CORRUPT;
118723 }
118724
118725 pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
118726 assert( pCsr->nRowAvg>0 );
118727 rc = sqlite3_reset(pStmt);
@@ -119488,20 +120536,20 @@
119488
119489 /*
119490 ** The first value in the apVal[] array is assumed to contain an integer.
119491 ** This function tests if there exist any documents with docid values that
119492 ** are different from that integer. i.e. if deleting the document with docid
119493 ** apVal[0] would mean the FTS3 table were empty.
119494 **
119495 ** If successful, *pisEmpty is set to true if the table is empty except for
119496 ** document apVal[0], or false otherwise, and SQLITE_OK is returned. If an
119497 ** error occurs, an SQLite error code is returned.
119498 */
119499 static int fts3IsEmpty(Fts3Table *p, sqlite3_value **apVal, int *pisEmpty){
119500 sqlite3_stmt *pStmt;
119501 int rc;
119502 rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, apVal);
119503 if( rc==SQLITE_OK ){
119504 if( SQLITE_ROW==sqlite3_step(pStmt) ){
119505 *pisEmpty = sqlite3_column_int(pStmt, 0);
119506 }
119507 rc = sqlite3_reset(pStmt);
@@ -120221,10 +121269,44 @@
120221 pToken->pDeferred = pDeferred;
120222
120223 return SQLITE_OK;
120224 }
120225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120226
120227 /*
120228 ** This function does the work for the xUpdate method of FTS3 virtual
120229 ** tables.
120230 */
@@ -120239,50 +121321,95 @@
120239 int isRemove = 0; /* True for an UPDATE or DELETE */
120240 sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
120241 u32 *aSzIns; /* Sizes of inserted documents */
120242 u32 *aSzDel; /* Sizes of deleted documents */
120243 int nChng = 0; /* Net change in number of documents */
 
120244
120245 assert( p->pSegments==0 );
 
 
 
 
 
 
 
 
 
 
 
120246
120247 /* Allocate space to hold the change in document sizes */
120248 aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
120249 if( aSzIns==0 ) return SQLITE_NOMEM;
120250 aSzDel = &aSzIns[p->nColumn+1];
120251 memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120252
120253 /* If this is a DELETE or UPDATE operation, remove the old record. */
120254 if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
120255 int isEmpty = 0;
120256 rc = fts3IsEmpty(p, apVal, &isEmpty);
120257 if( rc==SQLITE_OK ){
120258 if( isEmpty ){
120259 /* Deleting this row means the whole table is empty. In this case
120260 ** delete the contents of all three tables and throw away any
120261 ** data in the pendingTerms hash table.
120262 */
120263 rc = fts3DeleteAll(p);
120264 }else{
120265 isRemove = 1;
120266 iRemove = sqlite3_value_int64(apVal[0]);
120267 rc = fts3PendingTermsDocid(p, iRemove);
120268 fts3DeleteTerms(&rc, p, apVal, aSzDel);
120269 fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal);
120270 if( p->bHasDocsize ){
120271 fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal);
120272 }
120273 nChng--;
120274 }
120275 }
120276 }else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){
120277 sqlite3_free(aSzIns);
120278 return fts3SpecialInsert(p, apVal[p->nColumn+2]);
120279 }
120280
120281 /* If this is an INSERT or UPDATE operation, insert the new record. */
120282 if( nArg>1 && rc==SQLITE_OK ){
120283 rc = fts3InsertData(p, apVal, pRowid);
 
 
 
120284 if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
120285 rc = fts3PendingTermsDocid(p, *pRowid);
120286 }
120287 if( rc==SQLITE_OK ){
120288 rc = fts3InsertTerms(p, apVal, aSzIns);
@@ -120742,11 +121869,11 @@
120742 SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
120743 char *pCsr;
120744
120745 pPhrase->nToken = pExpr->pPhrase->nToken;
120746
120747 pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol);
120748 if( pCsr ){
120749 int iFirst = 0;
120750 pPhrase->pList = pCsr;
120751 fts3GetDeltaPosition(&pCsr, &iFirst);
120752 pPhrase->pHead = pCsr;
@@ -121215,11 +122342,11 @@
121215 for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0;
121216
121217 if( pExpr->aDoclist ){
121218 char *pCsr;
121219
121220 pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1);
121221 if( pCsr ){
121222 fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0);
121223 }
121224 }
121225
@@ -121287,11 +122414,11 @@
121287 pStmt = *ppStmt;
121288 assert( sqlite3_data_count(pStmt)==1 );
121289
121290 a = sqlite3_column_blob(pStmt, 0);
121291 a += sqlite3Fts3GetVarint(a, &nDoc);
121292 if( nDoc==0 ) return SQLITE_CORRUPT;
121293 *pnDoc = (u32)nDoc;
121294
121295 if( paLen ) *paLen = a;
121296 return SQLITE_OK;
121297 }
@@ -121382,11 +122509,11 @@
121382 (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
121383 for(i=0; i<pInfo->nPhrase; i++){
121384 LcsIterator *pIter = &aIter[i];
121385 nToken -= pIter->pExpr->pPhrase->nToken;
121386 pIter->iPosOffset = nToken;
121387 pIter->pRead = sqlite3Fts3FindPositions(pIter->pExpr, pCsr->iPrevId, -1);
121388 if( pIter->pRead ){
121389 pIter->iPos = pIter->iPosOffset;
121390 fts3LcsIteratorAdvance(&aIter[i]);
121391 }else{
121392 pIter->iCol = LCS_ITERATOR_FINISHED;
@@ -121735,10 +122862,11 @@
121735 int iPos; /* Position just read from pList */
121736 int iOff; /* Offset of this term from read positions */
121737 };
121738
121739 struct TermOffsetCtx {
 
121740 int iCol; /* Column of table to populate aTerm for */
121741 int iTerm;
121742 sqlite3_int64 iDocid;
121743 TermOffset *aTerm;
121744 };
@@ -121752,11 +122880,11 @@
121752 int iTerm; /* For looping through nTerm phrase terms */
121753 char *pList; /* Pointer to position list for phrase */
121754 int iPos = 0; /* First position in position-list */
121755
121756 UNUSED_PARAMETER(iPhrase);
121757 pList = sqlite3Fts3FindPositions(pExpr, p->iDocid, p->iCol);
121758 nTerm = pExpr->pPhrase->nToken;
121759 if( pList ){
121760 fts3GetDeltaPosition(&pList, &iPos);
121761 assert( iPos>=0 );
121762 }
@@ -121805,10 +122933,11 @@
121805 if( 0==sCtx.aTerm ){
121806 rc = SQLITE_NOMEM;
121807 goto offsets_out;
121808 }
121809 sCtx.iDocid = pCsr->iPrevId;
 
121810
121811 /* Loop through the table columns, appending offset information to
121812 ** string-buffer res for each column.
121813 */
121814 for(iCol=0; iCol<pTab->nColumn; iCol++){
@@ -121880,11 +123009,11 @@
121880 sqlite3_snprintf(sizeof(aBuffer), aBuffer,
121881 "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
121882 );
121883 rc = fts3StringAppend(&res, aBuffer, -1);
121884 }else if( rc==SQLITE_DONE ){
121885 rc = SQLITE_CORRUPT;
121886 }
121887 }
121888 }
121889 if( rc==SQLITE_DONE ){
121890 rc = SQLITE_OK;
@@ -122468,29 +123597,29 @@
122468 ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
122469 */
122470 if( pNode && iNode==1 ){
122471 pRtree->iDepth = readInt16(pNode->zData);
122472 if( pRtree->iDepth>RTREE_MAX_DEPTH ){
122473 rc = SQLITE_CORRUPT;
122474 }
122475 }
122476
122477 /* If no error has occurred so far, check if the "number of entries"
122478 ** field on the node is too large. If so, set the return code to
122479 ** SQLITE_CORRUPT.
122480 */
122481 if( pNode && rc==SQLITE_OK ){
122482 if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
122483 rc = SQLITE_CORRUPT;
122484 }
122485 }
122486
122487 if( rc==SQLITE_OK ){
122488 if( pNode!=0 ){
122489 nodeHashInsert(pRtree, pNode);
122490 }else{
122491 rc = SQLITE_CORRUPT;
122492 }
122493 *ppNode = pNode;
122494 }else{
122495 sqlite3_free(pNode);
122496 *ppNode = 0;
@@ -123013,11 +124142,11 @@
123013 if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
123014 *piIndex = ii;
123015 return SQLITE_OK;
123016 }
123017 }
123018 return SQLITE_CORRUPT;
123019 }
123020
123021 /*
123022 ** Return the index of the cell containing a pointer to node pNode
123023 ** in its parent. If pNode is the root node, return -1.
@@ -123608,11 +124737,11 @@
123608 RtreeNode *pParent = p->pParent;
123609 RtreeCell cell;
123610 int iCell;
123611
123612 if( nodeParentIndex(pRtree, p, &iCell) ){
123613 return SQLITE_CORRUPT;
123614 }
123615
123616 nodeGetCell(pRtree, pParent, iCell, &cell);
123617 if( !cellContains(pRtree, &cell, pCell) ){
123618 cellUnion(pRtree, &cell, pCell);
@@ -124280,11 +125409,11 @@
124280 rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
124281 }
124282 }
124283 rc = sqlite3_reset(pRtree->pReadParent);
124284 if( rc==SQLITE_OK ) rc = rc2;
124285 if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT;
124286 pChild = pChild->pParent;
124287 }
124288 return rc;
124289 }
124290
@@ -124575,10 +125704,94 @@
124575 sqlite3_step(pRtree->pWriteRowid);
124576 rc = sqlite3_reset(pRtree->pWriteRowid);
124577 *piRowid = sqlite3_last_insert_rowid(pRtree->db);
124578 return rc;
124579 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124580
124581 /*
124582 ** The xUpdate method for rtree module virtual tables.
124583 */
124584 static int rtreeUpdate(
@@ -124587,107 +125800,29 @@
124587 sqlite3_value **azData,
124588 sqlite_int64 *pRowid
124589 ){
124590 Rtree *pRtree = (Rtree *)pVtab;
124591 int rc = SQLITE_OK;
 
 
124592
124593 rtreeReference(pRtree);
124594
124595 assert(nData>=1);
124596
124597 /* If azData[0] is not an SQL NULL value, it is the rowid of a
124598 ** record to delete from the r-tree table. The following block does
124599 ** just that.
124600 */
124601 if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
124602 i64 iDelete; /* The rowid to delete */
124603 RtreeNode *pLeaf; /* Leaf node containing record iDelete */
124604 int iCell; /* Index of iDelete cell in pLeaf */
124605 RtreeNode *pRoot;
124606
124607 /* Obtain a reference to the root node to initialise Rtree.iDepth */
124608 rc = nodeAcquire(pRtree, 1, 0, &pRoot);
124609
124610 /* Obtain a reference to the leaf node that contains the entry
124611 ** about to be deleted.
124612 */
124613 if( rc==SQLITE_OK ){
124614 iDelete = sqlite3_value_int64(azData[0]);
124615 rc = findLeafNode(pRtree, iDelete, &pLeaf);
124616 }
124617
124618 /* Delete the cell in question from the leaf node. */
124619 if( rc==SQLITE_OK ){
124620 int rc2;
124621 rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
124622 if( rc==SQLITE_OK ){
124623 rc = deleteCell(pRtree, pLeaf, iCell, 0);
124624 }
124625 rc2 = nodeRelease(pRtree, pLeaf);
124626 if( rc==SQLITE_OK ){
124627 rc = rc2;
124628 }
124629 }
124630
124631 /* Delete the corresponding entry in the <rtree>_rowid table. */
124632 if( rc==SQLITE_OK ){
124633 sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
124634 sqlite3_step(pRtree->pDeleteRowid);
124635 rc = sqlite3_reset(pRtree->pDeleteRowid);
124636 }
124637
124638 /* Check if the root node now has exactly one child. If so, remove
124639 ** it, schedule the contents of the child for reinsertion and
124640 ** reduce the tree height by one.
124641 **
124642 ** This is equivalent to copying the contents of the child into
124643 ** the root node (the operation that Gutman's paper says to perform
124644 ** in this scenario).
124645 */
124646 if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
124647 int rc2;
124648 RtreeNode *pChild;
124649 i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
124650 rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
124651 if( rc==SQLITE_OK ){
124652 rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
124653 }
124654 rc2 = nodeRelease(pRtree, pChild);
124655 if( rc==SQLITE_OK ) rc = rc2;
124656 if( rc==SQLITE_OK ){
124657 pRtree->iDepth--;
124658 writeInt16(pRoot->zData, pRtree->iDepth);
124659 pRoot->isDirty = 1;
124660 }
124661 }
124662
124663 /* Re-insert the contents of any underfull nodes removed from the tree. */
124664 for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
124665 if( rc==SQLITE_OK ){
124666 rc = reinsertNodeContent(pRtree, pLeaf);
124667 }
124668 pRtree->pDeleted = pLeaf->pNext;
124669 sqlite3_free(pLeaf);
124670 }
124671
124672 /* Release the reference to the root node. */
124673 if( rc==SQLITE_OK ){
124674 rc = nodeRelease(pRtree, pRoot);
124675 }else{
124676 nodeRelease(pRtree, pRoot);
124677 }
124678 }
124679
124680 /* If the azData[] array contains more than one element, elements
124681 ** (azData[2]..azData[argc-1]) contain a new record to insert into
124682 ** the r-tree structure.
124683 */
124684 if( rc==SQLITE_OK && nData>1 ){
124685 /* Insert a new record into the r-tree */
124686 RtreeCell cell;
124687 int ii;
124688 RtreeNode *pLeaf;
124689
124690 /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
124691 assert( nData==(pRtree->nDim*2 + 3) );
124692 if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
124693 for(ii=0; ii<(pRtree->nDim*2); ii+=2){
@@ -124707,22 +125842,53 @@
124707 goto constraint;
124708 }
124709 }
124710 }
124711
124712 /* Figure out the rowid of the new row. */
124713 if( sqlite3_value_type(azData[2])==SQLITE_NULL ){
124714 rc = newRowid(pRtree, &cell.iRowid);
124715 }else{
124716 cell.iRowid = sqlite3_value_int64(azData[2]);
124717 sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
124718 if( SQLITE_ROW==sqlite3_step(pRtree->pReadRowid) ){
124719 sqlite3_reset(pRtree->pReadRowid);
124720 rc = SQLITE_CONSTRAINT;
124721 goto constraint;
 
 
 
 
 
 
 
 
 
 
124722 }
124723 rc = sqlite3_reset(pRtree->pReadRowid);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124724 }
124725 *pRowid = cell.iRowid;
124726
124727 if( rc==SQLITE_OK ){
124728 rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf);
@@ -124958,10 +126124,12 @@
124958 int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
124959 if( aErrMsg[iErr] ){
124960 *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
124961 return SQLITE_ERROR;
124962 }
 
 
124963
124964 /* Allocate the sqlite3_vtab structure */
124965 nDb = strlen(argv[1]);
124966 nName = strlen(argv[2]);
124967 pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
124968
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.7.7. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -648,13 +648,13 @@
648 **
649 ** See also: [sqlite3_libversion()],
650 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
651 ** [sqlite_version()] and [sqlite_source_id()].
652 */
653 #define SQLITE_VERSION "3.7.7"
654 #define SQLITE_VERSION_NUMBER 3007007
655 #define SQLITE_SOURCE_ID "2011-05-20 01:50:01 2018d4e108872f2436df046636401b89cfde589d"
656
657 /*
658 ** CAPI3REF: Run-Time Library Version Numbers
659 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
660 **
@@ -916,11 +916,12 @@
916 ** Many SQLite functions return an integer result code from the set shown
917 ** here in order to indicates success or failure.
918 **
919 ** New error codes may be added in future versions of SQLite.
920 **
921 ** See also: [SQLITE_IOERR_READ | extended result codes],
922 ** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
923 */
924 #define SQLITE_OK 0 /* Successful result */
925 /* beginning-of-error-codes */
926 #define SQLITE_ERROR 1 /* SQL error or missing database */
927 #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -993,28 +994,31 @@
994 #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
995 #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
996 #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
997 #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
998 #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
999 #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
1000 #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
1001 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
1002 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
1003 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
1004 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
1005
1006 /*
1007 ** CAPI3REF: Flags For File Open Operations
1008 **
1009 ** These bit values are intended for use in the
1010 ** 3rd parameter to the [sqlite3_open_v2()] interface and
1011 ** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
 
1012 */
1013 #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
1014 #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
1015 #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
1016 #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
1017 #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
1018 #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
1019 #define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
1020 #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
1021 #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
1022 #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
1023 #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
1024 #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
@@ -1121,21 +1125,22 @@
1125 };
1126
1127 /*
1128 ** CAPI3REF: OS Interface File Virtual Methods Object
1129 **
1130 ** Every file opened by the [sqlite3_vfs.xOpen] method populates an
1131 ** [sqlite3_file] object (or, more commonly, a subclass of the
1132 ** [sqlite3_file] object) with a pointer to an instance of this object.
1133 ** This object defines the methods used to perform various operations
1134 ** against the open file represented by the [sqlite3_file] object.
1135 **
1136 ** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
1137 ** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
1138 ** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
1139 ** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
1140 ** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
1141 ** to NULL.
1142 **
1143 ** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
1144 ** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
1145 ** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
1146 ** flag may be ORed in to indicate that only the data of the file
@@ -1300,10 +1305,11 @@
1305 */
1306 typedef struct sqlite3_mutex sqlite3_mutex;
1307
1308 /*
1309 ** CAPI3REF: OS Interface Object
1310 ** KEYWORDS: VFS VFSes
1311 **
1312 ** An instance of the sqlite3_vfs object defines the interface between
1313 ** the SQLite core and the underlying operating system. The "vfs"
1314 ** in the name of the object stands for "virtual file system".
1315 **
@@ -1332,10 +1338,11 @@
1338 ** object once the object has been registered.
1339 **
1340 ** The zName field holds the name of the VFS module. The name must
1341 ** be unique across all VFS modules.
1342 **
1343 ** [[sqlite3_vfs.xOpen]]
1344 ** ^SQLite guarantees that the zFilename parameter to xOpen
1345 ** is either a NULL pointer or string obtained
1346 ** from xFullPathname() with an optional suffix added.
1347 ** ^If a suffix is added to the zFilename parameter, it will
1348 ** consist of a single "-" character followed by no more than
@@ -1409,10 +1416,11 @@
1416 ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
1417 ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
1418 ** element will be valid after xOpen returns regardless of the success
1419 ** or failure of the xOpen call.
1420 **
1421 ** [[sqlite3_vfs.xAccess]]
1422 ** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
1423 ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
1424 ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
1425 ** to test whether a file is at least readable. The file can be a
1426 ** directory.
@@ -1655,13 +1663,13 @@
1663 ** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
1664 ** Note, however, that ^sqlite3_config() can be called as part of the
1665 ** implementation of an application-defined [sqlite3_os_init()].
1666 **
1667 ** The first argument to sqlite3_config() is an integer
1668 ** [configuration option] that determines
1669 ** what property of SQLite is to be configured. Subsequent arguments
1670 ** vary depending on the [configuration option]
1671 ** in the first argument.
1672 **
1673 ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
1674 ** ^If the option is unknown or SQLite is unable to set the option
1675 ** then this routine returns a non-zero [error code].
@@ -1767,10 +1775,11 @@
1775 void *pAppData; /* Argument to xInit() and xShutdown() */
1776 };
1777
1778 /*
1779 ** CAPI3REF: Configuration Options
1780 ** KEYWORDS: {configuration option}
1781 **
1782 ** These constants are the available integer configuration options that
1783 ** can be passed as the first argument to the [sqlite3_config()] interface.
1784 **
1785 ** New configuration options may be added in future releases of SQLite.
@@ -1779,11 +1788,11 @@
1788 ** the call worked. The [sqlite3_config()] interface will return a
1789 ** non-zero [error code] if a discontinued or unsupported configuration option
1790 ** is invoked.
1791 **
1792 ** <dl>
1793 ** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
1794 ** <dd>There are no arguments to this option. ^This option sets the
1795 ** [threading mode] to Single-thread. In other words, it disables
1796 ** all mutexing and puts SQLite into a mode where it can only be used
1797 ** by a single thread. ^If SQLite is compiled with
1798 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
@@ -1790,11 +1799,11 @@
1799 ** it is not possible to change the [threading mode] from its default
1800 ** value of Single-thread and so [sqlite3_config()] will return
1801 ** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
1802 ** configuration option.</dd>
1803 **
1804 ** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
1805 ** <dd>There are no arguments to this option. ^This option sets the
1806 ** [threading mode] to Multi-thread. In other words, it disables
1807 ** mutexing on [database connection] and [prepared statement] objects.
1808 ** The application is responsible for serializing access to
1809 ** [database connections] and [prepared statements]. But other mutexes
@@ -1804,11 +1813,11 @@
1813 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1814 ** it is not possible to set the Multi-thread [threading mode] and
1815 ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
1816 ** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
1817 **
1818 ** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
1819 ** <dd>There are no arguments to this option. ^This option sets the
1820 ** [threading mode] to Serialized. In other words, this option enables
1821 ** all mutexes including the recursive
1822 ** mutexes on [database connection] and [prepared statement] objects.
1823 ** In this mode (which is the default when SQLite is compiled with
@@ -1820,27 +1829,27 @@
1829 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1830 ** it is not possible to set the Serialized [threading mode] and
1831 ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
1832 ** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
1833 **
1834 ** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
1835 ** <dd> ^(This option takes a single argument which is a pointer to an
1836 ** instance of the [sqlite3_mem_methods] structure. The argument specifies
1837 ** alternative low-level memory allocation routines to be used in place of
1838 ** the memory allocation routines built into SQLite.)^ ^SQLite makes
1839 ** its own private copy of the content of the [sqlite3_mem_methods] structure
1840 ** before the [sqlite3_config()] call returns.</dd>
1841 **
1842 ** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
1843 ** <dd> ^(This option takes a single argument which is a pointer to an
1844 ** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
1845 ** structure is filled with the currently defined memory allocation routines.)^
1846 ** This option can be used to overload the default memory allocation
1847 ** routines with a wrapper that simulations memory allocation failure or
1848 ** tracks memory usage, for example. </dd>
1849 **
1850 ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
1851 ** <dd> ^This option takes single argument of type int, interpreted as a
1852 ** boolean, which enables or disables the collection of memory allocation
1853 ** statistics. ^(When memory allocation statistics are disabled, the
1854 ** following SQLite interfaces become non-operational:
1855 ** <ul>
@@ -1852,11 +1861,11 @@
1861 ** ^Memory allocation statistics are enabled by default unless SQLite is
1862 ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
1863 ** allocation statistics are disabled by default.
1864 ** </dd>
1865 **
1866 ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
1867 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1868 ** scratch memory. There are three arguments: A pointer an 8-byte
1869 ** aligned memory buffer from which the scratch allocations will be
1870 ** drawn, the size of each scratch allocation (sz),
1871 ** and the maximum number of scratch allocations (N). The sz
@@ -1868,11 +1877,11 @@
1877 ** ^SQLite will never require a scratch buffer that is more than 6
1878 ** times the database page size. ^If SQLite needs needs additional
1879 ** scratch memory beyond what is provided by this configuration option, then
1880 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
1881 **
1882 ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
1883 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1884 ** the database page cache with the default page cache implemenation.
1885 ** This configuration should not be used if an application-define page
1886 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
1887 ** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1889,11 +1898,11 @@
1898 ** SQLite goes to [sqlite3_malloc()] for the additional storage space.
1899 ** The pointer in the first argument must
1900 ** be aligned to an 8-byte boundary or subsequent behavior of SQLite
1901 ** will be undefined.</dd>
1902 **
1903 ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
1904 ** <dd> ^This option specifies a static memory buffer that SQLite will use
1905 ** for all of its dynamic memory allocation needs beyond those provided
1906 ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
1907 ** There are three arguments: An 8-byte aligned pointer to the memory,
1908 ** the number of bytes in the memory buffer, and the minimum allocation size.
@@ -1906,11 +1915,11 @@
1915 ** The first pointer (the memory pointer) must be aligned to an 8-byte
1916 ** boundary or subsequent behavior of SQLite will be undefined.
1917 ** The minimum allocation size is capped at 2^12. Reasonable values
1918 ** for the minimum allocation size are 2^5 through 2^8.</dd>
1919 **
1920 ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
1921 ** <dd> ^(This option takes a single argument which is a pointer to an
1922 ** instance of the [sqlite3_mutex_methods] structure. The argument specifies
1923 ** alternative low-level mutex routines to be used in place
1924 ** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
1925 ** content of the [sqlite3_mutex_methods] structure before the call to
@@ -1918,11 +1927,11 @@
1927 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1928 ** the entire mutexing subsystem is omitted from the build and hence calls to
1929 ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
1930 ** return [SQLITE_ERROR].</dd>
1931 **
1932 ** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
1933 ** <dd> ^(This option takes a single argument which is a pointer to an
1934 ** instance of the [sqlite3_mutex_methods] structure. The
1935 ** [sqlite3_mutex_methods]
1936 ** structure is filled with the currently defined mutex routines.)^
1937 ** This option can be used to overload the default mutex allocation
@@ -1931,32 +1940,32 @@
1940 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1941 ** the entire mutexing subsystem is omitted from the build and hence calls to
1942 ** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
1943 ** return [SQLITE_ERROR].</dd>
1944 **
1945 ** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
1946 ** <dd> ^(This option takes two arguments that determine the default
1947 ** memory allocation for the lookaside memory allocator on each
1948 ** [database connection]. The first argument is the
1949 ** size of each lookaside buffer slot and the second is the number of
1950 ** slots allocated to each database connection.)^ ^(This option sets the
1951 ** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
1952 ** verb to [sqlite3_db_config()] can be used to change the lookaside
1953 ** configuration on individual connections.)^ </dd>
1954 **
1955 ** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
1956 ** <dd> ^(This option takes a single argument which is a pointer to
1957 ** an [sqlite3_pcache_methods] object. This object specifies the interface
1958 ** to a custom page cache implementation.)^ ^SQLite makes a copy of the
1959 ** object and uses it for page cache memory allocations.</dd>
1960 **
1961 ** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
1962 ** <dd> ^(This option takes a single argument which is a pointer to an
1963 ** [sqlite3_pcache_methods] object. SQLite copies of the current
1964 ** page cache implementation into that object.)^ </dd>
1965 **
1966 ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
1967 ** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
1968 ** function with a call signature of void(*)(void*,int,const char*),
1969 ** and a pointer to void. ^If the function pointer is not NULL, it is
1970 ** invoked by [sqlite3_log()] to process each logging event. ^If the
1971 ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
@@ -1970,10 +1979,22 @@
1979 ** The SQLite logging interface is not reentrant; the logger function
1980 ** supplied by the application must not invoke any SQLite interface.
1981 ** In a multi-threaded application, the application-defined logger
1982 ** function must be threadsafe. </dd>
1983 **
1984 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
1985 ** <dd> This option takes a single argument of type int. If non-zero, then
1986 ** URI handling is globally enabled. If the parameter is zero, then URI handling
1987 ** is globally disabled. If URI handling is globally enabled, all filenames
1988 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
1989 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
1990 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
1991 ** connection is opened. If it is globally disabled, filenames are
1992 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
1993 ** database connection is opened. By default, URI handling is globally
1994 ** disabled. The default value may be changed by compiling with the
1995 ** [SQLITE_USE_URI] symbol defined.
1996 ** </dl>
1997 */
1998 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1999 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
2000 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1988,10 +2009,11 @@
2009 /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
2010 #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
2011 #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
2012 #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
2013 #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
2014 #define SQLITE_CONFIG_URI 17 /* int */
2015
2016 /*
2017 ** CAPI3REF: Database Connection Configuration Options
2018 **
2019 ** These constants are the available integer configuration options that
@@ -2073,17 +2095,21 @@
2095 ** the table has a column of type [INTEGER PRIMARY KEY] then that column
2096 ** is another alias for the rowid.
2097 **
2098 ** ^This routine returns the [rowid] of the most recent
2099 ** successful [INSERT] into the database from the [database connection]
2100 ** in the first argument. ^As of SQLite version 3.7.7, this routines
2101 ** records the last insert rowid of both ordinary tables and [virtual tables].
2102 ** ^If no successful [INSERT]s
2103 ** have ever occurred on that database connection, zero is returned.
2104 **
2105 ** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
2106 ** method, then this routine will return the [rowid] of the inserted
2107 ** row as long as the trigger or virtual table method is running.
2108 ** But once the trigger or virtual table method ends, the value returned
2109 ** by this routine reverts to what it was before the trigger or virtual
2110 ** table method began.)^
2111 **
2112 ** ^An [INSERT] that fails due to a constraint violation is not a
2113 ** successful [INSERT] and does not change the value returned by this
2114 ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
2115 ** and INSERT OR ABORT make no changes to the return value of this
@@ -2742,10 +2768,13 @@
2768 ** The [sqlite3_set_authorizer | authorizer callback function] must
2769 ** return either [SQLITE_OK] or one of these two constants in order
2770 ** to signal SQLite whether or not the action is permitted. See the
2771 ** [sqlite3_set_authorizer | authorizer documentation] for additional
2772 ** information.
2773 **
2774 ** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
2775 ** from the [sqlite3_vtab_on_conflict()] interface.
2776 */
2777 #define SQLITE_DENY 1 /* Abort the SQL statement with an error */
2778 #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
2779
2780 /*
@@ -2864,11 +2893,11 @@
2893 SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
2894
2895 /*
2896 ** CAPI3REF: Opening A New Database Connection
2897 **
2898 ** ^These routines open an SQLite database file as specified by the
2899 ** filename argument. ^The filename argument is interpreted as UTF-8 for
2900 ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
2901 ** order for sqlite3_open16(). ^(A [database connection] handle is usually
2902 ** returned in *ppDb, even if an error occurs. The only exception is that
2903 ** if SQLite is unable to allocate memory to hold the [sqlite3] object,
@@ -2891,11 +2920,11 @@
2920 ** except that it accepts two additional parameters for additional control
2921 ** over the new database connection. ^(The flags parameter to
2922 ** sqlite3_open_v2() can take one of
2923 ** the following three values, optionally combined with the
2924 ** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
2925 ** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
2926 **
2927 ** <dl>
2928 ** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
2929 ** <dd>The database is opened in read-only mode. If the database does not
2930 ** already exist, an error is returned.</dd>)^
@@ -2910,13 +2939,12 @@
2939 ** it does not already exist. This is the behavior that is always used for
2940 ** sqlite3_open() and sqlite3_open16().</dd>)^
2941 ** </dl>
2942 **
2943 ** If the 3rd parameter to sqlite3_open_v2() is not one of the
2944 ** combinations shown above optionally combined with other
2945 ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
 
2946 ** then the behavior is undefined.
2947 **
2948 ** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
2949 ** opens in the multi-thread [threading mode] as long as the single-thread
2950 ** mode has not been set at compile-time or start-time. ^If the
@@ -2926,10 +2954,15 @@
2954 ** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
2955 ** eligible to use [shared cache mode], regardless of whether or not shared
2956 ** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
2957 ** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
2958 ** participate in [shared cache mode] even if it is enabled.
2959 **
2960 ** ^The fourth parameter to sqlite3_open_v2() is the name of the
2961 ** [sqlite3_vfs] object that defines the operating system interface that
2962 ** the new database connection should use. ^If the fourth parameter is
2963 ** a NULL pointer then the default [sqlite3_vfs] object is used.
2964 **
2965 ** ^If the filename is ":memory:", then a private, temporary in-memory database
2966 ** is created for the connection. ^This in-memory database will vanish when
2967 ** the database connection is closed. Future versions of SQLite might
2968 ** make use of additional special filenames that begin with the ":" character.
@@ -2939,14 +2972,115 @@
2972 **
2973 ** ^If the filename is an empty string, then a private, temporary
2974 ** on-disk database will be created. ^This private database will be
2975 ** automatically deleted as soon as the database connection is closed.
2976 **
2977 ** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
2978 **
2979 ** ^If [URI filename] interpretation is enabled, and the filename argument
2980 ** begins with "file:", then the filename is interpreted as a URI. ^URI
2981 ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2982 ** is set in the fourth argument to sqlite3_open_v2(), or if it has
2983 ** been enabled globally using the [SQLITE_CONFIG_URI] option with the
2984 ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
2985 ** As of SQLite version 3.7.7, URI filename interpretation is turned off
2986 ** by default, but future releases of SQLite might enable URI filename
2987 ** intepretation by default. See "[URI filenames]" for additional
2988 ** information.
2989 **
2990 ** URI filenames are parsed according to RFC 3986. ^If the URI contains an
2991 ** authority, then it must be either an empty string or the string
2992 ** "localhost". ^If the authority is not an empty string or "localhost", an
2993 ** error is returned to the caller. ^The fragment component of a URI, if
2994 ** present, is ignored.
2995 **
2996 ** ^SQLite uses the path component of the URI as the name of the disk file
2997 ** which contains the database. ^If the path begins with a '/' character,
2998 ** then it is interpreted as an absolute path. ^If the path does not begin
2999 ** with a '/' (meaning that the authority section is omitted from the URI)
3000 ** then the path is interpreted as a relative path.
3001 ** ^On windows, the first component of an absolute path
3002 ** is a drive specification (e.g. "C:").
3003 **
3004 ** [[core URI query parameters]]
3005 ** The query component of a URI may contain parameters that are interpreted
3006 ** either by SQLite itself, or by a [VFS | custom VFS implementation].
3007 ** SQLite interprets the following three query parameters:
3008 **
3009 ** <ul>
3010 ** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
3011 ** a VFS object that provides the operating system interface that should
3012 ** be used to access the database file on disk. ^If this option is set to
3013 ** an empty string the default VFS object is used. ^Specifying an unknown
3014 ** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
3015 ** present, then the VFS specified by the option takes precedence over
3016 ** the value passed as the fourth parameter to sqlite3_open_v2().
3017 **
3018 ** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
3019 ** "rwc". Attempting to set it to any other value is an error)^.
3020 ** ^If "ro" is specified, then the database is opened for read-only
3021 ** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
3022 ** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
3023 ** "rw", then the database is opened for read-write (but not create)
3024 ** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
3025 ** been set. ^Value "rwc" is equivalent to setting both
3026 ** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
3027 ** used, it is an error to specify a value for the mode parameter that is
3028 ** less restrictive than that specified by the flags passed as the third
3029 ** parameter.
3030 **
3031 ** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
3032 ** "private". ^Setting it to "shared" is equivalent to setting the
3033 ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
3034 ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
3035 ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
3036 ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
3037 ** a URI filename, its value overrides any behaviour requested by setting
3038 ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
3039 ** </ul>
3040 **
3041 ** ^Specifying an unknown parameter in the query component of a URI is not an
3042 ** error. Future versions of SQLite might understand additional query
3043 ** parameters. See "[query parameters with special meaning to SQLite]" for
3044 ** additional information.
3045 **
3046 ** [[URI filename examples]] <h3>URI filename examples</h3>
3047 **
3048 ** <table border="1" align=center cellpadding=5>
3049 ** <tr><th> URI filenames <th> Results
3050 ** <tr><td> file:data.db <td>
3051 ** Open the file "data.db" in the current directory.
3052 ** <tr><td> file:/home/fred/data.db<br>
3053 ** file:///home/fred/data.db <br>
3054 ** file://localhost/home/fred/data.db <br> <td>
3055 ** Open the database file "/home/fred/data.db".
3056 ** <tr><td> file://darkstar/home/fred/data.db <td>
3057 ** An error. "darkstar" is not a recognized authority.
3058 ** <tr><td style="white-space:nowrap">
3059 ** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
3060 ** <td> Windows only: Open the file "data.db" on fred's desktop on drive
3061 ** C:. Note that the %20 escaping in this example is not strictly
3062 ** necessary - space characters can be used literally
3063 ** in URI filenames.
3064 ** <tr><td> file:data.db?mode=ro&cache=private <td>
3065 ** Open file "data.db" in the current directory for read-only access.
3066 ** Regardless of whether or not shared-cache mode is enabled by
3067 ** default, use a private cache.
3068 ** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
3069 ** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
3070 ** <tr><td> file:data.db?mode=readonly <td>
3071 ** An error. "readonly" is not a valid option for the "mode" parameter.
3072 ** </table>
3073 **
3074 ** ^URI hexadecimal escape sequences (%HH) are supported within the path and
3075 ** query components of a URI. A hexadecimal escape sequence consists of a
3076 ** percent sign - "%" - followed by exactly two hexadecimal digits
3077 ** specifying an octet value. ^Before the path or query components of a
3078 ** URI filename are interpreted, they are encoded using UTF-8 and all
3079 ** hexadecimal escape sequences replaced by a single byte containing the
3080 ** corresponding octet. If this process generates an invalid UTF-8 encoding,
3081 ** the results are undefined.
3082 **
3083 ** <b>Note to Windows users:</b> The encoding used for the filename argument
3084 ** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
3085 ** codepage is currently defined. Filenames containing international
3086 ** characters must be converted to UTF-8 prior to passing them into
@@ -2964,10 +3098,30 @@
3098 const char *filename, /* Database filename (UTF-8) */
3099 sqlite3 **ppDb, /* OUT: SQLite db handle */
3100 int flags, /* Flags */
3101 const char *zVfs /* Name of VFS module to use */
3102 );
3103
3104 /*
3105 ** CAPI3REF: Obtain Values For URI Parameters
3106 **
3107 ** This is a utility routine, useful to VFS implementations, that checks
3108 ** to see if a database file was a URI that contained a specific query
3109 ** parameter, and if so obtains the value of the query parameter.
3110 **
3111 ** The zFilename argument is the filename pointer passed into the xOpen()
3112 ** method of a VFS implementation. The zParam argument is the name of the
3113 ** query parameter we seek. This routine returns the value of the zParam
3114 ** parameter if it exists. If the parameter does not exist, this routine
3115 ** returns a NULL pointer.
3116 **
3117 ** If the zFilename argument to this function is not a pointer that SQLite
3118 ** passed into the xOpen VFS method, then the behavior of this routine
3119 ** is undefined and probably undesirable.
3120 */
3121 SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
3122
3123
3124 /*
3125 ** CAPI3REF: Error Codes And Messages
3126 **
3127 ** ^The sqlite3_errcode() interface returns the numeric [result code] or
@@ -3080,47 +3234,49 @@
3234 ** that can be lowered at run-time using [sqlite3_limit()].
3235 ** The synopsis of the meanings of the various limits is shown below.
3236 ** Additional information is available at [limits | Limits in SQLite].
3237 **
3238 ** <dl>
3239 ** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
3240 ** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
3241 **
3242 ** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
3243 ** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
3244 **
3245 ** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
3246 ** <dd>The maximum number of columns in a table definition or in the
3247 ** result set of a [SELECT] or the maximum number of columns in an index
3248 ** or in an ORDER BY or GROUP BY clause.</dd>)^
3249 **
3250 ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
3251 ** <dd>The maximum depth of the parse tree on any expression.</dd>)^
3252 **
3253 ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
3254 ** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
3255 **
3256 ** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
3257 ** <dd>The maximum number of instructions in a virtual machine program
3258 ** used to implement an SQL statement. This limit is not currently
3259 ** enforced, though that might be added in some future release of
3260 ** SQLite.</dd>)^
3261 **
3262 ** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
3263 ** <dd>The maximum number of arguments on a function.</dd>)^
3264 **
3265 ** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
3266 ** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
3267 **
3268 ** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
3269 ** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
3270 ** <dd>The maximum length of the pattern argument to the [LIKE] or
3271 ** [GLOB] operators.</dd>)^
3272 **
3273 ** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
3274 ** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
3275 ** <dd>The maximum index number of any [parameter] in an SQL statement.)^
3276 **
3277 ** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
3278 ** <dd>The maximum depth of recursion for triggers.</dd>)^
3279 ** </dl>
3280 */
3281 #define SQLITE_LIMIT_LENGTH 0
3282 #define SQLITE_LIMIT_SQL_LENGTH 1
@@ -5151,10 +5307,15 @@
5307 int (*xRollback)(sqlite3_vtab *pVTab);
5308 int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
5309 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
5310 void **ppArg);
5311 int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
5312 /* The methods above are in version 1 of the sqlite_module object. Those
5313 ** below are for version 2 and greater. */
5314 int (*xSavepoint)(sqlite3_vtab *pVTab, int);
5315 int (*xRelease)(sqlite3_vtab *pVTab, int);
5316 int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
5317 };
5318
5319 /*
5320 ** CAPI3REF: Virtual Table Indexing Information
5321 ** KEYWORDS: sqlite3_index_info
@@ -5965,11 +6126,11 @@
6126 **
6127 ** ^This interface is used to retrieve runtime status information
6128 ** about the performance of SQLite, and optionally to reset various
6129 ** highwater marks. ^The first argument is an integer code for
6130 ** the specific parameter to measure. ^(Recognized integer codes
6131 ** are of the form [status parameters | SQLITE_STATUS_...].)^
6132 ** ^The current value of the parameter is returned into *pCurrent.
6133 ** ^The highest recorded value is returned in *pHighwater. ^If the
6134 ** resetFlag is true, then the highest record value is reset after
6135 ** *pHighwater is written. ^(Some parameters do not record the highest
6136 ** value. For those parameters
@@ -5992,82 +6153,84 @@
6153 SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
6154
6155
6156 /*
6157 ** CAPI3REF: Status Parameters
6158 ** KEYWORDS: {status parameters}
6159 **
6160 ** These integer constants designate various run-time status parameters
6161 ** that can be returned by [sqlite3_status()].
6162 **
6163 ** <dl>
6164 ** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
6165 ** <dd>This parameter is the current amount of memory checked out
6166 ** using [sqlite3_malloc()], either directly or indirectly. The
6167 ** figure includes calls made to [sqlite3_malloc()] by the application
6168 ** and internal memory usage by the SQLite library. Scratch memory
6169 ** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
6170 ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
6171 ** this parameter. The amount returned is the sum of the allocation
6172 ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
6173 **
6174 ** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
6175 ** <dd>This parameter records the largest memory allocation request
6176 ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
6177 ** internal equivalents). Only the value returned in the
6178 ** *pHighwater parameter to [sqlite3_status()] is of interest.
6179 ** The value written into the *pCurrent parameter is undefined.</dd>)^
6180 **
6181 ** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
6182 ** <dd>This parameter records the number of separate memory allocations
6183 ** currently checked out.</dd>)^
6184 **
6185 ** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
6186 ** <dd>This parameter returns the number of pages used out of the
6187 ** [pagecache memory allocator] that was configured using
6188 ** [SQLITE_CONFIG_PAGECACHE]. The
6189 ** value returned is in pages, not in bytes.</dd>)^
6190 **
6191 ** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
6192 ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
6193 ** <dd>This parameter returns the number of bytes of page cache
6194 ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
6195 ** buffer and where forced to overflow to [sqlite3_malloc()]. The
6196 ** returned value includes allocations that overflowed because they
6197 ** where too large (they were larger than the "sz" parameter to
6198 ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
6199 ** no space was left in the page cache.</dd>)^
6200 **
6201 ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
6202 ** <dd>This parameter records the largest memory allocation request
6203 ** handed to [pagecache memory allocator]. Only the value returned in the
6204 ** *pHighwater parameter to [sqlite3_status()] is of interest.
6205 ** The value written into the *pCurrent parameter is undefined.</dd>)^
6206 **
6207 ** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
6208 ** <dd>This parameter returns the number of allocations used out of the
6209 ** [scratch memory allocator] configured using
6210 ** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
6211 ** in bytes. Since a single thread may only have one scratch allocation
6212 ** outstanding at time, this parameter also reports the number of threads
6213 ** using scratch memory at the same time.</dd>)^
6214 **
6215 ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
6216 ** <dd>This parameter returns the number of bytes of scratch memory
6217 ** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
6218 ** buffer and where forced to overflow to [sqlite3_malloc()]. The values
6219 ** returned include overflows because the requested allocation was too
6220 ** larger (that is, because the requested allocation was larger than the
6221 ** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
6222 ** slots were available.
6223 ** </dd>)^
6224 **
6225 ** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
6226 ** <dd>This parameter records the largest memory allocation request
6227 ** handed to [scratch memory allocator]. Only the value returned in the
6228 ** *pHighwater parameter to [sqlite3_status()] is of interest.
6229 ** The value written into the *pCurrent parameter is undefined.</dd>)^
6230 **
6231 ** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
6232 ** <dd>This parameter records the deepest parser stack. It is only
6233 ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
6234 ** </dl>
6235 **
6236 ** New status parameters may be added from time to time.
@@ -6088,13 +6251,13 @@
6251 **
6252 ** ^This interface is used to retrieve runtime status information
6253 ** about a single [database connection]. ^The first argument is the
6254 ** database connection object to be interrogated. ^The second argument
6255 ** is an integer constant, taken from the set of
6256 ** [SQLITE_DBSTATUS options], that
6257 ** determines the parameter to interrogate. The set of
6258 ** [SQLITE_DBSTATUS options] is likely
6259 ** to grow in future releases of SQLite.
6260 **
6261 ** ^The current value of the requested parameter is written into *pCur
6262 ** and the highest instantaneous value is written into *pHiwtr. ^If
6263 ** the resetFlg is true, then the highest instantaneous value is
@@ -6107,10 +6270,11 @@
6270 */
6271 SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
6272
6273 /*
6274 ** CAPI3REF: Status Parameters for database connections
6275 ** KEYWORDS: {SQLITE_DBSTATUS options}
6276 **
6277 ** These constants are the available integer "verbs" that can be passed as
6278 ** the second argument to the [sqlite3_db_status()] interface.
6279 **
6280 ** New verbs may be added in future releases of SQLite. Existing verbs
@@ -6118,48 +6282,50 @@
6282 ** [sqlite3_db_status()] to make sure that the call worked.
6283 ** The [sqlite3_db_status()] interface will return a non-zero error code
6284 ** if a discontinued or unsupported verb is invoked.
6285 **
6286 ** <dl>
6287 ** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
6288 ** <dd>This parameter returns the number of lookaside memory slots currently
6289 ** checked out.</dd>)^
6290 **
6291 ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
6292 ** <dd>This parameter returns the number malloc attempts that were
6293 ** satisfied using lookaside memory. Only the high-water value is meaningful;
6294 ** the current value is always zero.)^
6295 **
6296 ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
6297 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
6298 ** <dd>This parameter returns the number malloc attempts that might have
6299 ** been satisfied using lookaside memory but failed due to the amount of
6300 ** memory requested being larger than the lookaside slot size.
6301 ** Only the high-water value is meaningful;
6302 ** the current value is always zero.)^
6303 **
6304 ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
6305 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
6306 ** <dd>This parameter returns the number malloc attempts that might have
6307 ** been satisfied using lookaside memory but failed due to all lookaside
6308 ** memory already being in use.
6309 ** Only the high-water value is meaningful;
6310 ** the current value is always zero.)^
6311 **
6312 ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
6313 ** <dd>This parameter returns the approximate number of of bytes of heap
6314 ** memory used by all pager caches associated with the database connection.)^
6315 ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
6316 **
6317 ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
6318 ** <dd>This parameter returns the approximate number of of bytes of heap
6319 ** memory used to store the schema for all databases associated
6320 ** with the connection - main, temp, and any [ATTACH]-ed databases.)^
6321 ** ^The full amount of memory used by the schemas is reported, even if the
6322 ** schema memory is shared with other database connections due to
6323 ** [shared cache mode] being enabled.
6324 ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
6325 **
6326 ** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
6327 ** <dd>This parameter returns the approximate number of of bytes of heap
6328 ** and lookaside memory used by all prepared statements associated with
6329 ** the database connection.)^
6330 ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
6331 ** </dd>
@@ -6177,11 +6343,11 @@
6343
6344 /*
6345 ** CAPI3REF: Prepared Statement Status
6346 **
6347 ** ^(Each prepared statement maintains various
6348 ** [SQLITE_STMTSTATUS counters] that measure the number
6349 ** of times it has performed specific operations.)^ These counters can
6350 ** be used to monitor the performance characteristics of the prepared
6351 ** statements. For example, if the number of table steps greatly exceeds
6352 ** the number of table searches or result rows, that would tend to indicate
6353 ** that the prepared statement is using a full table scan rather than
@@ -6188,11 +6354,11 @@
6354 ** an index.
6355 **
6356 ** ^(This interface is used to retrieve and reset counter values from
6357 ** a [prepared statement]. The first argument is the prepared statement
6358 ** object to be interrogated. The second argument
6359 ** is an integer code for a specific [SQLITE_STMTSTATUS counter]
6360 ** to be interrogated.)^
6361 ** ^The current value of the requested counter is returned.
6362 ** ^If the resetFlg is true, then the counter is reset to zero after this
6363 ** interface call returns.
6364 **
@@ -6200,28 +6366,29 @@
6366 */
6367 SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
6368
6369 /*
6370 ** CAPI3REF: Status Parameters for prepared statements
6371 ** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
6372 **
6373 ** These preprocessor macros define integer codes that name counter
6374 ** values associated with the [sqlite3_stmt_status()] interface.
6375 ** The meanings of the various counters are as follows:
6376 **
6377 ** <dl>
6378 ** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
6379 ** <dd>^This is the number of times that SQLite has stepped forward in
6380 ** a table as part of a full table scan. Large numbers for this counter
6381 ** may indicate opportunities for performance improvement through
6382 ** careful use of indices.</dd>
6383 **
6384 ** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
6385 ** <dd>^This is the number of sort operations that have occurred.
6386 ** A non-zero value in this counter may indicate an opportunity to
6387 ** improvement performance through careful use of indices.</dd>
6388 **
6389 ** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
6390 ** <dd>^This is the number of rows inserted into transient indices that
6391 ** were created automatically in order to help joins run faster.
6392 ** A non-zero value in this counter may indicate an opportunity to
6393 ** improvement performance by adding permanent indices that do not
6394 ** need to be reinitialized each time the statement is run.</dd>
@@ -6268,10 +6435,11 @@
6435 ** ^(The contents of the sqlite3_pcache_methods structure are copied to an
6436 ** internal buffer by SQLite within the call to [sqlite3_config]. Hence
6437 ** the application may discard the parameter after the call to
6438 ** [sqlite3_config()] returns.)^
6439 **
6440 ** [[the xInit() page cache method]]
6441 ** ^(The xInit() method is called once for each effective
6442 ** call to [sqlite3_initialize()])^
6443 ** (usually only once during the lifetime of the process). ^(The xInit()
6444 ** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^
6445 ** The intent of the xInit() method is to set up global data structures
@@ -6278,10 +6446,11 @@
6446 ** required by the custom page cache implementation.
6447 ** ^(If the xInit() method is NULL, then the
6448 ** built-in default page cache is used instead of the application defined
6449 ** page cache.)^
6450 **
6451 ** [[the xShutdown() page cache method]]
6452 ** ^The xShutdown() method is called by [sqlite3_shutdown()].
6453 ** It can be used to clean up
6454 ** any outstanding resources before process shutdown, if required.
6455 ** ^The xShutdown() method may be NULL.
6456 **
@@ -6292,10 +6461,11 @@
6461 ** in multithreaded applications.
6462 **
6463 ** ^SQLite will never invoke xInit() more than once without an intervening
6464 ** call to xShutdown().
6465 **
6466 ** [[the xCreate() page cache methods]]
6467 ** ^SQLite invokes the xCreate() method to construct a new cache instance.
6468 ** SQLite will typically create one cache instance for each open database file,
6469 ** though this is not guaranteed. ^The
6470 ** first parameter, szPage, is the size in bytes of the pages that must
6471 ** be allocated by the cache. ^szPage will not be a power of two. ^szPage
@@ -6316,20 +6486,23 @@
6486 ** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
6487 ** false will always have the "discard" flag set to true.
6488 ** ^Hence, a cache created with bPurgeable false will
6489 ** never contain any unpinned pages.
6490 **
6491 ** [[the xCachesize() page cache method]]
6492 ** ^(The xCachesize() method may be called at any time by SQLite to set the
6493 ** suggested maximum cache-size (number of pages stored by) the cache
6494 ** instance passed as the first argument. This is the value configured using
6495 ** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
6496 ** parameter, the implementation is not required to do anything with this
6497 ** value; it is advisory only.
6498 **
6499 ** [[the xPagecount() page cache methods]]
6500 ** The xPagecount() method must return the number of pages currently
6501 ** stored in the cache, both pinned and unpinned.
6502 **
6503 ** [[the xFetch() page cache methods]]
6504 ** The xFetch() method locates a page in the cache and returns a pointer to
6505 ** the page, or a NULL pointer.
6506 ** A "page", in this context, means a buffer of szPage bytes aligned at an
6507 ** 8-byte boundary. The page to be fetched is determined by the key. ^The
6508 ** mimimum key value is 1. After it has been retrieved using xFetch, the page
@@ -6354,10 +6527,11 @@
6527 ** will only use a createFlag of 2 after a prior call with a createFlag of 1
6528 ** failed.)^ In between the to xFetch() calls, SQLite may
6529 ** attempt to unpin one or more cache pages by spilling the content of
6530 ** pinned pages to disk and synching the operating system disk cache.
6531 **
6532 ** [[the xUnpin() page cache method]]
6533 ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
6534 ** as its second argument. If the third parameter, discard, is non-zero,
6535 ** then the page must be evicted from the cache.
6536 ** ^If the discard parameter is
6537 ** zero, then the page may be discarded or retained at the discretion of
@@ -6366,10 +6540,11 @@
6540 **
6541 ** The cache must not perform any reference counting. A single
6542 ** call to xUnpin() unpins the page regardless of the number of prior calls
6543 ** to xFetch().
6544 **
6545 ** [[the xRekey() page cache methods]]
6546 ** The xRekey() method is used to change the key value associated with the
6547 ** page passed as the second argument. If the cache
6548 ** previously contains an entry associated with newKey, it must be
6549 ** discarded. ^Any prior cache entry associated with newKey is guaranteed not
6550 ** to be pinned.
@@ -6378,10 +6553,11 @@
6553 ** existing cache entries with page numbers (keys) greater than or equal
6554 ** to the value of the iLimit parameter passed to xTruncate(). If any
6555 ** of these pages are pinned, they are implicitly unpinned, meaning that
6556 ** they can be safely discarded.
6557 **
6558 ** [[the xDestroy() page cache method]]
6559 ** ^The xDestroy() method is used to delete a cache allocated by xCreate().
6560 ** All resources associated with the specified cache should be freed. ^After
6561 ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
6562 ** handle invalid, and will not use it with any other sqlite3_pcache_methods
6563 ** functions.
@@ -6440,11 +6616,11 @@
6616 ** associated with the backup operation.
6617 ** </ol>)^
6618 ** There should be exactly one call to sqlite3_backup_finish() for each
6619 ** successful call to sqlite3_backup_init().
6620 **
6621 ** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
6622 **
6623 ** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
6624 ** [database connection] associated with the destination database
6625 ** and the database name, respectively.
6626 ** ^The database name is "main" for the main database, "temp" for the
@@ -6467,11 +6643,11 @@
6643 ** [sqlite3_backup] object.
6644 ** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
6645 ** sqlite3_backup_finish() functions to perform the specified backup
6646 ** operation.
6647 **
6648 ** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
6649 **
6650 ** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
6651 ** the source and destination databases specified by [sqlite3_backup] object B.
6652 ** ^If N is negative, all remaining source pages are copied.
6653 ** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
@@ -6524,11 +6700,11 @@
6700 ** restarted by the next call to sqlite3_backup_step(). ^If the source
6701 ** database is modified by the using the same database connection as is used
6702 ** by the backup operation, then the backup database is automatically
6703 ** updated at the same time.
6704 **
6705 ** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
6706 **
6707 ** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
6708 ** application wishes to abandon the backup operation, the application
6709 ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
6710 ** ^The sqlite3_backup_finish() interfaces releases all
@@ -6547,11 +6723,12 @@
6723 **
6724 ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
6725 ** is not a permanent error and does not affect the return value of
6726 ** sqlite3_backup_finish().
6727 **
6728 ** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
6729 ** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
6730 **
6731 ** ^Each call to sqlite3_backup_step() sets two values inside
6732 ** the [sqlite3_backup] object: the number of pages still to be backed
6733 ** up and the total number of pages in the source database file.
6734 ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
@@ -6932,10 +7109,97 @@
7109 ** each of these values.
7110 */
7111 #define SQLITE_CHECKPOINT_PASSIVE 0
7112 #define SQLITE_CHECKPOINT_FULL 1
7113 #define SQLITE_CHECKPOINT_RESTART 2
7114
7115 /*
7116 ** CAPI3REF: Virtual Table Interface Configuration
7117 **
7118 ** This function may be called by either the [xConnect] or [xCreate] method
7119 ** of a [virtual table] implementation to configure
7120 ** various facets of the virtual table interface.
7121 **
7122 ** If this interface is invoked outside the context of an xConnect or
7123 ** xCreate virtual table method then the behavior is undefined.
7124 **
7125 ** At present, there is only one option that may be configured using
7126 ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
7127 ** may be added in the future.
7128 */
7129 SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
7130
7131 /*
7132 ** CAPI3REF: Virtual Table Configuration Options
7133 **
7134 ** These macros define the various options to the
7135 ** [sqlite3_vtab_config()] interface that [virtual table] implementations
7136 ** can use to customize and optimize their behavior.
7137 **
7138 ** <dl>
7139 ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
7140 ** <dd>Calls of the form
7141 ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
7142 ** where X is an integer. If X is zero, then the [virtual table] whose
7143 ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
7144 ** support constraints. In this configuration (which is the default) if
7145 ** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
7146 ** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
7147 ** specified as part of the users SQL statement, regardless of the actual
7148 ** ON CONFLICT mode specified.
7149 **
7150 ** If X is non-zero, then the virtual table implementation guarantees
7151 ** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
7152 ** any modifications to internal or persistent data structures have been made.
7153 ** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
7154 ** is able to roll back a statement or database transaction, and abandon
7155 ** or continue processing the current SQL statement as appropriate.
7156 ** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
7157 ** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
7158 ** had been ABORT.
7159 **
7160 ** Virtual table implementations that are required to handle OR REPLACE
7161 ** must do so within the [xUpdate] method. If a call to the
7162 ** [sqlite3_vtab_on_conflict()] function indicates that the current ON
7163 ** CONFLICT policy is REPLACE, the virtual table implementation should
7164 ** silently replace the appropriate rows within the xUpdate callback and
7165 ** return SQLITE_OK. Or, if this is not possible, it may return
7166 ** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
7167 ** constraint handling.
7168 ** </dl>
7169 */
7170 #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
7171
7172 /*
7173 ** CAPI3REF: Determine The Virtual Table Conflict Policy
7174 **
7175 ** This function may only be called from within a call to the [xUpdate] method
7176 ** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
7177 ** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
7178 ** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
7179 ** of the SQL statement that triggered the call to the [xUpdate] method of the
7180 ** [virtual table].
7181 */
7182 SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
7183
7184 /*
7185 ** CAPI3REF: Conflict resolution modes
7186 **
7187 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
7188 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
7189 ** is for the SQL statement being evaluated.
7190 **
7191 ** Note that the [SQLITE_IGNORE] constant is also used as a potential
7192 ** return value from the [sqlite3_set_authorizer()] callback and that
7193 ** [SQLITE_ABORT] is also a [result code].
7194 */
7195 #define SQLITE_ROLLBACK 1
7196 /* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
7197 #define SQLITE_FAIL 3
7198 /* #define SQLITE_ABORT 4 // Also an error code */
7199 #define SQLITE_REPLACE 5
7200
7201
7202
7203 /*
7204 ** Undo the hack that converts floating point types to integer for
7205 ** builds on processors without floating point support.
@@ -7599,10 +7863,11 @@
7863 typedef struct Trigger Trigger;
7864 typedef struct TriggerPrg TriggerPrg;
7865 typedef struct TriggerStep TriggerStep;
7866 typedef struct UnpackedRecord UnpackedRecord;
7867 typedef struct VTable VTable;
7868 typedef struct VtabCtx VtabCtx;
7869 typedef struct Walker Walker;
7870 typedef struct WherePlan WherePlan;
7871 typedef struct WhereInfo WhereInfo;
7872 typedef struct WhereLevel WhereLevel;
7873
@@ -7655,10 +7920,11 @@
7920 typedef struct BtCursor BtCursor;
7921 typedef struct BtShared BtShared;
7922
7923
7924 SQLITE_PRIVATE int sqlite3BtreeOpen(
7925 sqlite3_vfs *pVfs, /* VFS to use with this b-tree */
7926 const char *zFilename, /* Name of database file to open */
7927 sqlite3 *db, /* Associated database connection */
7928 Btree **ppBtree, /* Return open Btree* here */
7929 int flags, /* Flags */
7930 int vfsFlags /* Flags passed through to VFS open */
@@ -9134,19 +9400,20 @@
9400 struct sqlite3 {
9401 sqlite3_vfs *pVfs; /* OS Interface */
9402 int nDb; /* Number of backends currently in use */
9403 Db *aDb; /* All backends */
9404 int flags; /* Miscellaneous flags. See below */
9405 unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
9406 int errCode; /* Most recent error code (SQLITE_*) */
9407 int errMask; /* & result codes with this before returning */
9408 u8 autoCommit; /* The auto-commit flag. */
9409 u8 temp_store; /* 1: file 2: memory 0: default */
9410 u8 mallocFailed; /* True if we have seen a malloc failure */
9411 u8 dfltLockMode; /* Default locking-mode for attached dbs */
9412 signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
9413 u8 suppressErr; /* Do not issue error messages if true */
9414 u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
9415 int nextPagesize; /* Pagesize after VACUUM if >0 */
9416 int nTable; /* Number of tables in the database */
9417 CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
9418 i64 lastRowid; /* ROWID of most recent insert (see above) */
9419 u32 magic; /* Magic number for detect library misuse */
@@ -9201,11 +9468,11 @@
9468 void *pProgressArg; /* Argument to the progress callback */
9469 int nProgressOps; /* Number of opcodes for progress callback */
9470 #endif
9471 #ifndef SQLITE_OMIT_VIRTUALTABLE
9472 Hash aModule; /* populated by sqlite3_create_module() */
9473 VtabCtx *pVtabCtx; /* Context for active vtab connect/create */
9474 VTable **aVTrans; /* Virtual tables with open transactions */
9475 int nVTrans; /* Allocated size of aVTrans */
9476 VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
9477 #endif
9478 FuncDefHash aFunc; /* Hash table of connection functions */
@@ -9564,10 +9831,11 @@
9831 struct VTable {
9832 sqlite3 *db; /* Database connection associated with this table */
9833 Module *pMod; /* Pointer to module implementation */
9834 sqlite3_vtab *pVtab; /* Pointer to vtab instance */
9835 int nRef; /* Number of pointers to this structure */
9836 u8 bConstraint; /* True if constraints are supported */
9837 VTable *pNext; /* Next in linked list (see above) */
9838 };
9839
9840 /*
9841 ** Each SQL table is represented in memory by an instance of the
@@ -10752,10 +11020,11 @@
11020 */
11021 struct Sqlite3Config {
11022 int bMemstat; /* True to enable memory status */
11023 int bCoreMutex; /* True to enable core mutexing */
11024 int bFullMutex; /* True to enable full mutexing */
11025 int bOpenUri; /* True to interpret filenames as URIs */
11026 int mxStrlen; /* Maximum string length */
11027 int szLookaside; /* Default lookaside buffer size */
11028 int nLookaside; /* Default lookaside buffer count */
11029 sqlite3_mem_methods m; /* Low-level memory allocation interface */
11030 sqlite3_mutex_methods mutex; /* Low-level mutex interface */
@@ -11001,10 +11270,12 @@
11270 SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
11271 SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
11272 SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
11273 SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
11274 SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
11275 SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
11276 sqlite3_vfs**,char**,char **);
11277
11278 SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
11279 SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
11280 SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
11281 SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*);
@@ -11251,10 +11522,11 @@
11522 SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
11523 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
11524 SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
11525 SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
11526 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
11527 SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
11528 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
11529 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
11530 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
11531 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
11532 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
@@ -11266,10 +11538,16 @@
11538 SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
11539 SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
11540 SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
11541 SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
11542 SQLITE_PRIVATE int sqlite3AbsInt32(int);
11543 #ifdef SQLITE_ENABLE_8_3_NAMES
11544 SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
11545 #else
11546 # define sqlite3FileSuffix3(X,Y)
11547 #endif
11548 SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z);
11549
11550 SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
11551 SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
11552 SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
11553 void(*)(void*));
@@ -11375,18 +11653,20 @@
11653 # define sqlite3VtabCommit(X)
11654 # define sqlite3VtabInSync(db) 0
11655 # define sqlite3VtabLock(X)
11656 # define sqlite3VtabUnlock(X)
11657 # define sqlite3VtabUnlockList(X)
11658 # define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
11659 #else
11660 SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*);
11661 SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **);
11662 SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
11663 SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
11664 SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
11665 SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
11666 SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
11667 SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
11668 # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
11669 #endif
11670 SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
11671 SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
11672 SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
@@ -11689,20 +11969,23 @@
11969 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
11970 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
11971 };
11972 #endif
11973
11974 #ifndef SQLITE_USE_URI
11975 # define SQLITE_USE_URI 0
11976 #endif
11977
11978 /*
11979 ** The following singleton contains the global configuration for
11980 ** the SQLite library.
11981 */
11982 SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
11983 SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
11984 1, /* bCoreMutex */
11985 SQLITE_THREADSAFE==1, /* bFullMutex */
11986 SQLITE_USE_URI, /* bOpenUri */
11987 0x7ffffffe, /* mxStrlen */
11988 100, /* szLookaside */
11989 500, /* nLookaside */
11990 {0,0,0,0,0,0,0,0}, /* m */
11991 {0,0,0,0,0,0,0,0,0}, /* mutex */
@@ -17948,11 +18231,11 @@
18231 assert( sqlite3_mutex_held(mem0.mutex) );
18232 nFull = sqlite3GlobalConfig.m.xRoundup(n);
18233 sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
18234 if( mem0.alarmCallback!=0 ){
18235 int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
18236 if( nUsed >= mem0.alarmThreshold - nFull ){
18237 mem0.nearlyFull = 1;
18238 sqlite3MallocAlarm(nFull);
18239 }else{
18240 mem0.nearlyFull = 0;
18241 }
@@ -18189,11 +18472,11 @@
18472
18473 /*
18474 ** Change the size of an existing memory allocation
18475 */
18476 SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
18477 int nOld, nNew, nDiff;
18478 void *pNew;
18479 if( pOld==0 ){
18480 return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
18481 }
18482 if( nBytes<=0 ){
@@ -18212,13 +18495,14 @@
18495 if( nOld==nNew ){
18496 pNew = pOld;
18497 }else if( sqlite3GlobalConfig.bMemstat ){
18498 sqlite3_mutex_enter(mem0.mutex);
18499 sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
18500 nDiff = nNew - nOld;
18501 if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
18502 mem0.alarmThreshold-nDiff ){
18503 sqlite3MallocAlarm(nDiff);
18504 }
18505 assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
18506 assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
18507 pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
18508 if( pNew==0 && mem0.alarmCallback ){
@@ -21180,27 +21464,25 @@
21464 p[3] = (u8)v;
21465 }
21466
21467
21468
 
21469 /*
21470 ** Translate a single byte of Hex into an integer.
21471 ** This routine only works if h really is a valid hexadecimal
21472 ** character: 0..9a..fA..F
21473 */
21474 SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
21475 assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
21476 #ifdef SQLITE_ASCII
21477 h += 9*(1&(h>>6));
21478 #endif
21479 #ifdef SQLITE_EBCDIC
21480 h += 9*(1&~(h>>4));
21481 #endif
21482 return (u8)(h & 0xf);
21483 }
 
21484
21485 #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
21486 /*
21487 ** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
21488 ** value. Return a pointer to its binary value. Space to hold the
@@ -21213,11 +21495,11 @@
21495
21496 zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
21497 n--;
21498 if( zBlob ){
21499 for(i=0; i<n; i+=2){
21500 zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
21501 }
21502 zBlob[i/2] = 0;
21503 }
21504 return zBlob;
21505 }
@@ -21345,10 +21627,36 @@
21627 SQLITE_PRIVATE int sqlite3AbsInt32(int x){
21628 if( x>=0 ) return x;
21629 if( x==(int)0x80000000 ) return 0x7fffffff;
21630 return -x;
21631 }
21632
21633 #ifdef SQLITE_ENABLE_8_3_NAMES
21634 /*
21635 ** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
21636 ** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
21637 ** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
21638 ** three characters, then shorten the suffix on z[] to be the last three
21639 ** characters of the original suffix.
21640 **
21641 ** Examples:
21642 **
21643 ** test.db-journal => test.nal
21644 ** test.db-wal => test.wal
21645 ** test.db-shm => test.shm
21646 */
21647 SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
21648 const char *zOk;
21649 zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
21650 if( zOk && sqlite3GetBoolean(zOk) ){
21651 int i, sz;
21652 sz = sqlite3Strlen30(z);
21653 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
21654 if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
21655 }
21656 }
21657 #endif
21658
21659 /************** End of util.c ************************************************/
21660 /************** Begin file hash.c ********************************************/
21661 /*
21662 ** 2001 September 22
@@ -24398,10 +24706,22 @@
24706 #if SQLITE_THREADSAFE
24707 #define threadid pthread_self()
24708 #else
24709 #define threadid 0
24710 #endif
24711
24712 /*
24713 ** Different Unix systems declare open() in different ways. Same use
24714 ** open(const char*,int,mode_t). Others use open(const char*,int,...).
24715 ** The difference is important when using a pointer to the function.
24716 **
24717 ** The safest way to deal with the problem is to always use this wrapper
24718 ** which always has the same well-defined interface.
24719 */
24720 static int posixOpen(const char *zFile, int flags, int mode){
24721 return open(zFile, flags, mode);
24722 }
24723
24724 /*
24725 ** Many system calls are accessed through pointer-to-functions so that
24726 ** they may be overridden at runtime to facilitate fault injection during
24727 ** testing and sandboxing. The following array holds the names and pointers
@@ -24410,11 +24730,11 @@
24730 static struct unix_syscall {
24731 const char *zName; /* Name of the sytem call */
24732 sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
24733 sqlite3_syscall_ptr pDefault; /* Default value */
24734 } aSyscall[] = {
24735 { "open", (sqlite3_syscall_ptr)posixOpen, 0 },
24736 #define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
24737
24738 { "close", (sqlite3_syscall_ptr)close, 0 },
24739 #define osClose ((int(*)(int))aSyscall[1].pCurrent)
24740
@@ -24448,11 +24768,11 @@
24768 #define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
24769
24770 { "read", (sqlite3_syscall_ptr)read, 0 },
24771 #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
24772
24773 #if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
24774 { "pread", (sqlite3_syscall_ptr)pread, 0 },
24775 #else
24776 { "pread", (sqlite3_syscall_ptr)0, 0 },
24777 #endif
24778 #define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -24465,11 +24785,11 @@
24785 #define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
24786
24787 { "write", (sqlite3_syscall_ptr)write, 0 },
24788 #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
24789
24790 #if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
24791 { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
24792 #else
24793 { "pwrite", (sqlite3_syscall_ptr)0, 0 },
24794 #endif
24795 #define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -24483,12 +24803,14 @@
24803 #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
24804 aSyscall[13].pCurrent)
24805
24806 #if SQLITE_ENABLE_LOCKING_STYLE
24807 { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
24808 #else
24809 { "fchmod", (sqlite3_syscall_ptr)0, 0 },
24810 #endif
24811 #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
 
24812
24813 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
24814 { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
24815 #else
24816 { "fallocate", (sqlite3_syscall_ptr)0, 0 },
@@ -25049,11 +25371,11 @@
25371 unixShmNode *pShmNode; /* Shared memory associated with this inode */
25372 int nLock; /* Number of outstanding file locks */
25373 UnixUnusedFd *pUnused; /* Unused file descriptors to close */
25374 unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
25375 unixInodeInfo *pPrev; /* .... doubly linked */
25376 #if SQLITE_ENABLE_LOCKING_STYLE
25377 unsigned long long sharedByte; /* for AFP simulated shared lock */
25378 #endif
25379 #if OS_VXWORKS
25380 sem_t *pSem; /* Named POSIX semaphore */
25381 char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
@@ -27206,11 +27528,11 @@
27528 }
27529 SimulateIOError(( wrote=(-1), amt=1 ));
27530 SimulateDiskfullError(( wrote=0, amt=1 ));
27531
27532 if( amt>0 ){
27533 if( wrote<0 && pFile->lastErrno!=ENOSPC ){
27534 /* lastErrno set by seekAndWrite */
27535 return SQLITE_IOERR_WRITE;
27536 }else{
27537 pFile->lastErrno = 0; /* not a system error */
27538 return SQLITE_FULL;
@@ -27873,10 +28195,11 @@
28195 sqlite3_snprintf(nShmFilename, zShmFilename,
28196 SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
28197 (u32)sStat.st_ino, (u32)sStat.st_dev);
28198 #else
28199 sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
28200 sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
28201 #endif
28202 pShmNode->h = -1;
28203 pDbFd->pInode->pShmNode = pShmNode;
28204 pShmNode->pInode = pDbFd->pInode;
28205 pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
@@ -28031,11 +28354,11 @@
28354 if( pShmNode->h>=0 ){
28355 pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
28356 MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
28357 );
28358 if( pMem==MAP_FAILED ){
28359 rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
28360 goto shmpage_out;
28361 }
28362 }else{
28363 pMem = sqlite3_malloc(szRegion);
28364 if( pMem==0 ){
@@ -28906,17 +29229,23 @@
29229 ** Finally, if the file being opened is a WAL or regular journal file, then
29230 ** this function queries the file-system for the permissions on the
29231 ** corresponding database file and sets *pMode to this value. Whenever
29232 ** possible, WAL and journal files are created using the same permissions
29233 ** as the associated database file.
29234 **
29235 ** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
29236 ** original filename is unavailable. But 8_3_NAMES is only used for
29237 ** FAT filesystems and permissions do not matter there, so just use
29238 ** the default permissions.
29239 */
29240 static int findCreateFileMode(
29241 const char *zPath, /* Path of file (possibly) being created */
29242 int flags, /* Flags passed as 4th argument to xOpen() */
29243 mode_t *pMode /* OUT: Permissions to open file with */
29244 ){
29245 int rc = SQLITE_OK; /* Return Code */
29246 *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
29247 if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
29248 char zDb[MAX_PATHNAME+1]; /* Database file path */
29249 int nDb; /* Number of valid bytes in zDb */
29250 struct stat sStat; /* Output of stat() on database file */
29251
@@ -28924,19 +29253,19 @@
29253 ** the path to the associated database file from zPath. This block handles
29254 ** the following naming conventions:
29255 **
29256 ** "<path to db>-journal"
29257 ** "<path to db>-wal"
29258 ** "<path to db>-journalNN"
29259 ** "<path to db>-walNN"
29260 **
29261 ** where NN is a 4 digit decimal number. The NN naming schemes are
29262 ** used by the test_multiplex.c module.
29263 */
29264 nDb = sqlite3Strlen30(zPath) - 1;
29265 while( nDb>0 && zPath[nDb]!='-' ) nDb--;
29266 if( nDb==0 ) return SQLITE_OK;
29267 memcpy(zDb, zPath, nDb);
29268 zDb[nDb] = '\0';
29269
29270 if( 0==stat(zDb, &sStat) ){
29271 *pMode = sStat.st_mode & 0777;
@@ -28943,12 +29272,10 @@
29272 }else{
29273 rc = SQLITE_IOERR_FSTAT;
29274 }
29275 }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
29276 *pMode = 0600;
 
 
29277 }
29278 return rc;
29279 }
29280
29281 /*
@@ -30801,10 +31128,14 @@
31128 UNIXVFS("unix-nfs", nfsIoFinder ),
31129 UNIXVFS("unix-proxy", proxyIoFinder ),
31130 #endif
31131 };
31132 unsigned int i; /* Loop counter */
31133
31134 /* Double-check that the aSyscall[] array has been constructed
31135 ** correctly. See ticket [bb3a86e890c8e96ab] */
31136 assert( ArraySize(aSyscall)==16 );
31137
31138 /* Register all VFSes defined in the aVfs[] array */
31139 for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
31140 sqlite3_vfs_register(&aVfs[i], i==0);
31141 }
@@ -31147,10 +31478,11 @@
31478 HANDLE hShared; /* Shared memory segment used for locking */
31479 winceLock local; /* Locks obtained by this instance of winFile */
31480 winceLock *shared; /* Global shared lock memory for the file */
31481 #endif
31482 };
31483
31484
31485 /*
31486 ** Forward prototypes.
31487 */
31488 static int getSectorSize(
@@ -31315,11 +31647,11 @@
31647
31648 /*
31649 ** Convert UTF-8 to multibyte character string. Space to hold the
31650 ** returned string is obtained from malloc().
31651 */
31652 SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
31653 char *zFilenameMbcs;
31654 WCHAR *zTmpWide;
31655
31656 zTmpWide = utf8ToUnicode(zFilename);
31657 if( zTmpWide==0 ){
@@ -31328,10 +31660,113 @@
31660 zFilenameMbcs = unicodeToMbcs(zTmpWide);
31661 free(zTmpWide);
31662 return zFilenameMbcs;
31663 }
31664
31665
31666 /*
31667 ** The return value of getLastErrorMsg
31668 ** is zero if the error message fits in the buffer, or non-zero
31669 ** otherwise (if the message was truncated).
31670 */
31671 static int getLastErrorMsg(int nBuf, char *zBuf){
31672 /* FormatMessage returns 0 on failure. Otherwise it
31673 ** returns the number of TCHARs written to the output
31674 ** buffer, excluding the terminating null char.
31675 */
31676 DWORD error = GetLastError();
31677 DWORD dwLen = 0;
31678 char *zOut = 0;
31679
31680 if( isNT() ){
31681 WCHAR *zTempWide = NULL;
31682 dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
31683 NULL,
31684 error,
31685 0,
31686 (LPWSTR) &zTempWide,
31687 0,
31688 0);
31689 if( dwLen > 0 ){
31690 /* allocate a buffer and convert to UTF8 */
31691 zOut = unicodeToUtf8(zTempWide);
31692 /* free the system buffer allocated by FormatMessage */
31693 LocalFree(zTempWide);
31694 }
31695 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
31696 ** Since the ASCII version of these Windows API do not exist for WINCE,
31697 ** it's important to not reference them for WINCE builds.
31698 */
31699 #if SQLITE_OS_WINCE==0
31700 }else{
31701 char *zTemp = NULL;
31702 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
31703 NULL,
31704 error,
31705 0,
31706 (LPSTR) &zTemp,
31707 0,
31708 0);
31709 if( dwLen > 0 ){
31710 /* allocate a buffer and convert to UTF8 */
31711 zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
31712 /* free the system buffer allocated by FormatMessage */
31713 LocalFree(zTemp);
31714 }
31715 #endif
31716 }
31717 if( 0 == dwLen ){
31718 sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
31719 }else{
31720 /* copy a maximum of nBuf chars to output buffer */
31721 sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
31722 /* free the UTF8 buffer */
31723 free(zOut);
31724 }
31725 return 0;
31726 }
31727
31728 /*
31729 **
31730 ** This function - winLogErrorAtLine() - is only ever called via the macro
31731 ** winLogError().
31732 **
31733 ** This routine is invoked after an error occurs in an OS function.
31734 ** It logs a message using sqlite3_log() containing the current value of
31735 ** error code and, if possible, the human-readable equivalent from
31736 ** FormatMessage.
31737 **
31738 ** The first argument passed to the macro should be the error code that
31739 ** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
31740 ** The two subsequent arguments should be the name of the OS function that
31741 ** failed and the the associated file-system path, if any.
31742 */
31743 #define winLogError(a,b,c) winLogErrorAtLine(a,b,c,__LINE__)
31744 static int winLogErrorAtLine(
31745 int errcode, /* SQLite error code */
31746 const char *zFunc, /* Name of OS function that failed */
31747 const char *zPath, /* File path associated with error */
31748 int iLine /* Source line number where error occurred */
31749 ){
31750 char zMsg[500]; /* Human readable error text */
31751 int i; /* Loop counter */
31752 DWORD iErrno = GetLastError(); /* Error code */
31753
31754 zMsg[0] = 0;
31755 getLastErrorMsg(sizeof(zMsg), zMsg);
31756 assert( errcode!=SQLITE_OK );
31757 if( zPath==0 ) zPath = "";
31758 for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
31759 zMsg[i] = 0;
31760 sqlite3_log(errcode,
31761 "os_win.c:%d: (%d) %s(%s) - %s",
31762 iLine, iErrno, zFunc, zPath, zMsg
31763 );
31764
31765 return errcode;
31766 }
31767
31768 #if SQLITE_OS_WINCE
31769 /*************************************************************************
31770 ** This section contains code for WinCE only.
31771 */
31772 /*
@@ -31404,10 +31839,11 @@
31839
31840 /* Create/open the named mutex */
31841 pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
31842 if (!pFile->hMutex){
31843 pFile->lastErrno = GetLastError();
31844 winLogError(SQLITE_ERROR, "winceCreateLock1", zFilename);
31845 free(zName);
31846 return FALSE;
31847 }
31848
31849 /* Acquire the mutex before continuing */
@@ -31435,10 +31871,11 @@
31871 pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
31872 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
31873 /* If mapping failed, close the shared memory handle and erase it */
31874 if (!pFile->shared){
31875 pFile->lastErrno = GetLastError();
31876 winLogError(SQLITE_ERROR, "winceCreateLock2", zFilename);
31877 CloseHandle(pFile->hShared);
31878 pFile->hShared = NULL;
31879 }
31880 }
31881
@@ -31680,10 +32117,11 @@
32117 ** GetLastError().
32118 */
32119 dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
32120 if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){
32121 pFile->lastErrno = GetLastError();
32122 winLogError(SQLITE_IOERR_SEEK, "seekWinFile", pFile->zPath);
32123 return 1;
32124 }
32125
32126 return 0;
32127 }
@@ -31725,11 +32163,12 @@
32163 free(pFile->zDeleteOnClose);
32164 }
32165 #endif
32166 OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
32167 OpenCounter(-1);
32168 return rc ? SQLITE_OK
32169 : winLogError(SQLITE_IOERR_CLOSE, "winClose", pFile->zPath);
32170 }
32171
32172 /*
32173 ** Read data from a file into a buffer. Return SQLITE_OK if all
32174 ** bytes were read successfully and SQLITE_IOERR if anything goes
@@ -31751,11 +32190,11 @@
32190 if( seekWinFile(pFile, offset) ){
32191 return SQLITE_FULL;
32192 }
32193 if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
32194 pFile->lastErrno = GetLastError();
32195 return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
32196 }
32197 if( nRead<(DWORD)amt ){
32198 /* Unread parts of the buffer must be zero-filled */
32199 memset(&((char*)pBuf)[nRead], 0, amt-nRead);
32200 return SQLITE_IOERR_SHORT_READ;
@@ -31802,11 +32241,11 @@
32241
32242 if( rc ){
32243 if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
32244 return SQLITE_FULL;
32245 }
32246 return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath);
32247 }
32248 return SQLITE_OK;
32249 }
32250
32251 /*
@@ -31830,14 +32269,14 @@
32269 nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
32270 }
32271
32272 /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
32273 if( seekWinFile(pFile, nByte) ){
32274 rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate1", pFile->zPath);
32275 }else if( 0==SetEndOfFile(pFile->h) ){
32276 pFile->lastErrno = GetLastError();
32277 rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate2", pFile->zPath);
32278 }
32279
32280 OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
32281 return rc;
32282 }
@@ -31855,10 +32294,11 @@
32294 ** Make sure all writes to a particular file are committed to disk.
32295 */
32296 static int winSync(sqlite3_file *id, int flags){
32297 #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
32298 winFile *pFile = (winFile*)id;
32299 BOOL rc;
32300 #else
32301 UNUSED_PARAMETER(id);
32302 #endif
32303
32304 assert( pFile );
@@ -31867,36 +32307,37 @@
32307 || (flags&0x0F)==SQLITE_SYNC_FULL
32308 );
32309
32310 OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
32311
32312 /* Unix cannot, but some systems may return SQLITE_FULL from here. This
32313 ** line is to test that doing so does not cause any problems.
32314 */
32315 SimulateDiskfullError( return SQLITE_FULL );
32316
32317 #ifndef SQLITE_TEST
32318 UNUSED_PARAMETER(flags);
32319 #else
32320 if( (flags&0x0F)==SQLITE_SYNC_FULL ){
32321 sqlite3_fullsync_count++;
32322 }
32323 sqlite3_sync_count++;
32324 #endif
32325
 
 
 
 
 
 
32326 /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
32327 ** no-op
32328 */
32329 #ifdef SQLITE_NO_SYNC
32330 return SQLITE_OK;
32331 #else
32332 rc = FlushFileBuffers(pFile->h);
32333 SimulateIOError( rc=FALSE );
32334 if( rc ){
32335 return SQLITE_OK;
32336 }else{
32337 pFile->lastErrno = GetLastError();
32338 return winLogError(SQLITE_IOERR_FSYNC, "winSync", pFile->zPath);
32339 }
32340 #endif
32341 }
32342
32343 /*
@@ -31913,11 +32354,11 @@
32354 lowerBits = GetFileSize(pFile->h, &upperBits);
32355 if( (lowerBits == INVALID_FILE_SIZE)
32356 && ((error = GetLastError()) != NO_ERROR) )
32357 {
32358 pFile->lastErrno = error;
32359 return winLogError(SQLITE_IOERR_FSTAT, "winFileSize", pFile->zPath);
32360 }
32361 *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
32362 return SQLITE_OK;
32363 }
32364
@@ -31952,10 +32393,11 @@
32393 res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
32394 #endif
32395 }
32396 if( res == 0 ){
32397 pFile->lastErrno = GetLastError();
32398 /* No need to log a failure to lock */
32399 }
32400 return res;
32401 }
32402
32403 /*
@@ -31970,12 +32412,13 @@
32412 #if SQLITE_OS_WINCE==0
32413 }else{
32414 res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
32415 #endif
32416 }
32417 if( res==0 && GetLastError()!=ERROR_NOT_LOCKED ){
32418 pFile->lastErrno = GetLastError();
32419 winLogError(SQLITE_IOERR_UNLOCK, "unlockReadLock", pFile->zPath);
32420 }
32421 return res;
32422 }
32423
32424 /*
@@ -32172,11 +32615,11 @@
32615 if( type>=EXCLUSIVE_LOCK ){
32616 UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
32617 if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
32618 /* This should never happen. We should always be able to
32619 ** reacquire the read lock */
32620 rc = winLogError(SQLITE_IOERR_UNLOCK, "winUnlock", pFile->zPath);
32621 }
32622 }
32623 if( type>=RESERVED_LOCK ){
32624 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
32625 }
@@ -32487,10 +32930,11 @@
32930 return SQLITE_NOMEM;
32931 }
32932 memset(pNew, 0, sizeof(*pNew));
32933 pNew->zFilename = (char*)&pNew[1];
32934 sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
32935 sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
32936
32937 /* Look to see if there is an existing winShmNode that can be used.
32938 ** If no matching winShmNode currently exists, create a new one.
32939 */
32940 winShmEnterMutex();
@@ -32529,11 +32973,11 @@
32973 ** If not, truncate the file to zero length.
32974 */
32975 if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
32976 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
32977 if( rc!=SQLITE_OK ){
32978 rc = winLogError(SQLITE_IOERR_SHMOPEN, "winOpenShm", pDbFd->zPath);
32979 }
32980 }
32981 if( rc==SQLITE_OK ){
32982 winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
32983 rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
@@ -32788,11 +33232,11 @@
33232 ** Check to see if it has been allocated (i.e. if the wal-index file is
33233 ** large enough to contain the requested region).
33234 */
33235 rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
33236 if( rc!=SQLITE_OK ){
33237 rc = winLogError(SQLITE_IOERR_SHMSIZE, "winShmMap1", pDbFd->zPath);
33238 goto shmpage_out;
33239 }
33240
33241 if( sz<nByte ){
33242 /* The requested memory region does not exist. If isWrite is set to
@@ -32802,11 +33246,11 @@
33246 ** the requested memory region.
33247 */
33248 if( !isWrite ) goto shmpage_out;
33249 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
33250 if( rc!=SQLITE_OK ){
33251 rc = winLogError(SQLITE_IOERR_SHMSIZE, "winShmMap2", pDbFd->zPath);
33252 goto shmpage_out;
33253 }
33254 }
33255
33256 /* Map the requested memory region into this processes address space. */
@@ -32839,11 +33283,11 @@
33283 (int)GetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion,
33284 pMap ? "ok" : "failed"));
33285 }
33286 if( !pMap ){
33287 pShmNode->lastErrno = GetLastError();
33288 rc = winLogError(SQLITE_IOERR_SHMMAP, "winShmMap3", pDbFd->zPath);
33289 if( hMap ) CloseHandle(hMap);
33290 goto shmpage_out;
33291 }
33292
33293 pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
@@ -32921,11 +33365,11 @@
33365 zConverted = utf8ToUnicode(zFilename);
33366 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
33367 */
33368 #if SQLITE_OS_WINCE==0
33369 }else{
33370 zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
33371 #endif
33372 }
33373 /* caller will handle out of memory */
33374 return zConverted;
33375 }
@@ -33001,72 +33445,10 @@
33445
33446 OSTRACE(("TEMP FILENAME: %s\n", zBuf));
33447 return SQLITE_OK;
33448 }
33449
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33450 /*
33451 ** Open a file.
33452 */
33453 static int winOpen(
33454 sqlite3_vfs *pVfs, /* Not used */
@@ -33234,10 +33616,11 @@
33616 h, zName, dwDesiredAccess,
33617 h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
33618
33619 if( h==INVALID_HANDLE_VALUE ){
33620 pFile->lastErrno = GetLastError();
33621 winLogError(SQLITE_CANTOPEN, "winOpen", zUtf8Name);
33622 free(zConverted);
33623 if( isReadWrite ){
33624 return winOpen(pVfs, zName, id,
33625 ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
33626 }else{
@@ -33337,11 +33720,12 @@
33720 OSTRACE(("DELETE \"%s\" %s\n", zFilename,
33721 ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
33722 "ok" : "failed" ));
33723
33724 return ( (rc == INVALID_FILE_ATTRIBUTES)
33725 && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK :
33726 winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename);
33727 }
33728
33729 /*
33730 ** Check the existance and status of a file.
33731 */
@@ -33377,10 +33761,11 @@
33761 }else{
33762 attr = sAttrData.dwFileAttributes;
33763 }
33764 }else{
33765 if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
33766 winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename);
33767 free(zConverted);
33768 return SQLITE_IOERR_ACCESS;
33769 }else{
33770 attr = INVALID_FILE_ATTRIBUTES;
33771 }
@@ -33440,10 +33825,17 @@
33825
33826 #if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
33827 int nByte;
33828 void *zConverted;
33829 char *zOut;
33830
33831 /* If this path name begins with "/X:", where "X" is any alphabetic
33832 ** character, discard the initial "/" from the pathname.
33833 */
33834 if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
33835 zRelative++;
33836 }
33837
33838 /* It's odd to simulate an io-error here, but really this is just
33839 ** using the io-error infrastructure to test that SQLite handles this
33840 ** function failing. This function could fail if, for example, the
33841 ** current working directory has been unlinked.
@@ -36252,10 +36644,11 @@
36644 #define _WAL_H_
36645
36646
36647 #ifdef SQLITE_OMIT_WAL
36648 # define sqlite3WalOpen(x,y,z) 0
36649 # define sqlite3WalLimit(x,y)
36650 # define sqlite3WalClose(w,x,y,z) 0
36651 # define sqlite3WalBeginReadTransaction(y,z) 0
36652 # define sqlite3WalEndReadTransaction(z)
36653 # define sqlite3WalRead(v,w,x,y,z) 0
36654 # define sqlite3WalDbsize(y) 0
@@ -36277,13 +36670,16 @@
36670 ** There is one object of this type for each pager.
36671 */
36672 typedef struct Wal Wal;
36673
36674 /* Open and close a connection to a write-ahead log. */
36675 SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
36676 SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
36677
36678 /* Set the limiting size of a WAL file. */
36679 SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
36680
36681 /* Used by readers to open (lock) and close (unlock) a snapshot. A
36682 ** snapshot is like a read-transaction. It is the state of the database
36683 ** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
36684 ** preserves the current state even if the other threads or processes
36685 ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
@@ -40628,10 +41024,12 @@
41024 int nPathname = 0; /* Number of bytes in zPathname */
41025 int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
41026 int noReadlock = (flags & PAGER_NO_READLOCK)!=0; /* True to omit read-lock */
41027 int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
41028 u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
41029 const char *zUri = 0; /* URI args to copy */
41030 int nUri = 0; /* Number of bytes of URI args at *zUri */
41031
41032 /* Figure out how much space is required for each journal file-handle
41033 ** (there are two of them, the main journal and the sub-journal). This
41034 ** is the maximum space required for an in-memory journal file handle
41035 ** and a regular journal file-handle. Note that a "regular journal-handle"
@@ -40658,18 +41056,25 @@
41056 /* Compute and store the full pathname in an allocated buffer pointed
41057 ** to by zPathname, length nPathname. Or, if this is a temporary file,
41058 ** leave both nPathname and zPathname set to 0.
41059 */
41060 if( zFilename && zFilename[0] ){
41061 const char *z;
41062 nPathname = pVfs->mxPathname+1;
41063 zPathname = sqlite3Malloc(nPathname*2);
41064 if( zPathname==0 ){
41065 return SQLITE_NOMEM;
41066 }
41067 zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
41068 rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
41069 nPathname = sqlite3Strlen30(zPathname);
41070 z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
41071 while( *z ){
41072 z += sqlite3Strlen30(z)+1;
41073 z += sqlite3Strlen30(z)+1;
41074 }
41075 nUri = &z[1] - zUri;
41076 if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
41077 /* This branch is taken when the journal path required by
41078 ** the database being opened will be more than pVfs->mxPathname
41079 ** bytes in length. This means the database cannot be opened,
41080 ** as it will not be possible to open the journal file or even
@@ -40698,11 +41103,11 @@
41103 pPtr = (u8 *)sqlite3MallocZero(
41104 ROUND8(sizeof(*pPager)) + /* Pager structure */
41105 ROUND8(pcacheSize) + /* PCache object */
41106 ROUND8(pVfs->szOsFile) + /* The main db file */
41107 journalFileSize * 2 + /* The two journal files */
41108 nPathname + 1 + nUri + /* zFilename */
41109 nPathname + 8 + 1 /* zJournal */
41110 #ifndef SQLITE_OMIT_WAL
41111 + nPathname + 4 + 1 /* zWal */
41112 #endif
41113 );
@@ -40720,18 +41125,21 @@
41125 assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
41126
41127 /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
41128 if( zPathname ){
41129 assert( nPathname>0 );
41130 pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
41131 memcpy(pPager->zFilename, zPathname, nPathname);
41132 memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
41133 memcpy(pPager->zJournal, zPathname, nPathname);
41134 memcpy(&pPager->zJournal[nPathname], "-journal", 8);
41135 sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
41136 #ifndef SQLITE_OMIT_WAL
41137 pPager->zWal = &pPager->zJournal[nPathname+8+1];
41138 memcpy(pPager->zWal, zPathname, nPathname);
41139 memcpy(&pPager->zWal[nPathname], "-wal", 4);
41140 sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
41141 #endif
41142 sqlite3_free(zPathname);
41143 }
41144 pPager->pVfs = pVfs;
41145 pPager->vfsFlags = vfsFlags;
@@ -42064,15 +42472,25 @@
42472 */
42473 sqlite3BackupRestart(pPager->pBackup);
42474 }else{
42475 if( pagerUseWal(pPager) ){
42476 PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
42477 PgHdr *pPageOne = 0;
42478 if( pList==0 ){
42479 /* Must have at least one page for the WAL commit flag.
42480 ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
42481 rc = sqlite3PagerGet(pPager, 1, &pPageOne);
42482 pList = pPageOne;
42483 pList->pDirty = 0;
42484 }
42485 assert( rc==SQLITE_OK );
42486 if( ALWAYS(pList) ){
42487 rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1,
42488 (pPager->fullSync ? pPager->syncFlags : 0)
42489 );
42490 }
42491 sqlite3PagerUnref(pPageOne);
42492 if( rc==SQLITE_OK ){
42493 sqlite3PcacheCleanAll(pPager->pPCache);
42494 }
42495 }else{
42496 /* The following block updates the change-counter. Exactly how it
@@ -42926,10 +43344,11 @@
43344 ** An attempt to set a limit smaller than -1 is a no-op.
43345 */
43346 SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
43347 if( iLimit>=-1 ){
43348 pPager->journalSizeLimit = iLimit;
43349 sqlite3WalLimit(pPager->pWal, iLimit);
43350 }
43351 return pPager->journalSizeLimit;
43352 }
43353
43354 /*
@@ -43017,11 +43436,12 @@
43436 /* Open the connection to the log file. If this operation fails,
43437 ** (e.g. due to malloc() failure), return an error code.
43438 */
43439 if( rc==SQLITE_OK ){
43440 rc = sqlite3WalOpen(pPager->pVfs,
43441 pPager->fd, pPager->zWal, pPager->exclusiveMode,
43442 pPager->journalSizeLimit, &pPager->pWal
43443 );
43444 }
43445
43446 return rc;
43447 }
@@ -43549,10 +43969,11 @@
43969 struct Wal {
43970 sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
43971 sqlite3_file *pDbFd; /* File handle for the database file */
43972 sqlite3_file *pWalFd; /* File handle for WAL file */
43973 u32 iCallback; /* Value to pass to log callback (or 0) */
43974 i64 mxWalSize; /* Truncate WAL to this size upon reset */
43975 int nWiData; /* Size of array apWiData */
43976 volatile u32 **apWiData; /* Pointer to wal-index content in memory */
43977 u32 szPage; /* Database page size */
43978 i16 readLock; /* Which read lock is being held. -1 for none */
43979 u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
@@ -44371,10 +44792,11 @@
44792 SQLITE_PRIVATE int sqlite3WalOpen(
44793 sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
44794 sqlite3_file *pDbFd, /* The open database file */
44795 const char *zWalName, /* Name of the WAL file */
44796 int bNoShm, /* True to run in heap-memory mode */
44797 i64 mxWalSize, /* Truncate WAL to this size on reset */
44798 Wal **ppWal /* OUT: Allocated Wal handle */
44799 ){
44800 int rc; /* Return Code */
44801 Wal *pRet; /* Object to allocate and return */
44802 int flags; /* Flags passed to OsOpen() */
@@ -44403,10 +44825,11 @@
44825
44826 pRet->pVfs = pVfs;
44827 pRet->pWalFd = (sqlite3_file *)&pRet[1];
44828 pRet->pDbFd = pDbFd;
44829 pRet->readLock = -1;
44830 pRet->mxWalSize = mxWalSize;
44831 pRet->zWalName = zWalName;
44832 pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
44833
44834 /* Open file handle on the write-ahead log file. */
44835 flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
@@ -44423,10 +44846,17 @@
44846 *ppWal = pRet;
44847 WALTRACE(("WAL%d: opened\n", pRet));
44848 }
44849 return rc;
44850 }
44851
44852 /*
44853 ** Change the size to which the WAL file is trucated on each reset.
44854 */
44855 SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
44856 if( pWal ) pWal->mxWalSize = iLimit;
44857 }
44858
44859 /*
44860 ** Find the smallest page number out of all pages held in the WAL that
44861 ** has not been returned by any prior invocation of this method on the
44862 ** same WalIterator object. Write into *piFrame the frame index where
@@ -45659,10 +46089,26 @@
46089 ** safe and means there is no special case for sqlite3WalUndo()
46090 ** to handle if this transaction is rolled back.
46091 */
46092 int i; /* Loop counter */
46093 u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */
46094
46095 /* Limit the size of WAL file if the journal_size_limit PRAGMA is
46096 ** set to a non-negative value. Log errors encountered
46097 ** during the truncation attempt. */
46098 if( pWal->mxWalSize>=0 ){
46099 i64 sz;
46100 int rx;
46101 rx = sqlite3OsFileSize(pWal->pWalFd, &sz);
46102 if( rx==SQLITE_OK && (sz > pWal->mxWalSize) ){
46103 rx = sqlite3OsTruncate(pWal->pWalFd, pWal->mxWalSize);
46104 }
46105 if( rx ){
46106 sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
46107 }
46108 }
46109
46110 pWal->nCkpt++;
46111 pWal->hdr.mxFrame = 0;
46112 sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
46113 aSalt[1] = salt1;
46114 walIndexWriteHdr(pWal);
@@ -47764,10 +48210,11 @@
48210 offset = PTRMAP_PTROFFSET(iPtrmap, key);
48211 if( offset<0 ){
48212 *pRC = SQLITE_CORRUPT_BKPT;
48213 goto ptrmap_exit;
48214 }
48215 assert( offset <= (int)pBt->usableSize-5 );
48216 pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
48217
48218 if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
48219 TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));
48220 *pRC= rc = sqlite3PagerWrite(pDbPage);
@@ -47803,10 +48250,15 @@
48250 return rc;
48251 }
48252 pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
48253
48254 offset = PTRMAP_PTROFFSET(iPtrmap, key);
48255 if( offset<0 ){
48256 sqlite3PagerUnref(pDbPage);
48257 return SQLITE_CORRUPT_BKPT;
48258 }
48259 assert( offset <= (int)pBt->usableSize-5 );
48260 assert( pEType!=0 );
48261 *pEType = pPtrmap[offset];
48262 if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
48263
48264 sqlite3PagerUnref(pDbPage);
@@ -48664,17 +49116,17 @@
49116 ** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
49117 ** objects in the same database connection since doing so will lead
49118 ** to problems with locking.
49119 */
49120 SQLITE_PRIVATE int sqlite3BtreeOpen(
49121 sqlite3_vfs *pVfs, /* VFS to use for this b-tree */
49122 const char *zFilename, /* Name of the file containing the BTree database */
49123 sqlite3 *db, /* Associated database handle */
49124 Btree **ppBtree, /* Pointer to new Btree object written here */
49125 int flags, /* Options */
49126 int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */
49127 ){
 
49128 BtShared *pBt = 0; /* Shared part of btree structure */
49129 Btree *p; /* Handle to return */
49130 sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */
49131 int rc = SQLITE_OK; /* Result code from this function */
49132 u8 nReserve; /* Byte of unused space on each page */
@@ -48692,10 +49144,11 @@
49144 const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
49145 || (isTempDb && sqlite3TempInMemory(db));
49146 #endif
49147
49148 assert( db!=0 );
49149 assert( pVfs!=0 );
49150 assert( sqlite3_mutex_held(db->mutex) );
49151 assert( (flags&0xff)==flags ); /* flags fit in 8 bits */
49152
49153 /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
49154 assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
@@ -48710,11 +49163,10 @@
49163 flags |= BTREE_MEMORY;
49164 }
49165 if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
49166 vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
49167 }
 
49168 p = sqlite3MallocZero(sizeof(Btree));
49169 if( !p ){
49170 return SQLITE_NOMEM;
49171 }
49172 p->inTrans = TRANS_NONE;
@@ -58781,10 +59233,11 @@
59233 sqlite3_randomness(sizeof(iRandom), &iRandom);
59234 zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, iRandom&0x7fffffff);
59235 if( !zMaster ){
59236 return SQLITE_NOMEM;
59237 }
59238 sqlite3FileSuffix3(zMainFile, zMaster);
59239 rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
59240 }while( rc==SQLITE_OK && res );
59241 if( rc==SQLITE_OK ){
59242 /* Open the master journal. */
59243 rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
@@ -58994,10 +59447,19 @@
59447 }
59448 }
59449 }
59450 db->nStatement--;
59451 p->iStatement = 0;
59452
59453 if( rc==SQLITE_OK ){
59454 if( eOp==SAVEPOINT_ROLLBACK ){
59455 rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
59456 }
59457 if( rc==SQLITE_OK ){
59458 rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
59459 }
59460 }
59461
59462 /* If the statement transaction is being rolled back, also restore the
59463 ** database handles deferred constraint counter to the value it had when
59464 ** the statement transaction was opened. */
59465 if( eOp==SAVEPOINT_ROLLBACK ){
@@ -59911,11 +60373,11 @@
60373 /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
60374 VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
60375
60376 /* Compilers may complain that mem1.u.i is potentially uninitialized.
60377 ** We could initialize it, as shown here, to silence those complaints.
60378 ** But in fact, mem1.u.i will never actually be used uninitialized, and doing
60379 ** the unnecessary initialization has a measurable negative performance
60380 ** impact, since this routine is a very high runner. And so, we choose
60381 ** to ignore the compiler warnings and leave this variable uninitialized.
60382 */
60383 /* mem1.u.i = 0; // not needed, here to silence compiler warning */
@@ -62326,10 +62788,11 @@
62788 Mem *pIn2 = 0; /* 2nd input operand */
62789 Mem *pIn3 = 0; /* 3rd input operand */
62790 Mem *pOut = 0; /* Output operand */
62791 int iCompare = 0; /* Result of last OP_Compare operation */
62792 int *aPermute = 0; /* Permutation of columns for OP_Compare */
62793 i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
62794 #ifdef VDBE_PROFILE
62795 u64 start; /* CPU clock count at start of opcode */
62796 int origPc; /* Program counter at start of opcode */
62797 #endif
62798 /********************************************************************
@@ -63004,10 +63467,11 @@
63467 VdbeFrame *pFrame = p->pFrame;
63468 p->pFrame = pFrame->pParent;
63469 p->nFrame--;
63470 sqlite3VdbeSetChanges(db, p->nChange);
63471 pc = sqlite3VdbeFrameRestore(pFrame);
63472 lastRowid = db->lastRowid;
63473 if( pOp->p2==OE_Ignore ){
63474 /* Instruction pc is the OP_Program that invoked the sub-program
63475 ** currently being halted. If the p2 instruction of this OP_Halt
63476 ** instruction is set to OE_Ignore, then the sub-program is throwing
63477 ** an IGNORE exception. In this case jump to the address specified
@@ -63576,11 +64040,13 @@
64040 assert( pOp>aOp );
64041 assert( pOp[-1].p4type==P4_COLLSEQ );
64042 assert( pOp[-1].opcode==OP_CollSeq );
64043 u.ag.ctx.pColl = pOp[-1].p4.pColl;
64044 }
64045 db->lastRowid = lastRowid;
64046 (*u.ag.ctx.pFunc->xFunc)(&u.ag.ctx, u.ag.n, u.ag.apVal); /* IMP: R-24505-23230 */
64047 lastRowid = db->lastRowid;
64048 if( db->mallocFailed ){
64049 /* Even though a malloc() has failed, the implementation of the
64050 ** user function may have called an sqlite3_result_XXX() function
64051 ** to return a value. The following call releases any resources
64052 ** associated with such a value.
@@ -64783,10 +65249,18 @@
65249 "SQL statements in progress");
65250 rc = SQLITE_BUSY;
65251 }else{
65252 u.aq.nName = sqlite3Strlen30(u.aq.zName);
65253
65254 /* This call is Ok even if this savepoint is actually a transaction
65255 ** savepoint (and therefore should not prompt xSavepoint()) callbacks.
65256 ** If this is a transaction savepoint being opened, it is guaranteed
65257 ** that the db->aVTrans[] array is empty. */
65258 assert( db->autoCommit==0 || db->nVTrans==0 );
65259 rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement);
65260 if( rc!=SQLITE_OK ) goto abort_due_to_error;
65261
65262 /* Create a new savepoint structure. */
65263 u.aq.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.aq.nName+1);
65264 if( u.aq.pNew ){
65265 u.aq.pNew->zName = (char *)&u.aq.pNew[1];
65266 memcpy(u.aq.pNew->zName, u.aq.zName, u.aq.nName+1);
@@ -64889,10 +65363,15 @@
65363 db->nSavepoint--;
65364 }
65365 }else{
65366 db->nDeferredCons = u.aq.pSavepoint->nDeferredCons;
65367 }
65368
65369 if( !isTransaction ){
65370 rc = sqlite3VtabSavepoint(db, u.aq.p1, u.aq.iSavepoint);
65371 if( rc!=SQLITE_OK ) goto abort_due_to_error;
65372 }
65373 }
65374 }
65375
65376 break;
65377 }
@@ -65028,11 +65507,15 @@
65507 if( p->iStatement==0 ){
65508 assert( db->nStatement>=0 && db->nSavepoint>=0 );
65509 db->nStatement++;
65510 p->iStatement = db->nSavepoint + db->nStatement;
65511 }
65512
65513 rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement);
65514 if( rc==SQLITE_OK ){
65515 rc = sqlite3BtreeBeginStmt(u.as.pBt, p->iStatement);
65516 }
65517
65518 /* Store the current value of the database handles deferred constraint
65519 ** counter. If the statement transaction needs to be rolled back,
65520 ** the value of this counter needs to be restored too. */
65521 p->nStmtDefCons = db->nDeferredCons;
@@ -65349,11 +65832,11 @@
65832
65833 assert( pOp->p1>=0 );
65834 u.ax.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
65835 if( u.ax.pCx==0 ) goto no_mem;
65836 u.ax.pCx->nullRow = 1;
65837 rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ax.pCx->pBt,
65838 BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
65839 if( rc==SQLITE_OK ){
65840 rc = sqlite3BtreeBeginTrans(u.ax.pCx->pBt, 1);
65841 }
65842 if( rc==SQLITE_OK ){
@@ -66023,11 +66506,11 @@
66506 ** engine starts picking positive candidate ROWIDs at random until
66507 ** it finds one that is not previously used. */
66508 assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
66509 ** an AUTOINCREMENT table. */
66510 /* on the first attempt, simply do one more than previous */
66511 u.be.v = lastRowid;
66512 u.be.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
66513 u.be.v++; /* ensure non-zero */
66514 u.be.cnt = 0;
66515 while( ((rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, 0, (u64)u.be.v,
66516 0, &u.be.res))==SQLITE_OK)
@@ -66135,11 +66618,11 @@
66618 assert( pOp->opcode==OP_InsertInt );
66619 u.bf.iKey = pOp->p3;
66620 }
66621
66622 if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
66623 if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bf.iKey;
66624 if( u.bf.pData->flags & MEM_Null ){
66625 u.bf.pData->z = 0;
66626 u.bf.pData->n = 0;
66627 }else{
66628 assert( u.bf.pData->flags & (MEM_Blob|MEM_Str) );
@@ -67261,11 +67744,11 @@
67744 assert( pc==u.by.pFrame->pc );
67745 }
67746
67747 p->nFrame++;
67748 u.by.pFrame->pParent = p->pFrame;
67749 u.by.pFrame->lastRowid = lastRowid;
67750 u.by.pFrame->nChange = p->nChange;
67751 p->nChange = 0;
67752 p->pFrame = u.by.pFrame;
67753 p->aMem = aMem = &VdbeFrameMem(u.by.pFrame)[-1];
67754 p->nMem = u.by.pFrame->nChildMem;
@@ -68072,31 +68555,45 @@
68555 sqlite_int64 rowid;
68556 Mem **apArg;
68557 Mem *pX;
68558 #endif /* local variables moved into u.cm */
68559
68560 assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
68561 || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
68562 );
68563 u.cm.pVtab = pOp->p4.pVtab->pVtab;
68564 u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
68565 u.cm.nArg = pOp->p2;
68566 assert( pOp->p4type==P4_VTAB );
68567 if( ALWAYS(u.cm.pModule->xUpdate) ){
68568 u8 vtabOnConflict = db->vtabOnConflict;
68569 u.cm.apArg = p->apArg;
68570 u.cm.pX = &aMem[pOp->p3];
68571 for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){
68572 assert( memIsValid(u.cm.pX) );
68573 memAboutToChange(p, u.cm.pX);
68574 sqlite3VdbeMemStoreType(u.cm.pX);
68575 u.cm.apArg[u.cm.i] = u.cm.pX;
68576 u.cm.pX++;
68577 }
68578 db->vtabOnConflict = pOp->p5;
68579 rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
68580 db->vtabOnConflict = vtabOnConflict;
68581 importVtabErrMsg(p, u.cm.pVtab);
68582 if( rc==SQLITE_OK && pOp->p1 ){
68583 assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) );
68584 db->lastRowid = lastRowid = u.cm.rowid;
68585 }
68586 if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
68587 if( pOp->p5==OE_Ignore ){
68588 rc = SQLITE_OK;
68589 }else{
68590 p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
68591 }
68592 }else{
68593 p->nChange++;
68594 }
68595 }
68596 break;
68597 }
68598 #endif /* SQLITE_OMIT_VIRTUALTABLE */
68599
@@ -68242,10 +68739,11 @@
68739
68740 /* This is the only way out of this procedure. We have to
68741 ** release the mutexes on btrees that were acquired at the
68742 ** top. */
68743 vdbe_return:
68744 db->lastRowid = lastRowid;
68745 sqlite3VdbeLeave(p);
68746 return rc;
68747
68748 /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
68749 ** is encountered.
@@ -75970,12 +76468,16 @@
76468 int i;
76469 int rc = 0;
76470 sqlite3 *db = sqlite3_context_db_handle(context);
76471 const char *zName;
76472 const char *zFile;
76473 char *zPath = 0;
76474 char *zErr = 0;
76475 unsigned int flags;
76476 Db *aNew;
76477 char *zErrDyn = 0;
76478 sqlite3_vfs *pVfs;
76479
76480 UNUSED_PARAMETER(NotUsed);
76481
76482 zFile = (const char *)sqlite3_value_text(argv[0]);
76483 zName = (const char *)sqlite3_value_text(argv[1]);
@@ -76024,12 +76526,22 @@
76526
76527 /* Open the database file. If the btree is successfully opened, use
76528 ** it to obtain the database schema. At this point the schema may
76529 ** or may not be initialised.
76530 */
76531 flags = db->openFlags;
76532 rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
76533 if( rc!=SQLITE_OK ){
76534 if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
76535 sqlite3_result_error(context, zErr, -1);
76536 sqlite3_free(zErr);
76537 return;
76538 }
76539 assert( pVfs );
76540 flags |= SQLITE_OPEN_MAIN_DB;
76541 rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
76542 sqlite3_free( zPath );
76543 db->nDb++;
76544 if( rc==SQLITE_CONSTRAINT ){
76545 rc = SQLITE_ERROR;
76546 zErrDyn = sqlite3MPrintf(db, "database is already attached");
76547 }else if( rc==SQLITE_OK ){
@@ -80139,11 +80651,11 @@
80651 SQLITE_OPEN_CREATE |
80652 SQLITE_OPEN_EXCLUSIVE |
80653 SQLITE_OPEN_DELETEONCLOSE |
80654 SQLITE_OPEN_TEMP_DB;
80655
80656 rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
80657 if( rc!=SQLITE_OK ){
80658 sqlite3ErrorMsg(pParse, "unable to open a temporary database "
80659 "file for storing temporary tables");
80660 pParse->rc = rc;
80661 return 1;
@@ -82329,10 +82841,25 @@
82841 UNUSED_PARAMETER2(NotUsed, NotUsed2);
82842 /* IMP: R-24470-31136 This function is an SQL wrapper around the
82843 ** sqlite3_sourceid() C interface. */
82844 sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
82845 }
82846
82847 /*
82848 ** Implementation of the sqlite_log() function. This is a wrapper around
82849 ** sqlite3_log(). The return value is NULL. The function exists purely for
82850 ** its side-effects.
82851 */
82852 static void errlogFunc(
82853 sqlite3_context *context,
82854 int argc,
82855 sqlite3_value **argv
82856 ){
82857 UNUSED_PARAMETER(argc);
82858 UNUSED_PARAMETER(context);
82859 sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1]));
82860 }
82861
82862 /*
82863 ** Implementation of the sqlite_compileoption_used() function.
82864 ** The result is an integer that identifies if the compiler option
82865 ** was used to build SQLite.
@@ -83097,10 +83624,11 @@
83624 FUNCTION(random, 0, 0, 0, randomFunc ),
83625 FUNCTION(randomblob, 1, 0, 0, randomBlob ),
83626 FUNCTION(nullif, 2, 0, 1, nullifFunc ),
83627 FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
83628 FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
83629 FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
83630 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
83631 FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
83632 FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
83633 #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
83634 FUNCTION(quote, 1, 0, 0, quoteFunc ),
@@ -85309,10 +85837,11 @@
85837 #ifndef SQLITE_OMIT_VIRTUALTABLE
85838 if( IsVirtual(pTab) ){
85839 const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
85840 sqlite3VtabMakeWritable(pParse, pTab);
85841 sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
85842 sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
85843 sqlite3MayAbort(pParse);
85844 }else
85845 #endif
85846 {
85847 int isReplace; /* Set to true if constraints may cause a replace */
@@ -86073,10 +86602,22 @@
86602 }
86603 #ifndef SQLITE_OMIT_CHECK
86604 if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
86605 return 0; /* Tables have different CHECK constraints. Ticket #2252 */
86606 }
86607 #endif
86608 #ifndef SQLITE_OMIT_FOREIGN_KEY
86609 /* Disallow the transfer optimization if the destination table constains
86610 ** any foreign key constraints. This is more restrictive than necessary.
86611 ** But the main beneficiary of the transfer optimization is the VACUUM
86612 ** command, and the VACUUM command disables foreign key constraints. So
86613 ** the extra complication to make this rule less restrictive is probably
86614 ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
86615 */
86616 if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
86617 return 0;
86618 }
86619 #endif
86620
86621 /* If we get this far, it means either:
86622 **
86623 ** * We can always do the transfer if the table contains an
@@ -87442,11 +87983,11 @@
87983 }
87984
87985 /*
87986 ** Interpret the given string as a boolean value.
87987 */
87988 SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z){
87989 return getSafetyLevel(z)&1;
87990 }
87991
87992 /*
87993 ** Interpret the given string as a locking mode value.
@@ -87612,11 +88153,11 @@
88153 /* Foreign key support may not be enabled or disabled while not
88154 ** in auto-commit mode. */
88155 mask &= ~(SQLITE_ForeignKeys);
88156 }
88157
88158 if( sqlite3GetBoolean(zRight) ){
88159 db->flags |= mask;
88160 }else{
88161 db->flags &= ~mask;
88162 }
88163
@@ -87826,11 +88367,11 @@
88367 if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
88368 Btree *pBt = pDb->pBt;
88369 int b = -1;
88370 assert( pBt!=0 );
88371 if( zRight ){
88372 b = sqlite3GetBoolean(zRight);
88373 }
88374 if( pId2->n==0 && b>=0 ){
88375 int ii;
88376 for(ii=0; ii<db->nDb; ii++){
88377 sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
@@ -88426,11 +88967,11 @@
88967 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
88968
88969 #ifndef NDEBUG
88970 if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
88971 if( zRight ){
88972 if( sqlite3GetBoolean(zRight) ){
88973 sqlite3ParserTrace(stderr, "parser: ");
88974 }else{
88975 sqlite3ParserTrace(0, 0);
88976 }
88977 }
@@ -88440,11 +88981,11 @@
88981 /* Reinstall the LIKE and GLOB functions. The variant of LIKE
88982 ** used will be case sensitive or not depending on the RHS.
88983 */
88984 if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
88985 if( zRight ){
88986 sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight));
88987 }
88988 }else
88989
88990 #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
88991 # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
@@ -94017,16 +94558,18 @@
94558 ** does, then we can assume that it consumes less space on disk and
94559 ** will therefore be cheaper to scan to determine the query result.
94560 ** In this case set iRoot to the root page number of the index b-tree
94561 ** and pKeyInfo to the KeyInfo structure required to navigate the
94562 ** index.
94563 **
94564 ** (2011-04-15) Do not do a full scan of an unordered index.
94565 **
94566 ** In practice the KeyInfo structure will not be used. It is only
94567 ** passed to keep OP_OpenRead happy.
94568 */
94569 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
94570 if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
94571 pBest = pIdx;
94572 }
94573 }
94574 if( pBest && pBest->nColumn<pTab->nCol ){
94575 iRoot = pBest->tnum;
@@ -95579,11 +96122,12 @@
96122 SrcList *pSrc, /* The virtual table to be modified */
96123 Table *pTab, /* The virtual table */
96124 ExprList *pChanges, /* The columns to change in the UPDATE statement */
96125 Expr *pRowidExpr, /* Expression used to recompute the rowid */
96126 int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
96127 Expr *pWhere, /* WHERE clause of the UPDATE statement */
96128 int onError /* ON CONFLICT strategy */
96129 );
96130 #endif /* SQLITE_OMIT_VIRTUALTABLE */
96131
96132 /*
96133 ** The most recently coded instruction was an OP_Column to retrieve the
@@ -95823,11 +96367,11 @@
96367
96368 #ifndef SQLITE_OMIT_VIRTUALTABLE
96369 /* Virtual tables must be handled separately */
96370 if( IsVirtual(pTab) ){
96371 updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
96372 pWhere, onError);
96373 pWhere = 0;
96374 pTabList = 0;
96375 goto update_cleanup;
96376 }
96377 #endif
@@ -96153,11 +96697,12 @@
96697 SrcList *pSrc, /* The virtual table to be modified */
96698 Table *pTab, /* The virtual table */
96699 ExprList *pChanges, /* The columns to change in the UPDATE statement */
96700 Expr *pRowid, /* Expression used to recompute the rowid */
96701 int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
96702 Expr *pWhere, /* WHERE clause of the UPDATE statement */
96703 int onError /* ON CONFLICT strategy */
96704 ){
96705 Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
96706 ExprList *pEList = 0; /* The result set of the SELECT statement */
96707 Select *pSelect = 0; /* The SELECT statement */
96708 Expr *pExpr; /* Temporary expression */
@@ -96210,10 +96755,11 @@
96755 for(i=0; i<pTab->nCol; i++){
96756 sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i);
96757 }
96758 sqlite3VtabMakeWritable(pParse, pTab);
96759 sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
96760 sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
96761 sqlite3MayAbort(pParse);
96762 sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1);
96763 sqlite3VdbeJumpHere(v, addr);
96764 sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
96765
@@ -96583,10 +97129,22 @@
97129 *************************************************************************
97130 ** This file contains code used to help implement virtual tables.
97131 */
97132 #ifndef SQLITE_OMIT_VIRTUALTABLE
97133
97134 /*
97135 ** Before a virtual table xCreate() or xConnect() method is invoked, the
97136 ** sqlite3.pVtabCtx member variable is set to point to an instance of
97137 ** this struct allocated on the stack. It is used by the implementation of
97138 ** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
97139 ** are invoked only from within xCreate and xConnect methods.
97140 */
97141 struct VtabCtx {
97142 Table *pTab;
97143 VTable *pVTable;
97144 };
97145
97146 /*
97147 ** The actual function that does the work of creating a new module.
97148 ** This function implements the sqlite3_create_module() and
97149 ** sqlite3_create_module_v2() interfaces.
97150 */
@@ -96611,17 +97169,17 @@
97169 pMod->pModule = pModule;
97170 pMod->pAux = pAux;
97171 pMod->xDestroy = xDestroy;
97172 pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
97173 if( pDel && pDel->xDestroy ){
97174 sqlite3ResetInternalSchema(db, -1);
97175 pDel->xDestroy(pDel->pAux);
97176 }
97177 sqlite3DbFree(db, pDel);
97178 if( pDel==pMod ){
97179 db->mallocFailed = 1;
97180 }
 
97181 }else if( xDestroy ){
97182 xDestroy(pAux);
97183 }
97184 rc = sqlite3ApiExit(db, SQLITE_OK);
97185 sqlite3_mutex_leave(db->mutex);
@@ -97003,10 +97561,11 @@
97561 Table *pTab,
97562 Module *pMod,
97563 int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
97564 char **pzErr
97565 ){
97566 VtabCtx sCtx;
97567 VTable *pVTable;
97568 int rc;
97569 const char *const*azArg = (const char *const*)pTab->azModuleArg;
97570 int nArg = pTab->nModuleArg;
97571 char *zErr = 0;
@@ -97022,16 +97581,18 @@
97581 return SQLITE_NOMEM;
97582 }
97583 pVTable->db = db;
97584 pVTable->pMod = pMod;
97585
97586 /* Invoke the virtual table constructor */
97587 assert( &db->pVtabCtx );
97588 assert( xConstruct );
97589 sCtx.pTab = pTab;
97590 sCtx.pVTable = pVTable;
97591 db->pVtabCtx = &sCtx;
97592 rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
97593 db->pVtabCtx = 0;
97594 if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
97595
97596 if( SQLITE_OK!=rc ){
97597 if( zErr==0 ){
97598 *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
@@ -97043,11 +97604,11 @@
97604 }else if( ALWAYS(pVTable->pVtab) ){
97605 /* Justification of ALWAYS(): A correct vtab constructor must allocate
97606 ** the sqlite3_vtab object if successful. */
97607 pVTable->pVtab->pModule = pMod->pModule;
97608 pVTable->nRef = 1;
97609 if( sCtx.pTab ){
97610 const char *zFormat = "vtable constructor did not declare schema: %s";
97611 *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
97612 sqlite3VtabUnlock(pVTable);
97613 rc = SQLITE_ERROR;
97614 }else{
@@ -97091,11 +97652,10 @@
97652 }
97653 }
97654 }
97655
97656 sqlite3DbFree(db, zModuleName);
 
97657 return rc;
97658 }
97659
97660 /*
97661 ** This function is invoked by the parser to call the xConnect() method
@@ -97211,12 +97771,11 @@
97771 int rc = SQLITE_OK;
97772 Table *pTab;
97773 char *zErr = 0;
97774
97775 sqlite3_mutex_enter(db->mutex);
97776 if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
 
97777 sqlite3Error(db, SQLITE_MISUSE, 0);
97778 sqlite3_mutex_leave(db->mutex);
97779 return SQLITE_MISUSE_BKPT;
97780 }
97781 assert( (pTab->tabFlags & TF_Virtual)!=0 );
@@ -97239,11 +97798,11 @@
97798 pTab->aCol = pParse->pNewTable->aCol;
97799 pTab->nCol = pParse->pNewTable->nCol;
97800 pParse->pNewTable->nCol = 0;
97801 pParse->pNewTable->aCol = 0;
97802 }
97803 db->pVtabCtx->pTab = 0;
97804 }else{
97805 sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
97806 sqlite3DbFree(db, zErr);
97807 rc = SQLITE_ERROR;
97808 }
@@ -97391,11 +97950,10 @@
97950 pModule = pVTab->pVtab->pModule;
97951
97952 if( pModule->xBegin ){
97953 int i;
97954
 
97955 /* If pVtab is already in the aVTrans array, return early */
97956 for(i=0; i<db->nVTrans; i++){
97957 if( db->aVTrans[i]==pVTab ){
97958 return SQLITE_OK;
97959 }
@@ -97404,10 +97962,53 @@
97962 /* Invoke the xBegin method */
97963 rc = pModule->xBegin(pVTab->pVtab);
97964 if( rc==SQLITE_OK ){
97965 rc = addToVTrans(db, pVTab);
97966 }
97967 }
97968 return rc;
97969 }
97970
97971 /*
97972 ** Invoke either the xSavepoint, xRollbackTo or xRelease method of all
97973 ** virtual tables that currently have an open transaction. Pass iSavepoint
97974 ** as the second argument to the virtual table method invoked.
97975 **
97976 ** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is
97977 ** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is
97978 ** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with
97979 ** an open transaction is invoked.
97980 **
97981 ** If any virtual table method returns an error code other than SQLITE_OK,
97982 ** processing is abandoned and the error returned to the caller of this
97983 ** function immediately. If all calls to virtual table methods are successful,
97984 ** SQLITE_OK is returned.
97985 */
97986 SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
97987 int rc = SQLITE_OK;
97988
97989 assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
97990 if( db->aVTrans ){
97991 int i;
97992 for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
97993 const sqlite3_module *pMod = db->aVTrans[i]->pMod->pModule;
97994 if( pMod->iVersion>=2 ){
97995 int (*xMethod)(sqlite3_vtab *, int);
97996 switch( op ){
97997 case SAVEPOINT_BEGIN:
97998 xMethod = pMod->xSavepoint;
97999 break;
98000 case SAVEPOINT_ROLLBACK:
98001 xMethod = pMod->xRollbackTo;
98002 break;
98003 default:
98004 xMethod = pMod->xRelease;
98005 break;
98006 }
98007 if( xMethod ) rc = xMethod(db->aVTrans[i]->pVtab, iSavepoint);
98008 }
98009 }
98010 }
98011 return rc;
98012 }
98013
98014 /*
@@ -97505,10 +98106,61 @@
98106 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
98107 }else{
98108 pToplevel->db->mallocFailed = 1;
98109 }
98110 }
98111
98112 /*
98113 ** Return the ON CONFLICT resolution mode in effect for the virtual
98114 ** table update operation currently in progress.
98115 **
98116 ** The results of this routine are undefined unless it is called from
98117 ** within an xUpdate method.
98118 */
98119 SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){
98120 static const unsigned char aMap[] = {
98121 SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
98122 };
98123 assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
98124 assert( OE_Ignore==4 && OE_Replace==5 );
98125 assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
98126 return (int)aMap[db->vtabOnConflict-1];
98127 }
98128
98129 /*
98130 ** Call from within the xCreate() or xConnect() methods to provide
98131 ** the SQLite core with additional information about the behavior
98132 ** of the virtual table being implemented.
98133 */
98134 SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
98135 va_list ap;
98136 int rc = SQLITE_OK;
98137
98138 sqlite3_mutex_enter(db->mutex);
98139
98140 va_start(ap, op);
98141 switch( op ){
98142 case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
98143 VtabCtx *p = db->pVtabCtx;
98144 if( !p ){
98145 rc = SQLITE_MISUSE_BKPT;
98146 }else{
98147 assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
98148 p->pVTable->bConstraint = (u8)va_arg(ap, int);
98149 }
98150 break;
98151 }
98152 default:
98153 rc = SQLITE_MISUSE_BKPT;
98154 break;
98155 }
98156 va_end(ap);
98157
98158 if( rc!=SQLITE_OK ) sqlite3Error(db, rc, 0);
98159 sqlite3_mutex_leave(db->mutex);
98160 return rc;
98161 }
98162
98163 #endif /* SQLITE_OMIT_VIRTUALTABLE */
98164
98165 /************** End of vtab.c ************************************************/
98166 /************** Begin file where.c *******************************************/
@@ -107527,10 +108179,15 @@
108179 typedef void(*LOGFUNC_t)(void*,int,const char*);
108180 sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
108181 sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
108182 break;
108183 }
108184
108185 case SQLITE_CONFIG_URI: {
108186 sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
108187 break;
108188 }
108189
108190 default: {
108191 rc = SQLITE_ERROR;
108192 break;
108193 }
@@ -108886,25 +109543,257 @@
109543 }
109544 db->aLimit[limitId] = newLimit;
109545 }
109546 return oldLimit; /* IMP: R-53341-35419 */
109547 }
109548
109549 /*
109550 ** This function is used to parse both URIs and non-URI filenames passed by the
109551 ** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
109552 ** URIs specified as part of ATTACH statements.
109553 **
109554 ** The first argument to this function is the name of the VFS to use (or
109555 ** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
109556 ** query parameter. The second argument contains the URI (or non-URI filename)
109557 ** itself. When this function is called the *pFlags variable should contain
109558 ** the default flags to open the database handle with. The value stored in
109559 ** *pFlags may be updated before returning if the URI filename contains
109560 ** "cache=xxx" or "mode=xxx" query parameters.
109561 **
109562 ** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
109563 ** the VFS that should be used to open the database file. *pzFile is set to
109564 ** point to a buffer containing the name of the file to open. It is the
109565 ** responsibility of the caller to eventually call sqlite3_free() to release
109566 ** this buffer.
109567 **
109568 ** If an error occurs, then an SQLite error code is returned and *pzErrMsg
109569 ** may be set to point to a buffer containing an English language error
109570 ** message. It is the responsibility of the caller to eventually release
109571 ** this buffer by calling sqlite3_free().
109572 */
109573 SQLITE_PRIVATE int sqlite3ParseUri(
109574 const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
109575 const char *zUri, /* Nul-terminated URI to parse */
109576 unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */
109577 sqlite3_vfs **ppVfs, /* OUT: VFS to use */
109578 char **pzFile, /* OUT: Filename component of URI */
109579 char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
109580 ){
109581 int rc = SQLITE_OK;
109582 unsigned int flags = *pFlags;
109583 const char *zVfs = zDefaultVfs;
109584 char *zFile;
109585 char c;
109586 int nUri = sqlite3Strlen30(zUri);
109587
109588 assert( *pzErrMsg==0 );
109589
109590 if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
109591 && nUri>=5 && memcmp(zUri, "file:", 5)==0
109592 ){
109593 char *zOpt;
109594 int eState; /* Parser state when parsing URI */
109595 int iIn; /* Input character index */
109596 int iOut = 0; /* Output character index */
109597 int nByte = nUri+2; /* Bytes of space to allocate */
109598
109599 /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
109600 ** method that there may be extra parameters following the file-name. */
109601 flags |= SQLITE_OPEN_URI;
109602
109603 for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
109604 zFile = sqlite3_malloc(nByte);
109605 if( !zFile ) return SQLITE_NOMEM;
109606
109607 /* Discard the scheme and authority segments of the URI. */
109608 if( zUri[5]=='/' && zUri[6]=='/' ){
109609 iIn = 7;
109610 while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
109611
109612 if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
109613 *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
109614 iIn-7, &zUri[7]);
109615 rc = SQLITE_ERROR;
109616 goto parse_uri_out;
109617 }
109618 }else{
109619 iIn = 5;
109620 }
109621
109622 /* Copy the filename and any query parameters into the zFile buffer.
109623 ** Decode %HH escape codes along the way.
109624 **
109625 ** Within this loop, variable eState may be set to 0, 1 or 2, depending
109626 ** on the parsing context. As follows:
109627 **
109628 ** 0: Parsing file-name.
109629 ** 1: Parsing name section of a name=value query parameter.
109630 ** 2: Parsing value section of a name=value query parameter.
109631 */
109632 eState = 0;
109633 while( (c = zUri[iIn])!=0 && c!='#' ){
109634 iIn++;
109635 if( c=='%'
109636 && sqlite3Isxdigit(zUri[iIn])
109637 && sqlite3Isxdigit(zUri[iIn+1])
109638 ){
109639 int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
109640 octet += sqlite3HexToInt(zUri[iIn++]);
109641
109642 assert( octet>=0 && octet<256 );
109643 if( octet==0 ){
109644 /* This branch is taken when "%00" appears within the URI. In this
109645 ** case we ignore all text in the remainder of the path, name or
109646 ** value currently being parsed. So ignore the current character
109647 ** and skip to the next "?", "=" or "&", as appropriate. */
109648 while( (c = zUri[iIn])!=0 && c!='#'
109649 && (eState!=0 || c!='?')
109650 && (eState!=1 || (c!='=' && c!='&'))
109651 && (eState!=2 || c!='&')
109652 ){
109653 iIn++;
109654 }
109655 continue;
109656 }
109657 c = octet;
109658 }else if( eState==1 && (c=='&' || c=='=') ){
109659 if( zFile[iOut-1]==0 ){
109660 /* An empty option name. Ignore this option altogether. */
109661 while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
109662 continue;
109663 }
109664 if( c=='&' ){
109665 zFile[iOut++] = '\0';
109666 }else{
109667 eState = 2;
109668 }
109669 c = 0;
109670 }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
109671 c = 0;
109672 eState = 1;
109673 }
109674 zFile[iOut++] = c;
109675 }
109676 if( eState==1 ) zFile[iOut++] = '\0';
109677 zFile[iOut++] = '\0';
109678 zFile[iOut++] = '\0';
109679
109680 /* Check if there were any options specified that should be interpreted
109681 ** here. Options that are interpreted here include "vfs" and those that
109682 ** correspond to flags that may be passed to the sqlite3_open_v2()
109683 ** method. */
109684 zOpt = &zFile[sqlite3Strlen30(zFile)+1];
109685 while( zOpt[0] ){
109686 int nOpt = sqlite3Strlen30(zOpt);
109687 char *zVal = &zOpt[nOpt+1];
109688 int nVal = sqlite3Strlen30(zVal);
109689
109690 if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
109691 zVfs = zVal;
109692 }else{
109693 struct OpenMode {
109694 const char *z;
109695 int mode;
109696 } *aMode = 0;
109697 char *zModeType;
109698 int mask;
109699 int limit;
109700
109701 if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
109702 static struct OpenMode aCacheMode[] = {
109703 { "shared", SQLITE_OPEN_SHAREDCACHE },
109704 { "private", SQLITE_OPEN_PRIVATECACHE },
109705 { 0, 0 }
109706 };
109707
109708 mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
109709 aMode = aCacheMode;
109710 limit = mask;
109711 zModeType = "cache";
109712 }
109713 if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
109714 static struct OpenMode aOpenMode[] = {
109715 { "ro", SQLITE_OPEN_READONLY },
109716 { "rw", SQLITE_OPEN_READWRITE },
109717 { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
109718 { 0, 0 }
109719 };
109720
109721 mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
109722 aMode = aOpenMode;
109723 limit = mask & flags;
109724 zModeType = "access";
109725 }
109726
109727 if( aMode ){
109728 int i;
109729 int mode = 0;
109730 for(i=0; aMode[i].z; i++){
109731 const char *z = aMode[i].z;
109732 if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
109733 mode = aMode[i].mode;
109734 break;
109735 }
109736 }
109737 if( mode==0 ){
109738 *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
109739 rc = SQLITE_ERROR;
109740 goto parse_uri_out;
109741 }
109742 if( mode>limit ){
109743 *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
109744 zModeType, zVal);
109745 rc = SQLITE_PERM;
109746 goto parse_uri_out;
109747 }
109748 flags = (flags & ~mask) | mode;
109749 }
109750 }
109751
109752 zOpt = &zVal[nVal+1];
109753 }
109754
109755 }else{
109756 zFile = sqlite3_malloc(nUri+2);
109757 if( !zFile ) return SQLITE_NOMEM;
109758 memcpy(zFile, zUri, nUri);
109759 zFile[nUri] = '\0';
109760 zFile[nUri+1] = '\0';
109761 }
109762
109763 *ppVfs = sqlite3_vfs_find(zVfs);
109764 if( *ppVfs==0 ){
109765 *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
109766 rc = SQLITE_ERROR;
109767 }
109768 parse_uri_out:
109769 if( rc!=SQLITE_OK ){
109770 sqlite3_free(zFile);
109771 zFile = 0;
109772 }
109773 *pFlags = flags;
109774 *pzFile = zFile;
109775 return rc;
109776 }
109777
109778
109779 /*
109780 ** This routine does the work of opening a database on behalf of
109781 ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
109782 ** is UTF-8 encoded.
109783 */
109784 static int openDatabase(
109785 const char *zFilename, /* Database filename UTF-8 encoded */
109786 sqlite3 **ppDb, /* OUT: Returned database handle */
109787 unsigned int flags, /* Operational flags */
109788 const char *zVfs /* Name of the VFS to use */
109789 ){
109790 sqlite3 *db; /* Store allocated handle here */
109791 int rc; /* Return code */
109792 int isThreadsafe; /* True for threadsafe connections */
109793 char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
109794 char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
109795
109796 *ppDb = 0;
109797 #ifndef SQLITE_OMIT_AUTOINIT
109798 rc = sqlite3_initialize();
109799 if( rc ) return rc;
@@ -108924,11 +109813,11 @@
109813 assert( SQLITE_OPEN_READWRITE == 0x02 );
109814 assert( SQLITE_OPEN_CREATE == 0x04 );
109815 testcase( (1<<(flags&7))==0x02 ); /* READONLY */
109816 testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
109817 testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
109818 if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;
109819
109820 if( sqlite3GlobalConfig.bCoreMutex==0 ){
109821 isThreadsafe = 0;
109822 }else if( flags & SQLITE_OPEN_NOMUTEX ){
109823 isThreadsafe = 0;
@@ -109005,17 +109894,10 @@
109894 sqlite3HashInit(&db->aCollSeq);
109895 #ifndef SQLITE_OMIT_VIRTUALTABLE
109896 sqlite3HashInit(&db->aModule);
109897 #endif
109898
 
 
 
 
 
 
 
109899 /* Add the default collation sequence BINARY. BINARY works for both UTF-8
109900 ** and UTF-16, so add a version for each to avoid any unnecessary
109901 ** conversions. The only error that can occur here is a malloc() failure.
109902 */
109903 createCollation(db, "BINARY", SQLITE_UTF8, SQLITE_COLL_BINARY, 0,
@@ -109034,13 +109916,22 @@
109916
109917 /* Also add a UTF-8 case-insensitive collation sequence. */
109918 createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
109919 nocaseCollatingFunc, 0);
109920
109921 /* Parse the filename/URI argument. */
109922 db->openFlags = flags;
109923 rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
109924 if( rc!=SQLITE_OK ){
109925 if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
109926 sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
109927 sqlite3_free(zErrMsg);
109928 goto opendb_out;
109929 }
109930
109931 /* Open the backend database driver */
109932 rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
109933 flags | SQLITE_OPEN_MAIN_DB);
109934 if( rc!=SQLITE_OK ){
109935 if( rc==SQLITE_IOERR_NOMEM ){
109936 rc = SQLITE_NOMEM;
109937 }
@@ -109129,10 +110020,11 @@
110020 sqlite3GlobalConfig.nLookaside);
110021
110022 sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
110023
110024 opendb_out:
110025 sqlite3_free(zOpen);
110026 if( db ){
110027 assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
110028 sqlite3_mutex_leave(db->mutex);
110029 }
110030 rc = sqlite3_errcode(db);
@@ -109160,11 +110052,11 @@
110052 const char *filename, /* Database filename (UTF-8) */
110053 sqlite3 **ppDb, /* OUT: SQLite db handle */
110054 int flags, /* Flags */
110055 const char *zVfs /* Name of VFS module to use */
110056 ){
110057 return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
110058 }
110059
110060 #ifndef SQLITE_OMIT_UTF16
110061 /*
110062 ** Open a new database handle.
@@ -109770,10 +110662,32 @@
110662 }
110663 va_end(ap);
110664 #endif /* SQLITE_OMIT_BUILTIN_TEST */
110665 return rc;
110666 }
110667
110668 /*
110669 ** This is a utility routine, useful to VFS implementations, that checks
110670 ** to see if a database file was a URI that contained a specific query
110671 ** parameter, and if so obtains the value of the query parameter.
110672 **
110673 ** The zFilename argument is the filename pointer passed into the xOpen()
110674 ** method of a VFS implementation. The zParam argument is the name of the
110675 ** query parameter we seek. This routine returns the value of the zParam
110676 ** parameter if it exists. If the parameter does not exist, this routine
110677 ** returns a NULL pointer.
110678 */
110679 SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
110680 zFilename += sqlite3Strlen30(zFilename) + 1;
110681 while( zFilename[0] ){
110682 int x = strcmp(zFilename, zParam);
110683 zFilename += sqlite3Strlen30(zFilename) + 1;
110684 if( x==0 ) return zFilename;
110685 zFilename += sqlite3Strlen30(zFilename) + 1;
110686 }
110687 return 0;
110688 }
110689
110690 /************** End of main.c ************************************************/
110691 /************** Begin file notify.c ******************************************/
110692 /*
110693 ** 2009 March 3
@@ -110851,10 +111765,11 @@
111765 Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
111766 sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
111767 char *pNextId; /* Pointer into the body of aDoclist */
111768 char *aDoclist; /* List of docids for full-text queries */
111769 int nDoclist; /* Size of buffer at aDoclist */
111770 int desc; /* True to sort in descending order */
111771 int eEvalmode; /* An FTS3_EVAL_XX constant */
111772 int nRowAvg; /* Average size of database rows, in pages */
111773
111774 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
111775 u32 *aMatchinfo; /* Information about most recent match */
@@ -111033,11 +111948,11 @@
111948 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
111949 SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
111950 SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
111951 SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
111952
111953 SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Cursor *, Fts3Expr *, sqlite3_int64, int);
111954 SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Cursor *, Fts3Expr *);
111955 SQLITE_PRIVATE int sqlite3Fts3ExprLoadFtDoclist(Fts3Cursor *, Fts3Expr *, char **, int *);
111956 SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
111957
111958 /* fts3_tokenizer.c */
@@ -111060,10 +111975,11 @@
111975 char **, int, int, const char *, int, Fts3Expr **
111976 );
111977 SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
111978 #ifdef SQLITE_TEST
111979 SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
111980 SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
111981 #endif
111982
111983 /* fts3_aux.c */
111984 SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
111985
@@ -111180,10 +112096,38 @@
112096 static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
112097 sqlite3_int64 iVal;
112098 *pp += sqlite3Fts3GetVarint(*pp, &iVal);
112099 *pVal += iVal;
112100 }
112101
112102 /*
112103 ** When this function is called, *pp points to the first byte following a
112104 ** varint that is part of a doclist (or position-list, or any other list
112105 ** of varints). This function moves *pp to point to the start of that varint,
112106 ** and decrements the value stored in *pVal by the varint value.
112107 **
112108 ** Argument pStart points to the first byte of the doclist that the
112109 ** varint is part of.
112110 */
112111 static void fts3GetReverseDeltaVarint(
112112 char **pp,
112113 char *pStart,
112114 sqlite3_int64 *pVal
112115 ){
112116 sqlite3_int64 iVal;
112117 char *p = *pp;
112118
112119 /* Pointer p now points at the first byte past the varint we are
112120 ** interested in. So, unless the doclist is corrupt, the 0x80 bit is
112121 ** clear on character p[-1]. */
112122 for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
112123 p++;
112124 *pp = p;
112125
112126 sqlite3Fts3GetVarint(p, &iVal);
112127 *pVal -= iVal;
112128 }
112129
112130 /*
112131 ** As long as *pp has not reached its end (pEnd), then do the same
112132 ** as fts3GetDeltaVarint(): read a single varint and add it to *pVal.
112133 ** But if we have reached the end of the varint, just set *pp=0 and
@@ -111285,10 +112229,12 @@
112229 if( *pRc==SQLITE_OK ){
112230 int i; /* Iterator variable */
112231 int rc; /* Return code */
112232 char *zSql; /* SQL statement passed to declare_vtab() */
112233 char *zCols; /* List of user defined columns */
112234
112235 sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
112236
112237 /* Create a list of user columns for the virtual table */
112238 zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
112239 for(i=1; zCols && i<p->nColumn; i++){
112240 zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
@@ -111854,10 +112800,26 @@
112800
112801 if( iCons>=0 ){
112802 pInfo->aConstraintUsage[iCons].argvIndex = 1;
112803 pInfo->aConstraintUsage[iCons].omit = 1;
112804 }
112805
112806 /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
112807 ** docid) order. Both ascending and descending are possible.
112808 */
112809 if( pInfo->nOrderBy==1 ){
112810 struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0];
112811 if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){
112812 if( pOrder->desc ){
112813 pInfo->idxStr = "DESC";
112814 }else{
112815 pInfo->idxStr = "ASC";
112816 }
112817 }
112818 pInfo->orderByConsumed = 1;
112819 }
112820
112821 return SQLITE_OK;
112822 }
112823
112824 /*
112825 ** Implementation of xOpen method.
@@ -111911,11 +112873,11 @@
112873 if( rc==SQLITE_OK ){
112874 /* If no row was found and no error has occured, then the %_content
112875 ** table is missing a row that is present in the full-text index.
112876 ** The data structures are corrupt.
112877 */
112878 rc = SQLITE_CORRUPT_VTAB;
112879 }
112880 pCsr->isEof = 1;
112881 if( pContext ){
112882 sqlite3_result_error_code(pContext, rc);
112883 }
@@ -111971,11 +112933,11 @@
112933 ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
112934 */
112935 zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
112936 zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
112937 if( zCsr>zEnd ){
112938 return SQLITE_CORRUPT_VTAB;
112939 }
112940
112941 while( zCsr<zEnd && (piFirst || piLast) ){
112942 int cmp; /* memcmp() result */
112943 int nSuffix; /* Size of term suffix */
@@ -111989,11 +112951,11 @@
112951 }
112952 isFirstTerm = 0;
112953 zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
112954
112955 if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
112956 rc = SQLITE_CORRUPT_VTAB;
112957 goto finish_scan;
112958 }
112959 if( nPrefix+nSuffix>nAlloc ){
112960 char *zNew;
112961 nAlloc = (nPrefix+nSuffix) * 2;
@@ -113758,16 +114720,24 @@
114720 rc = sqlite3_reset(pCsr->pStmt);
114721 break;
114722 }
114723 pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
114724 }else{
114725 if( pCsr->desc==0 ){
114726 if( pCsr->pNextId>=&pCsr->aDoclist[pCsr->nDoclist] ){
114727 pCsr->isEof = 1;
114728 break;
114729 }
114730 fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
114731 }else{
114732 fts3GetReverseDeltaVarint(&pCsr->pNextId,pCsr->aDoclist,&pCsr->iPrevId);
114733 if( pCsr->pNextId<=pCsr->aDoclist ){
114734 pCsr->isEof = 1;
114735 break;
114736 }
114737 }
114738 sqlite3_reset(pCsr->pStmt);
 
114739 pCsr->isRequireSeek = 1;
114740 pCsr->isMatchinfoNeeded = 1;
114741 }
114742 }while( SQLITE_OK==(rc = fts3EvalDeferred(pCsr, &res)) && res==0 );
114743
@@ -113796,12 +114766,12 @@
114766 const char *idxStr, /* Unused */
114767 int nVal, /* Number of elements in apVal */
114768 sqlite3_value **apVal /* Arguments for the indexing scheme */
114769 ){
114770 const char *azSql[] = {
114771 "SELECT %s FROM %Q.'%q_content' AS x WHERE docid = ?", /* non-full-scan */
114772 "SELECT %s FROM %Q.'%q_content' AS x ORDER BY docid %s", /* full-scan */
114773 };
114774 int rc; /* Return code */
114775 char *zSql; /* SQL statement used to access %_content */
114776 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
114777 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
@@ -113853,11 +114823,13 @@
114823 ** statement loops through all rows of the %_content table. For a
114824 ** full-text query or docid lookup, the statement retrieves a single
114825 ** row by docid.
114826 */
114827 zSql = (char *)azSql[idxNum==FTS3_FULLSCAN_SEARCH];
114828 zSql = sqlite3_mprintf(
114829 zSql, p->zReadExprlist, p->zDb, p->zName, (idxStr ? idxStr : "ASC")
114830 );
114831 if( !zSql ){
114832 rc = SQLITE_NOMEM;
114833 }else{
114834 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
114835 sqlite3_free(zSql);
@@ -113865,11 +114837,26 @@
114837 if( rc==SQLITE_OK && idxNum==FTS3_DOCID_SEARCH ){
114838 rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
114839 }
114840 pCsr->eSearch = (i16)idxNum;
114841
114842 assert( pCsr->desc==0 );
114843 if( rc!=SQLITE_OK ) return rc;
114844 if( rc==SQLITE_OK && pCsr->nDoclist>0 && idxStr && idxStr[0]=='D' ){
114845 sqlite3_int64 iDocid = 0;
114846 char *csr = pCsr->aDoclist;
114847 while( csr<&pCsr->aDoclist[pCsr->nDoclist] ){
114848 fts3GetDeltaVarint(&csr, &iDocid);
114849 }
114850 pCsr->pNextId = csr;
114851 pCsr->iPrevId = iDocid;
114852 pCsr->desc = 1;
114853 pCsr->isRequireSeek = 1;
114854 pCsr->isMatchinfoNeeded = 1;
114855 pCsr->eEvalmode = FTS3_EVAL_NEXT;
114856 return SQLITE_OK;
114857 }
114858 return fts3NextMethod(pCursor);
114859 }
114860
114861 /*
114862 ** This is the xEof method of the virtual table. SQLite calls this
@@ -114017,17 +115004,37 @@
115004 pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
115005 rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
115006 pCsr->eEvalmode = FTS3_EVAL_NEXT;
115007 return rc;
115008 }
115009
115010
115011 /*
115012 ** When called, *ppPoslist must point to the byte immediately following the
115013 ** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
115014 ** moves *ppPoslist so that it instead points to the first byte of the
115015 ** same position list.
115016 */
115017 static void fts3ReversePoslist(char *pStart, char **ppPoslist){
115018 char *p = &(*ppPoslist)[-3];
115019 char c = p[1];
115020 while( p>pStart && (*p & 0x80) | c ){
115021 c = *p--;
115022 }
115023 if( p>pStart ){ p = &p[2]; }
115024 while( *p++&0x80 );
115025 *ppPoslist = p;
115026 }
115027
115028
115029 /*
115030 ** After ExprLoadDoclist() (see above) has been called, this function is
115031 ** used to iterate/search through the position lists that make up the doclist
115032 ** stored in pExpr->aDoclist.
115033 */
115034 SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
115035 Fts3Cursor *pCursor, /* Associate FTS3 cursor */
115036 Fts3Expr *pExpr, /* Access this expressions doclist */
115037 sqlite3_int64 iDocid, /* Docid associated with requested pos-list */
115038 int iCol /* Column of requested pos-list */
115039 ){
115040 assert( pExpr->isLoaded );
@@ -114034,23 +115041,39 @@
115041 if( pExpr->aDoclist ){
115042 char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
115043 char *pCsr;
115044
115045 if( pExpr->pCurrent==0 ){
115046 if( pCursor->desc==0 ){
115047 pExpr->pCurrent = pExpr->aDoclist;
115048 pExpr->iCurrent = 0;
115049 fts3GetDeltaVarint(&pExpr->pCurrent, &pExpr->iCurrent);
115050 }else{
115051 pCsr = pExpr->aDoclist;
115052 while( pCsr<pEnd ){
115053 fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
115054 fts3PoslistCopy(0, &pCsr);
115055 }
115056 fts3ReversePoslist(pExpr->aDoclist, &pCsr);
115057 pExpr->pCurrent = pCsr;
115058 }
115059 }
115060 pCsr = pExpr->pCurrent;
115061 assert( pCsr );
115062
115063 while( (pCursor->desc==0 && pCsr<pEnd)
115064 || (pCursor->desc && pCsr>pExpr->aDoclist)
115065 ){
115066 if( pCursor->desc==0 && pExpr->iCurrent<iDocid ){
115067 fts3PoslistCopy(0, &pCsr);
115068 if( pCsr<pEnd ){
115069 fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
115070 }
115071 pExpr->pCurrent = pCsr;
115072 }else if( pCursor->desc && pExpr->iCurrent>iDocid ){
115073 fts3GetReverseDeltaVarint(&pCsr, pExpr->aDoclist, &pExpr->iCurrent);
115074 fts3ReversePoslist(pExpr->aDoclist, &pCsr);
115075 pExpr->pCurrent = pCsr;
115076 }else{
115077 if( pExpr->iCurrent==iDocid ){
115078 int iThis = 0;
115079 if( iCol<0 ){
@@ -114303,13 +115326,24 @@
115326 "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';",
115327 p->zDb, p->zName, zName
115328 );
115329 return rc;
115330 }
115331
115332 static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
115333 return sqlite3Fts3PendingTermsFlush((Fts3Table *)pVtab);
115334 }
115335 static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
115336 return SQLITE_OK;
115337 }
115338 static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
115339 sqlite3Fts3PendingTermsClear((Fts3Table *)pVtab);
115340 return SQLITE_OK;
115341 }
115342
115343 static const sqlite3_module fts3Module = {
115344 /* iVersion */ 2,
115345 /* xCreate */ fts3CreateMethod,
115346 /* xConnect */ fts3ConnectMethod,
115347 /* xBestIndex */ fts3BestIndexMethod,
115348 /* xDisconnect */ fts3DisconnectMethod,
115349 /* xDestroy */ fts3DestroyMethod,
@@ -114325,10 +115359,13 @@
115359 /* xSync */ fts3SyncMethod,
115360 /* xCommit */ fts3CommitMethod,
115361 /* xRollback */ fts3RollbackMethod,
115362 /* xFindFunction */ fts3FindFunctionMethod,
115363 /* xRename */ fts3RenameMethod,
115364 /* xSavepoint */ fts3SavepointMethod,
115365 /* xRelease */ fts3ReleaseMethod,
115366 /* xRollbackTo */ fts3RollbackToMethod,
115367 };
115368
115369 /*
115370 ** This function is registered as the module destructor (called when an
115371 ** FTS3 enabled database connection is closed). It frees the memory
@@ -114370,10 +115407,15 @@
115407
115408 #ifdef SQLITE_ENABLE_ICU
115409 const sqlite3_tokenizer_module *pIcu = 0;
115410 sqlite3Fts3IcuTokenizerModule(&pIcu);
115411 #endif
115412
115413 #ifdef SQLITE_TEST
115414 rc = sqlite3Fts3InitTerm(db);
115415 if( rc!=SQLITE_OK ) return rc;
115416 #endif
115417
115418 rc = sqlite3Fts3InitAux(db);
115419 if( rc!=SQLITE_OK ) return rc;
115420
115421 sqlite3Fts3SimpleTokenizerModule(&pSimple);
@@ -117891,11 +118933,11 @@
118933 sqlite3_bind_int64(pStmt, 1, iDocid);
118934 }
118935 rc = sqlite3_step(pStmt);
118936 if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
118937 rc = sqlite3_reset(pStmt);
118938 if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT_VTAB;
118939 pStmt = 0;
118940 }else{
118941 rc = SQLITE_OK;
118942 }
118943 }
@@ -118141,10 +119183,18 @@
119183 sqlite3_tokenizer_cursor *pCsr;
119184 int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
119185 const char**,int*,int*,int*,int*);
119186
119187 assert( pTokenizer && pModule );
119188
119189 /* If the user has inserted a NULL value, this function may be called with
119190 ** zText==0. In this case, add zero token entries to the hash table and
119191 ** return early. */
119192 if( zText==0 ){
119193 *pnWord = 0;
119194 return SQLITE_OK;
119195 }
119196
119197 rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr);
119198 if( rc!=SQLITE_OK ){
119199 return rc;
119200 }
@@ -118232,15 +119282,13 @@
119282 */
119283 static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
119284 int i; /* Iterator variable */
119285 for(i=2; i<p->nColumn+2; i++){
119286 const char *zText = (const char *)sqlite3_value_text(apVal[i]);
119287 int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
119288 if( rc!=SQLITE_OK ){
119289 return rc;
 
 
119290 }
119291 aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
119292 }
119293 return SQLITE_OK;
119294 }
@@ -118341,18 +119389,18 @@
119389 ** full-text index.
119390 */
119391 static void fts3DeleteTerms(
119392 int *pRC, /* Result code */
119393 Fts3Table *p, /* The FTS table to delete from */
119394 sqlite3_value *pRowid, /* The docid to be deleted */
119395 u32 *aSz /* Sizes of deleted document written here */
119396 ){
119397 int rc;
119398 sqlite3_stmt *pSelect;
119399
119400 if( *pRC ) return;
119401 rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
119402 if( rc==SQLITE_OK ){
119403 if( SQLITE_ROW==sqlite3_step(pSelect) ){
119404 int i;
119405 for(i=1; i<=p->nColumn; i++){
119406 const char *zText = (const char *)sqlite3_column_text(pSelect, i);
@@ -118566,11 +119614,11 @@
119614 pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
119615 pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
119616 if( nPrefix<0 || nSuffix<=0
119617 || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
119618 ){
119619 return SQLITE_CORRUPT_VTAB;
119620 }
119621
119622 if( nPrefix+nSuffix>pReader->nTermAlloc ){
119623 int nNew = (nPrefix+nSuffix)*2;
119624 char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
@@ -118592,11 +119640,11 @@
119640 ** of these statements is untrue, then the data structure is corrupt.
119641 */
119642 if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
119643 || pReader->aDoclist[pReader->nDoclist-1]
119644 ){
119645 return SQLITE_CORRUPT_VTAB;
119646 }
119647 return SQLITE_OK;
119648 }
119649
119650 /*
@@ -118717,11 +119765,11 @@
119765 while( a<pEnd ){
119766 a += sqlite3Fts3GetVarint(a, &nByte);
119767 }
119768 if( nDoc==0 || nByte==0 ){
119769 sqlite3_reset(pStmt);
119770 return SQLITE_CORRUPT_VTAB;
119771 }
119772
119773 pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
119774 assert( pCsr->nRowAvg>0 );
119775 rc = sqlite3_reset(pStmt);
@@ -119488,20 +120536,20 @@
120536
120537 /*
120538 ** The first value in the apVal[] array is assumed to contain an integer.
120539 ** This function tests if there exist any documents with docid values that
120540 ** are different from that integer. i.e. if deleting the document with docid
120541 ** pRowid would mean the FTS3 table were empty.
120542 **
120543 ** If successful, *pisEmpty is set to true if the table is empty except for
120544 ** document pRowid, or false otherwise, and SQLITE_OK is returned. If an
120545 ** error occurs, an SQLite error code is returned.
120546 */
120547 static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){
120548 sqlite3_stmt *pStmt;
120549 int rc;
120550 rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid);
120551 if( rc==SQLITE_OK ){
120552 if( SQLITE_ROW==sqlite3_step(pStmt) ){
120553 *pisEmpty = sqlite3_column_int(pStmt, 0);
120554 }
120555 rc = sqlite3_reset(pStmt);
@@ -120221,10 +121269,44 @@
121269 pToken->pDeferred = pDeferred;
121270
121271 return SQLITE_OK;
121272 }
121273
121274 /*
121275 ** SQLite value pRowid contains the rowid of a row that may or may not be
121276 ** present in the FTS3 table. If it is, delete it and adjust the contents
121277 ** of subsiduary data structures accordingly.
121278 */
121279 static int fts3DeleteByRowid(
121280 Fts3Table *p,
121281 sqlite3_value *pRowid,
121282 int *pnDoc,
121283 u32 *aSzDel
121284 ){
121285 int isEmpty = 0;
121286 int rc = fts3IsEmpty(p, pRowid, &isEmpty);
121287 if( rc==SQLITE_OK ){
121288 if( isEmpty ){
121289 /* Deleting this row means the whole table is empty. In this case
121290 ** delete the contents of all three tables and throw away any
121291 ** data in the pendingTerms hash table. */
121292 rc = fts3DeleteAll(p);
121293 *pnDoc = *pnDoc - 1;
121294 }else{
121295 sqlite3_int64 iRemove = sqlite3_value_int64(pRowid);
121296 rc = fts3PendingTermsDocid(p, iRemove);
121297 fts3DeleteTerms(&rc, p, pRowid, aSzDel);
121298 fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
121299 if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
121300 if( p->bHasDocsize ){
121301 fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
121302 }
121303 }
121304 }
121305
121306 return rc;
121307 }
121308
121309 /*
121310 ** This function does the work for the xUpdate method of FTS3 virtual
121311 ** tables.
121312 */
@@ -120239,50 +121321,95 @@
121321 int isRemove = 0; /* True for an UPDATE or DELETE */
121322 sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
121323 u32 *aSzIns; /* Sizes of inserted documents */
121324 u32 *aSzDel; /* Sizes of deleted documents */
121325 int nChng = 0; /* Net change in number of documents */
121326 int bInsertDone = 0;
121327
121328 assert( p->pSegments==0 );
121329
121330 /* Check for a "special" INSERT operation. One of the form:
121331 **
121332 ** INSERT INTO xyz(xyz) VALUES('command');
121333 */
121334 if( nArg>1
121335 && sqlite3_value_type(apVal[0])==SQLITE_NULL
121336 && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
121337 ){
121338 return fts3SpecialInsert(p, apVal[p->nColumn+2]);
121339 }
121340
121341 /* Allocate space to hold the change in document sizes */
121342 aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
121343 if( aSzIns==0 ) return SQLITE_NOMEM;
121344 aSzDel = &aSzIns[p->nColumn+1];
121345 memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
121346
121347 /* If this is an INSERT operation, or an UPDATE that modifies the rowid
121348 ** value, then this operation requires constraint handling.
121349 **
121350 ** If the on-conflict mode is REPLACE, this means that the existing row
121351 ** should be deleted from the database before inserting the new row. Or,
121352 ** if the on-conflict mode is other than REPLACE, then this method must
121353 ** detect the conflict and return SQLITE_CONSTRAINT before beginning to
121354 ** modify the database file.
121355 */
121356 if( nArg>1 ){
121357 /* Find the value object that holds the new rowid value. */
121358 sqlite3_value *pNewRowid = apVal[3+p->nColumn];
121359 if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){
121360 pNewRowid = apVal[1];
121361 }
121362
121363 if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
121364 sqlite3_value_type(apVal[0])==SQLITE_NULL
121365 || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid)
121366 )){
121367 /* The new rowid is not NULL (in this case the rowid will be
121368 ** automatically assigned and there is no chance of a conflict), and
121369 ** the statement is either an INSERT or an UPDATE that modifies the
121370 ** rowid column. So if the conflict mode is REPLACE, then delete any
121371 ** existing row with rowid=pNewRowid.
121372 **
121373 ** Or, if the conflict mode is not REPLACE, insert the new record into
121374 ** the %_content table. If we hit the duplicate rowid constraint (or any
121375 ** other error) while doing so, return immediately.
121376 **
121377 ** This branch may also run if pNewRowid contains a value that cannot
121378 ** be losslessly converted to an integer. In this case, the eventual
121379 ** call to fts3InsertData() (either just below or further on in this
121380 ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
121381 ** invoked, it will delete zero rows (since no row will have
121382 ** docid=$pNewRowid if $pNewRowid is not an integer value).
121383 */
121384 if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){
121385 rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel);
121386 }else{
121387 rc = fts3InsertData(p, apVal, pRowid);
121388 bInsertDone = 1;
121389 }
121390 }
121391 }
121392 if( rc!=SQLITE_OK ){
121393 sqlite3_free(aSzIns);
121394 return rc;
121395 }
121396
121397 /* If this is a DELETE or UPDATE operation, remove the old record. */
121398 if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
121399 assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
121400 rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
121401 isRemove = 1;
121402 iRemove = sqlite3_value_int64(apVal[0]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121403 }
121404
121405 /* If this is an INSERT or UPDATE operation, insert the new record. */
121406 if( nArg>1 && rc==SQLITE_OK ){
121407 if( bInsertDone==0 ){
121408 rc = fts3InsertData(p, apVal, pRowid);
121409 if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT_VTAB;
121410 }
121411 if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
121412 rc = fts3PendingTermsDocid(p, *pRowid);
121413 }
121414 if( rc==SQLITE_OK ){
121415 rc = fts3InsertTerms(p, apVal, aSzIns);
@@ -120742,11 +121869,11 @@
121869 SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
121870 char *pCsr;
121871
121872 pPhrase->nToken = pExpr->pPhrase->nToken;
121873
121874 pCsr = sqlite3Fts3FindPositions(p->pCsr, pExpr, p->pCsr->iPrevId, p->iCol);
121875 if( pCsr ){
121876 int iFirst = 0;
121877 pPhrase->pList = pCsr;
121878 fts3GetDeltaPosition(&pCsr, &iFirst);
121879 pPhrase->pHead = pCsr;
@@ -121215,11 +122342,11 @@
122342 for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0;
122343
122344 if( pExpr->aDoclist ){
122345 char *pCsr;
122346
122347 pCsr = sqlite3Fts3FindPositions(p->pCursor, pExpr, p->pCursor->iPrevId, -1);
122348 if( pCsr ){
122349 fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0);
122350 }
122351 }
122352
@@ -121287,11 +122414,11 @@
122414 pStmt = *ppStmt;
122415 assert( sqlite3_data_count(pStmt)==1 );
122416
122417 a = sqlite3_column_blob(pStmt, 0);
122418 a += sqlite3Fts3GetVarint(a, &nDoc);
122419 if( nDoc==0 ) return SQLITE_CORRUPT_VTAB;
122420 *pnDoc = (u32)nDoc;
122421
122422 if( paLen ) *paLen = a;
122423 return SQLITE_OK;
122424 }
@@ -121382,11 +122509,11 @@
122509 (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
122510 for(i=0; i<pInfo->nPhrase; i++){
122511 LcsIterator *pIter = &aIter[i];
122512 nToken -= pIter->pExpr->pPhrase->nToken;
122513 pIter->iPosOffset = nToken;
122514 pIter->pRead = sqlite3Fts3FindPositions(pCsr,pIter->pExpr,pCsr->iPrevId,-1);
122515 if( pIter->pRead ){
122516 pIter->iPos = pIter->iPosOffset;
122517 fts3LcsIteratorAdvance(&aIter[i]);
122518 }else{
122519 pIter->iCol = LCS_ITERATOR_FINISHED;
@@ -121735,10 +122862,11 @@
122862 int iPos; /* Position just read from pList */
122863 int iOff; /* Offset of this term from read positions */
122864 };
122865
122866 struct TermOffsetCtx {
122867 Fts3Cursor *pCsr;
122868 int iCol; /* Column of table to populate aTerm for */
122869 int iTerm;
122870 sqlite3_int64 iDocid;
122871 TermOffset *aTerm;
122872 };
@@ -121752,11 +122880,11 @@
122880 int iTerm; /* For looping through nTerm phrase terms */
122881 char *pList; /* Pointer to position list for phrase */
122882 int iPos = 0; /* First position in position-list */
122883
122884 UNUSED_PARAMETER(iPhrase);
122885 pList = sqlite3Fts3FindPositions(p->pCsr, pExpr, p->iDocid, p->iCol);
122886 nTerm = pExpr->pPhrase->nToken;
122887 if( pList ){
122888 fts3GetDeltaPosition(&pList, &iPos);
122889 assert( iPos>=0 );
122890 }
@@ -121805,10 +122933,11 @@
122933 if( 0==sCtx.aTerm ){
122934 rc = SQLITE_NOMEM;
122935 goto offsets_out;
122936 }
122937 sCtx.iDocid = pCsr->iPrevId;
122938 sCtx.pCsr = pCsr;
122939
122940 /* Loop through the table columns, appending offset information to
122941 ** string-buffer res for each column.
122942 */
122943 for(iCol=0; iCol<pTab->nColumn; iCol++){
@@ -121880,11 +123009,11 @@
123009 sqlite3_snprintf(sizeof(aBuffer), aBuffer,
123010 "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
123011 );
123012 rc = fts3StringAppend(&res, aBuffer, -1);
123013 }else if( rc==SQLITE_DONE ){
123014 rc = SQLITE_CORRUPT_VTAB;
123015 }
123016 }
123017 }
123018 if( rc==SQLITE_DONE ){
123019 rc = SQLITE_OK;
@@ -122468,29 +123597,29 @@
123597 ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
123598 */
123599 if( pNode && iNode==1 ){
123600 pRtree->iDepth = readInt16(pNode->zData);
123601 if( pRtree->iDepth>RTREE_MAX_DEPTH ){
123602 rc = SQLITE_CORRUPT_VTAB;
123603 }
123604 }
123605
123606 /* If no error has occurred so far, check if the "number of entries"
123607 ** field on the node is too large. If so, set the return code to
123608 ** SQLITE_CORRUPT_VTAB.
123609 */
123610 if( pNode && rc==SQLITE_OK ){
123611 if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
123612 rc = SQLITE_CORRUPT_VTAB;
123613 }
123614 }
123615
123616 if( rc==SQLITE_OK ){
123617 if( pNode!=0 ){
123618 nodeHashInsert(pRtree, pNode);
123619 }else{
123620 rc = SQLITE_CORRUPT_VTAB;
123621 }
123622 *ppNode = pNode;
123623 }else{
123624 sqlite3_free(pNode);
123625 *ppNode = 0;
@@ -123013,11 +124142,11 @@
124142 if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
124143 *piIndex = ii;
124144 return SQLITE_OK;
124145 }
124146 }
124147 return SQLITE_CORRUPT_VTAB;
124148 }
124149
124150 /*
124151 ** Return the index of the cell containing a pointer to node pNode
124152 ** in its parent. If pNode is the root node, return -1.
@@ -123608,11 +124737,11 @@
124737 RtreeNode *pParent = p->pParent;
124738 RtreeCell cell;
124739 int iCell;
124740
124741 if( nodeParentIndex(pRtree, p, &iCell) ){
124742 return SQLITE_CORRUPT_VTAB;
124743 }
124744
124745 nodeGetCell(pRtree, pParent, iCell, &cell);
124746 if( !cellContains(pRtree, &cell, pCell) ){
124747 cellUnion(pRtree, &cell, pCell);
@@ -124280,11 +125409,11 @@
125409 rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
125410 }
125411 }
125412 rc = sqlite3_reset(pRtree->pReadParent);
125413 if( rc==SQLITE_OK ) rc = rc2;
125414 if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
125415 pChild = pChild->pParent;
125416 }
125417 return rc;
125418 }
125419
@@ -124575,10 +125704,94 @@
125704 sqlite3_step(pRtree->pWriteRowid);
125705 rc = sqlite3_reset(pRtree->pWriteRowid);
125706 *piRowid = sqlite3_last_insert_rowid(pRtree->db);
125707 return rc;
125708 }
125709
125710 /*
125711 ** Remove the entry with rowid=iDelete from the r-tree structure.
125712 */
125713 static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
125714 int rc; /* Return code */
125715 RtreeNode *pLeaf; /* Leaf node containing record iDelete */
125716 int iCell; /* Index of iDelete cell in pLeaf */
125717 RtreeNode *pRoot; /* Root node of rtree structure */
125718
125719
125720 /* Obtain a reference to the root node to initialise Rtree.iDepth */
125721 rc = nodeAcquire(pRtree, 1, 0, &pRoot);
125722
125723 /* Obtain a reference to the leaf node that contains the entry
125724 ** about to be deleted.
125725 */
125726 if( rc==SQLITE_OK ){
125727 rc = findLeafNode(pRtree, iDelete, &pLeaf);
125728 }
125729
125730 /* Delete the cell in question from the leaf node. */
125731 if( rc==SQLITE_OK ){
125732 int rc2;
125733 rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
125734 if( rc==SQLITE_OK ){
125735 rc = deleteCell(pRtree, pLeaf, iCell, 0);
125736 }
125737 rc2 = nodeRelease(pRtree, pLeaf);
125738 if( rc==SQLITE_OK ){
125739 rc = rc2;
125740 }
125741 }
125742
125743 /* Delete the corresponding entry in the <rtree>_rowid table. */
125744 if( rc==SQLITE_OK ){
125745 sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
125746 sqlite3_step(pRtree->pDeleteRowid);
125747 rc = sqlite3_reset(pRtree->pDeleteRowid);
125748 }
125749
125750 /* Check if the root node now has exactly one child. If so, remove
125751 ** it, schedule the contents of the child for reinsertion and
125752 ** reduce the tree height by one.
125753 **
125754 ** This is equivalent to copying the contents of the child into
125755 ** the root node (the operation that Gutman's paper says to perform
125756 ** in this scenario).
125757 */
125758 if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
125759 int rc2;
125760 RtreeNode *pChild;
125761 i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
125762 rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
125763 if( rc==SQLITE_OK ){
125764 rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
125765 }
125766 rc2 = nodeRelease(pRtree, pChild);
125767 if( rc==SQLITE_OK ) rc = rc2;
125768 if( rc==SQLITE_OK ){
125769 pRtree->iDepth--;
125770 writeInt16(pRoot->zData, pRtree->iDepth);
125771 pRoot->isDirty = 1;
125772 }
125773 }
125774
125775 /* Re-insert the contents of any underfull nodes removed from the tree. */
125776 for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
125777 if( rc==SQLITE_OK ){
125778 rc = reinsertNodeContent(pRtree, pLeaf);
125779 }
125780 pRtree->pDeleted = pLeaf->pNext;
125781 sqlite3_free(pLeaf);
125782 }
125783
125784 /* Release the reference to the root node. */
125785 if( rc==SQLITE_OK ){
125786 rc = nodeRelease(pRtree, pRoot);
125787 }else{
125788 nodeRelease(pRtree, pRoot);
125789 }
125790
125791 return rc;
125792 }
125793
125794 /*
125795 ** The xUpdate method for rtree module virtual tables.
125796 */
125797 static int rtreeUpdate(
@@ -124587,107 +125800,29 @@
125800 sqlite3_value **azData,
125801 sqlite_int64 *pRowid
125802 ){
125803 Rtree *pRtree = (Rtree *)pVtab;
125804 int rc = SQLITE_OK;
125805 RtreeCell cell; /* New cell to insert if nData>1 */
125806 int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
125807
125808 rtreeReference(pRtree);
 
125809 assert(nData>=1);
125810
125811 /* Constraint handling. A write operation on an r-tree table may return
125812 ** SQLITE_CONSTRAINT for two reasons:
125813 **
125814 ** 1. A duplicate rowid value, or
125815 ** 2. The supplied data violates the "x2>=x1" constraint.
125816 **
125817 ** In the first case, if the conflict-handling mode is REPLACE, then
125818 ** the conflicting row can be removed before proceeding. In the second
125819 ** case, SQLITE_CONSTRAINT must be returned regardless of the
125820 ** conflict-handling mode specified by the user.
125821 */
125822 if( nData>1 ){
125823 int ii;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125824
125825 /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
125826 assert( nData==(pRtree->nDim*2 + 3) );
125827 if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
125828 for(ii=0; ii<(pRtree->nDim*2); ii+=2){
@@ -124707,22 +125842,53 @@
125842 goto constraint;
125843 }
125844 }
125845 }
125846
125847 /* If a rowid value was supplied, check if it is already present in
125848 ** the table. If so, the constraint has failed. */
125849 if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){
 
125850 cell.iRowid = sqlite3_value_int64(azData[2]);
125851 if( sqlite3_value_type(azData[0])==SQLITE_NULL
125852 || sqlite3_value_int64(azData[0])!=cell.iRowid
125853 ){
125854 int steprc;
125855 sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
125856 steprc = sqlite3_step(pRtree->pReadRowid);
125857 rc = sqlite3_reset(pRtree->pReadRowid);
125858 if( SQLITE_ROW==steprc ){
125859 if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){
125860 rc = rtreeDeleteRowid(pRtree, cell.iRowid);
125861 }else{
125862 rc = SQLITE_CONSTRAINT;
125863 goto constraint;
125864 }
125865 }
125866 }
125867 bHaveRowid = 1;
125868 }
125869 }
125870
125871 /* If azData[0] is not an SQL NULL value, it is the rowid of a
125872 ** record to delete from the r-tree table. The following block does
125873 ** just that.
125874 */
125875 if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
125876 rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0]));
125877 }
125878
125879 /* If the azData[] array contains more than one element, elements
125880 ** (azData[2]..azData[argc-1]) contain a new record to insert into
125881 ** the r-tree structure.
125882 */
125883 if( rc==SQLITE_OK && nData>1 ){
125884 /* Insert the new record into the r-tree */
125885 RtreeNode *pLeaf;
125886
125887 /* Figure out the rowid of the new row. */
125888 if( bHaveRowid==0 ){
125889 rc = newRowid(pRtree, &cell.iRowid);
125890 }
125891 *pRowid = cell.iRowid;
125892
125893 if( rc==SQLITE_OK ){
125894 rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf);
@@ -124958,10 +126124,12 @@
126124 int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
126125 if( aErrMsg[iErr] ){
126126 *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
126127 return SQLITE_ERROR;
126128 }
126129
126130 sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
126131
126132 /* Allocate the sqlite3_vtab structure */
126133 nDb = strlen(argv[1]);
126134 nName = strlen(argv[2]);
126135 pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
126136
+341 -77
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105105
**
106106
** See also: [sqlite3_libversion()],
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110
-#define SQLITE_VERSION "3.7.6"
111
-#define SQLITE_VERSION_NUMBER 3007006
112
-#define SQLITE_SOURCE_ID "2011-04-12 01:58:40 f9d43fa363d54beab6f45db005abac0a7c0c47a7"
110
+#define SQLITE_VERSION "3.7.7"
111
+#define SQLITE_VERSION_NUMBER 3007007
112
+#define SQLITE_SOURCE_ID "2011-05-20 01:50:01 2018d4e108872f2436df046636401b89cfde589d"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -373,11 +373,12 @@
373373
** Many SQLite functions return an integer result code from the set shown
374374
** here in order to indicates success or failure.
375375
**
376376
** New error codes may be added in future versions of SQLite.
377377
**
378
-** See also: [SQLITE_IOERR_READ | extended result codes]
378
+** See also: [SQLITE_IOERR_READ | extended result codes],
379
+** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
379380
*/
380381
#define SQLITE_OK 0 /* Successful result */
381382
/* beginning-of-error-codes */
382383
#define SQLITE_ERROR 1 /* SQL error or missing database */
383384
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -450,28 +451,31 @@
450451
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
451452
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
452453
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
453454
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
454455
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
456
+#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
457
+#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
455458
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
456459
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
457460
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
461
+#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
458462
459463
/*
460464
** CAPI3REF: Flags For File Open Operations
461465
**
462466
** These bit values are intended for use in the
463467
** 3rd parameter to the [sqlite3_open_v2()] interface and
464
-** in the 4th parameter to the xOpen method of the
465
-** [sqlite3_vfs] object.
468
+** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
466469
*/
467470
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
468471
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
469472
#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
470473
#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
471474
#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
472475
#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
476
+#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
473477
#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
474478
#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
475479
#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
476480
#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
477481
#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
@@ -578,21 +582,22 @@
578582
};
579583
580584
/*
581585
** CAPI3REF: OS Interface File Virtual Methods Object
582586
**
583
-** Every file opened by the [sqlite3_vfs] xOpen method populates an
587
+** Every file opened by the [sqlite3_vfs.xOpen] method populates an
584588
** [sqlite3_file] object (or, more commonly, a subclass of the
585589
** [sqlite3_file] object) with a pointer to an instance of this object.
586590
** This object defines the methods used to perform various operations
587591
** against the open file represented by the [sqlite3_file] object.
588592
**
589
-** If the xOpen method sets the sqlite3_file.pMethods element
593
+** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
590594
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
591
-** may be invoked even if the xOpen reported that it failed. The
592
-** only way to prevent a call to xClose following a failed xOpen
593
-** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
595
+** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
596
+** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
597
+** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
598
+** to NULL.
594599
**
595600
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
596601
** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
597602
** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
598603
** flag may be ORed in to indicate that only the data of the file
@@ -757,10 +762,11 @@
757762
*/
758763
typedef struct sqlite3_mutex sqlite3_mutex;
759764
760765
/*
761766
** CAPI3REF: OS Interface Object
767
+** KEYWORDS: VFS VFSes
762768
**
763769
** An instance of the sqlite3_vfs object defines the interface between
764770
** the SQLite core and the underlying operating system. The "vfs"
765771
** in the name of the object stands for "virtual file system".
766772
**
@@ -789,10 +795,11 @@
789795
** object once the object has been registered.
790796
**
791797
** The zName field holds the name of the VFS module. The name must
792798
** be unique across all VFS modules.
793799
**
800
+** [[sqlite3_vfs.xOpen]]
794801
** ^SQLite guarantees that the zFilename parameter to xOpen
795802
** is either a NULL pointer or string obtained
796803
** from xFullPathname() with an optional suffix added.
797804
** ^If a suffix is added to the zFilename parameter, it will
798805
** consist of a single "-" character followed by no more than
@@ -866,10 +873,11 @@
866873
** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
867874
** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
868875
** element will be valid after xOpen returns regardless of the success
869876
** or failure of the xOpen call.
870877
**
878
+** [[sqlite3_vfs.xAccess]]
871879
** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
872880
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
873881
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
874882
** to test whether a file is at least readable. The file can be a
875883
** directory.
@@ -1112,13 +1120,13 @@
11121120
** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
11131121
** Note, however, that ^sqlite3_config() can be called as part of the
11141122
** implementation of an application-defined [sqlite3_os_init()].
11151123
**
11161124
** The first argument to sqlite3_config() is an integer
1117
-** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
1125
+** [configuration option] that determines
11181126
** what property of SQLite is to be configured. Subsequent arguments
1119
-** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
1127
+** vary depending on the [configuration option]
11201128
** in the first argument.
11211129
**
11221130
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
11231131
** ^If the option is unknown or SQLite is unable to set the option
11241132
** then this routine returns a non-zero [error code].
@@ -1224,10 +1232,11 @@
12241232
void *pAppData; /* Argument to xInit() and xShutdown() */
12251233
};
12261234
12271235
/*
12281236
** CAPI3REF: Configuration Options
1237
+** KEYWORDS: {configuration option}
12291238
**
12301239
** These constants are the available integer configuration options that
12311240
** can be passed as the first argument to the [sqlite3_config()] interface.
12321241
**
12331242
** New configuration options may be added in future releases of SQLite.
@@ -1236,11 +1245,11 @@
12361245
** the call worked. The [sqlite3_config()] interface will return a
12371246
** non-zero [error code] if a discontinued or unsupported configuration option
12381247
** is invoked.
12391248
**
12401249
** <dl>
1241
-** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
1250
+** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
12421251
** <dd>There are no arguments to this option. ^This option sets the
12431252
** [threading mode] to Single-thread. In other words, it disables
12441253
** all mutexing and puts SQLite into a mode where it can only be used
12451254
** by a single thread. ^If SQLite is compiled with
12461255
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
@@ -1247,11 +1256,11 @@
12471256
** it is not possible to change the [threading mode] from its default
12481257
** value of Single-thread and so [sqlite3_config()] will return
12491258
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
12501259
** configuration option.</dd>
12511260
**
1252
-** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
1261
+** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
12531262
** <dd>There are no arguments to this option. ^This option sets the
12541263
** [threading mode] to Multi-thread. In other words, it disables
12551264
** mutexing on [database connection] and [prepared statement] objects.
12561265
** The application is responsible for serializing access to
12571266
** [database connections] and [prepared statements]. But other mutexes
@@ -1261,11 +1270,11 @@
12611270
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
12621271
** it is not possible to set the Multi-thread [threading mode] and
12631272
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
12641273
** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
12651274
**
1266
-** <dt>SQLITE_CONFIG_SERIALIZED</dt>
1275
+** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
12671276
** <dd>There are no arguments to this option. ^This option sets the
12681277
** [threading mode] to Serialized. In other words, this option enables
12691278
** all mutexes including the recursive
12701279
** mutexes on [database connection] and [prepared statement] objects.
12711280
** In this mode (which is the default when SQLite is compiled with
@@ -1277,27 +1286,27 @@
12771286
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
12781287
** it is not possible to set the Serialized [threading mode] and
12791288
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
12801289
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
12811290
**
1282
-** <dt>SQLITE_CONFIG_MALLOC</dt>
1291
+** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
12831292
** <dd> ^(This option takes a single argument which is a pointer to an
12841293
** instance of the [sqlite3_mem_methods] structure. The argument specifies
12851294
** alternative low-level memory allocation routines to be used in place of
12861295
** the memory allocation routines built into SQLite.)^ ^SQLite makes
12871296
** its own private copy of the content of the [sqlite3_mem_methods] structure
12881297
** before the [sqlite3_config()] call returns.</dd>
12891298
**
1290
-** <dt>SQLITE_CONFIG_GETMALLOC</dt>
1299
+** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
12911300
** <dd> ^(This option takes a single argument which is a pointer to an
12921301
** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
12931302
** structure is filled with the currently defined memory allocation routines.)^
12941303
** This option can be used to overload the default memory allocation
12951304
** routines with a wrapper that simulations memory allocation failure or
12961305
** tracks memory usage, for example. </dd>
12971306
**
1298
-** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
1307
+** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
12991308
** <dd> ^This option takes single argument of type int, interpreted as a
13001309
** boolean, which enables or disables the collection of memory allocation
13011310
** statistics. ^(When memory allocation statistics are disabled, the
13021311
** following SQLite interfaces become non-operational:
13031312
** <ul>
@@ -1309,11 +1318,11 @@
13091318
** ^Memory allocation statistics are enabled by default unless SQLite is
13101319
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
13111320
** allocation statistics are disabled by default.
13121321
** </dd>
13131322
**
1314
-** <dt>SQLITE_CONFIG_SCRATCH</dt>
1323
+** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
13151324
** <dd> ^This option specifies a static memory buffer that SQLite can use for
13161325
** scratch memory. There are three arguments: A pointer an 8-byte
13171326
** aligned memory buffer from which the scratch allocations will be
13181327
** drawn, the size of each scratch allocation (sz),
13191328
** and the maximum number of scratch allocations (N). The sz
@@ -1325,11 +1334,11 @@
13251334
** ^SQLite will never require a scratch buffer that is more than 6
13261335
** times the database page size. ^If SQLite needs needs additional
13271336
** scratch memory beyond what is provided by this configuration option, then
13281337
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
13291338
**
1330
-** <dt>SQLITE_CONFIG_PAGECACHE</dt>
1339
+** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
13311340
** <dd> ^This option specifies a static memory buffer that SQLite can use for
13321341
** the database page cache with the default page cache implemenation.
13331342
** This configuration should not be used if an application-define page
13341343
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
13351344
** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1346,11 +1355,11 @@
13461355
** SQLite goes to [sqlite3_malloc()] for the additional storage space.
13471356
** The pointer in the first argument must
13481357
** be aligned to an 8-byte boundary or subsequent behavior of SQLite
13491358
** will be undefined.</dd>
13501359
**
1351
-** <dt>SQLITE_CONFIG_HEAP</dt>
1360
+** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
13521361
** <dd> ^This option specifies a static memory buffer that SQLite will use
13531362
** for all of its dynamic memory allocation needs beyond those provided
13541363
** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
13551364
** There are three arguments: An 8-byte aligned pointer to the memory,
13561365
** the number of bytes in the memory buffer, and the minimum allocation size.
@@ -1363,11 +1372,11 @@
13631372
** The first pointer (the memory pointer) must be aligned to an 8-byte
13641373
** boundary or subsequent behavior of SQLite will be undefined.
13651374
** The minimum allocation size is capped at 2^12. Reasonable values
13661375
** for the minimum allocation size are 2^5 through 2^8.</dd>
13671376
**
1368
-** <dt>SQLITE_CONFIG_MUTEX</dt>
1377
+** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
13691378
** <dd> ^(This option takes a single argument which is a pointer to an
13701379
** instance of the [sqlite3_mutex_methods] structure. The argument specifies
13711380
** alternative low-level mutex routines to be used in place
13721381
** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
13731382
** content of the [sqlite3_mutex_methods] structure before the call to
@@ -1375,11 +1384,11 @@
13751384
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
13761385
** the entire mutexing subsystem is omitted from the build and hence calls to
13771386
** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
13781387
** return [SQLITE_ERROR].</dd>
13791388
**
1380
-** <dt>SQLITE_CONFIG_GETMUTEX</dt>
1389
+** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
13811390
** <dd> ^(This option takes a single argument which is a pointer to an
13821391
** instance of the [sqlite3_mutex_methods] structure. The
13831392
** [sqlite3_mutex_methods]
13841393
** structure is filled with the currently defined mutex routines.)^
13851394
** This option can be used to overload the default mutex allocation
@@ -1388,32 +1397,32 @@
13881397
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
13891398
** the entire mutexing subsystem is omitted from the build and hence calls to
13901399
** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
13911400
** return [SQLITE_ERROR].</dd>
13921401
**
1393
-** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
1402
+** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
13941403
** <dd> ^(This option takes two arguments that determine the default
13951404
** memory allocation for the lookaside memory allocator on each
13961405
** [database connection]. The first argument is the
13971406
** size of each lookaside buffer slot and the second is the number of
13981407
** slots allocated to each database connection.)^ ^(This option sets the
13991408
** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
14001409
** verb to [sqlite3_db_config()] can be used to change the lookaside
14011410
** configuration on individual connections.)^ </dd>
14021411
**
1403
-** <dt>SQLITE_CONFIG_PCACHE</dt>
1412
+** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
14041413
** <dd> ^(This option takes a single argument which is a pointer to
14051414
** an [sqlite3_pcache_methods] object. This object specifies the interface
14061415
** to a custom page cache implementation.)^ ^SQLite makes a copy of the
14071416
** object and uses it for page cache memory allocations.</dd>
14081417
**
1409
-** <dt>SQLITE_CONFIG_GETPCACHE</dt>
1418
+** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
14101419
** <dd> ^(This option takes a single argument which is a pointer to an
14111420
** [sqlite3_pcache_methods] object. SQLite copies of the current
14121421
** page cache implementation into that object.)^ </dd>
14131422
**
1414
-** <dt>SQLITE_CONFIG_LOG</dt>
1423
+** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
14151424
** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
14161425
** function with a call signature of void(*)(void*,int,const char*),
14171426
** and a pointer to void. ^If the function pointer is not NULL, it is
14181427
** invoked by [sqlite3_log()] to process each logging event. ^If the
14191428
** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
@@ -1427,10 +1436,22 @@
14271436
** The SQLite logging interface is not reentrant; the logger function
14281437
** supplied by the application must not invoke any SQLite interface.
14291438
** In a multi-threaded application, the application-defined logger
14301439
** function must be threadsafe. </dd>
14311440
**
1441
+** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
1442
+** <dd> This option takes a single argument of type int. If non-zero, then
1443
+** URI handling is globally enabled. If the parameter is zero, then URI handling
1444
+** is globally disabled. If URI handling is globally enabled, all filenames
1445
+** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
1446
+** specified as part of [ATTACH] commands are interpreted as URIs, regardless
1447
+** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
1448
+** connection is opened. If it is globally disabled, filenames are
1449
+** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
1450
+** database connection is opened. By default, URI handling is globally
1451
+** disabled. The default value may be changed by compiling with the
1452
+** [SQLITE_USE_URI] symbol defined.
14321453
** </dl>
14331454
*/
14341455
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
14351456
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
14361457
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1445,10 +1466,11 @@
14451466
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
14461467
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
14471468
#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
14481469
#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
14491470
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
1471
+#define SQLITE_CONFIG_URI 17 /* int */
14501472
14511473
/*
14521474
** CAPI3REF: Database Connection Configuration Options
14531475
**
14541476
** These constants are the available integer configuration options that
@@ -1530,17 +1552,21 @@
15301552
** the table has a column of type [INTEGER PRIMARY KEY] then that column
15311553
** is another alias for the rowid.
15321554
**
15331555
** ^This routine returns the [rowid] of the most recent
15341556
** successful [INSERT] into the database from the [database connection]
1535
-** in the first argument. ^If no successful [INSERT]s
1557
+** in the first argument. ^As of SQLite version 3.7.7, this routines
1558
+** records the last insert rowid of both ordinary tables and [virtual tables].
1559
+** ^If no successful [INSERT]s
15361560
** have ever occurred on that database connection, zero is returned.
15371561
**
1538
-** ^(If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
1539
-** row is returned by this routine as long as the trigger is running.
1540
-** But once the trigger terminates, the value returned by this routine
1541
-** reverts to the last value inserted before the trigger fired.)^
1562
+** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
1563
+** method, then this routine will return the [rowid] of the inserted
1564
+** row as long as the trigger or virtual table method is running.
1565
+** But once the trigger or virtual table method ends, the value returned
1566
+** by this routine reverts to what it was before the trigger or virtual
1567
+** table method began.)^
15421568
**
15431569
** ^An [INSERT] that fails due to a constraint violation is not a
15441570
** successful [INSERT] and does not change the value returned by this
15451571
** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
15461572
** and INSERT OR ABORT make no changes to the return value of this
@@ -2199,10 +2225,13 @@
21992225
** The [sqlite3_set_authorizer | authorizer callback function] must
22002226
** return either [SQLITE_OK] or one of these two constants in order
22012227
** to signal SQLite whether or not the action is permitted. See the
22022228
** [sqlite3_set_authorizer | authorizer documentation] for additional
22032229
** information.
2230
+**
2231
+** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
2232
+** from the [sqlite3_vtab_on_conflict()] interface.
22042233
*/
22052234
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
22062235
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
22072236
22082237
/*
@@ -2321,11 +2350,11 @@
23212350
SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
23222351
23232352
/*
23242353
** CAPI3REF: Opening A New Database Connection
23252354
**
2326
-** ^These routines open an SQLite database file whose name is given by the
2355
+** ^These routines open an SQLite database file as specified by the
23272356
** filename argument. ^The filename argument is interpreted as UTF-8 for
23282357
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
23292358
** order for sqlite3_open16(). ^(A [database connection] handle is usually
23302359
** returned in *ppDb, even if an error occurs. The only exception is that
23312360
** if SQLite is unable to allocate memory to hold the [sqlite3] object,
@@ -2348,11 +2377,11 @@
23482377
** except that it accepts two additional parameters for additional control
23492378
** over the new database connection. ^(The flags parameter to
23502379
** sqlite3_open_v2() can take one of
23512380
** the following three values, optionally combined with the
23522381
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
2353
-** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
2382
+** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
23542383
**
23552384
** <dl>
23562385
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
23572386
** <dd>The database is opened in read-only mode. If the database does not
23582387
** already exist, an error is returned.</dd>)^
@@ -2367,13 +2396,12 @@
23672396
** it does not already exist. This is the behavior that is always used for
23682397
** sqlite3_open() and sqlite3_open16().</dd>)^
23692398
** </dl>
23702399
**
23712400
** If the 3rd parameter to sqlite3_open_v2() is not one of the
2372
-** combinations shown above or one of the combinations shown above combined
2373
-** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX],
2374
-** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags,
2401
+** combinations shown above optionally combined with other
2402
+** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
23752403
** then the behavior is undefined.
23762404
**
23772405
** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
23782406
** opens in the multi-thread [threading mode] as long as the single-thread
23792407
** mode has not been set at compile-time or start-time. ^If the
@@ -2383,10 +2411,15 @@
23832411
** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
23842412
** eligible to use [shared cache mode], regardless of whether or not shared
23852413
** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
23862414
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
23872415
** participate in [shared cache mode] even if it is enabled.
2416
+**
2417
+** ^The fourth parameter to sqlite3_open_v2() is the name of the
2418
+** [sqlite3_vfs] object that defines the operating system interface that
2419
+** the new database connection should use. ^If the fourth parameter is
2420
+** a NULL pointer then the default [sqlite3_vfs] object is used.
23882421
**
23892422
** ^If the filename is ":memory:", then a private, temporary in-memory database
23902423
** is created for the connection. ^This in-memory database will vanish when
23912424
** the database connection is closed. Future versions of SQLite might
23922425
** make use of additional special filenames that begin with the ":" character.
@@ -2396,14 +2429,115 @@
23962429
**
23972430
** ^If the filename is an empty string, then a private, temporary
23982431
** on-disk database will be created. ^This private database will be
23992432
** automatically deleted as soon as the database connection is closed.
24002433
**
2401
-** ^The fourth parameter to sqlite3_open_v2() is the name of the
2402
-** [sqlite3_vfs] object that defines the operating system interface that
2403
-** the new database connection should use. ^If the fourth parameter is
2404
-** a NULL pointer then the default [sqlite3_vfs] object is used.
2434
+** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
2435
+**
2436
+** ^If [URI filename] interpretation is enabled, and the filename argument
2437
+** begins with "file:", then the filename is interpreted as a URI. ^URI
2438
+** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2439
+** is set in the fourth argument to sqlite3_open_v2(), or if it has
2440
+** been enabled globally using the [SQLITE_CONFIG_URI] option with the
2441
+** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
2442
+** As of SQLite version 3.7.7, URI filename interpretation is turned off
2443
+** by default, but future releases of SQLite might enable URI filename
2444
+** intepretation by default. See "[URI filenames]" for additional
2445
+** information.
2446
+**
2447
+** URI filenames are parsed according to RFC 3986. ^If the URI contains an
2448
+** authority, then it must be either an empty string or the string
2449
+** "localhost". ^If the authority is not an empty string or "localhost", an
2450
+** error is returned to the caller. ^The fragment component of a URI, if
2451
+** present, is ignored.
2452
+**
2453
+** ^SQLite uses the path component of the URI as the name of the disk file
2454
+** which contains the database. ^If the path begins with a '/' character,
2455
+** then it is interpreted as an absolute path. ^If the path does not begin
2456
+** with a '/' (meaning that the authority section is omitted from the URI)
2457
+** then the path is interpreted as a relative path.
2458
+** ^On windows, the first component of an absolute path
2459
+** is a drive specification (e.g. "C:").
2460
+**
2461
+** [[core URI query parameters]]
2462
+** The query component of a URI may contain parameters that are interpreted
2463
+** either by SQLite itself, or by a [VFS | custom VFS implementation].
2464
+** SQLite interprets the following three query parameters:
2465
+**
2466
+** <ul>
2467
+** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
2468
+** a VFS object that provides the operating system interface that should
2469
+** be used to access the database file on disk. ^If this option is set to
2470
+** an empty string the default VFS object is used. ^Specifying an unknown
2471
+** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
2472
+** present, then the VFS specified by the option takes precedence over
2473
+** the value passed as the fourth parameter to sqlite3_open_v2().
2474
+**
2475
+** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
2476
+** "rwc". Attempting to set it to any other value is an error)^.
2477
+** ^If "ro" is specified, then the database is opened for read-only
2478
+** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
2479
+** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
2480
+** "rw", then the database is opened for read-write (but not create)
2481
+** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
2482
+** been set. ^Value "rwc" is equivalent to setting both
2483
+** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
2484
+** used, it is an error to specify a value for the mode parameter that is
2485
+** less restrictive than that specified by the flags passed as the third
2486
+** parameter.
2487
+**
2488
+** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
2489
+** "private". ^Setting it to "shared" is equivalent to setting the
2490
+** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
2491
+** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
2492
+** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
2493
+** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
2494
+** a URI filename, its value overrides any behaviour requested by setting
2495
+** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
2496
+** </ul>
2497
+**
2498
+** ^Specifying an unknown parameter in the query component of a URI is not an
2499
+** error. Future versions of SQLite might understand additional query
2500
+** parameters. See "[query parameters with special meaning to SQLite]" for
2501
+** additional information.
2502
+**
2503
+** [[URI filename examples]] <h3>URI filename examples</h3>
2504
+**
2505
+** <table border="1" align=center cellpadding=5>
2506
+** <tr><th> URI filenames <th> Results
2507
+** <tr><td> file:data.db <td>
2508
+** Open the file "data.db" in the current directory.
2509
+** <tr><td> file:/home/fred/data.db<br>
2510
+** file:///home/fred/data.db <br>
2511
+** file://localhost/home/fred/data.db <br> <td>
2512
+** Open the database file "/home/fred/data.db".
2513
+** <tr><td> file://darkstar/home/fred/data.db <td>
2514
+** An error. "darkstar" is not a recognized authority.
2515
+** <tr><td style="white-space:nowrap">
2516
+** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
2517
+** <td> Windows only: Open the file "data.db" on fred's desktop on drive
2518
+** C:. Note that the %20 escaping in this example is not strictly
2519
+** necessary - space characters can be used literally
2520
+** in URI filenames.
2521
+** <tr><td> file:data.db?mode=ro&cache=private <td>
2522
+** Open file "data.db" in the current directory for read-only access.
2523
+** Regardless of whether or not shared-cache mode is enabled by
2524
+** default, use a private cache.
2525
+** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
2526
+** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
2527
+** <tr><td> file:data.db?mode=readonly <td>
2528
+** An error. "readonly" is not a valid option for the "mode" parameter.
2529
+** </table>
2530
+**
2531
+** ^URI hexadecimal escape sequences (%HH) are supported within the path and
2532
+** query components of a URI. A hexadecimal escape sequence consists of a
2533
+** percent sign - "%" - followed by exactly two hexadecimal digits
2534
+** specifying an octet value. ^Before the path or query components of a
2535
+** URI filename are interpreted, they are encoded using UTF-8 and all
2536
+** hexadecimal escape sequences replaced by a single byte containing the
2537
+** corresponding octet. If this process generates an invalid UTF-8 encoding,
2538
+** the results are undefined.
24052539
**
24062540
** <b>Note to Windows users:</b> The encoding used for the filename argument
24072541
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
24082542
** codepage is currently defined. Filenames containing international
24092543
** characters must be converted to UTF-8 prior to passing them into
@@ -2421,10 +2555,30 @@
24212555
const char *filename, /* Database filename (UTF-8) */
24222556
sqlite3 **ppDb, /* OUT: SQLite db handle */
24232557
int flags, /* Flags */
24242558
const char *zVfs /* Name of VFS module to use */
24252559
);
2560
+
2561
+/*
2562
+** CAPI3REF: Obtain Values For URI Parameters
2563
+**
2564
+** This is a utility routine, useful to VFS implementations, that checks
2565
+** to see if a database file was a URI that contained a specific query
2566
+** parameter, and if so obtains the value of the query parameter.
2567
+**
2568
+** The zFilename argument is the filename pointer passed into the xOpen()
2569
+** method of a VFS implementation. The zParam argument is the name of the
2570
+** query parameter we seek. This routine returns the value of the zParam
2571
+** parameter if it exists. If the parameter does not exist, this routine
2572
+** returns a NULL pointer.
2573
+**
2574
+** If the zFilename argument to this function is not a pointer that SQLite
2575
+** passed into the xOpen VFS method, then the behavior of this routine
2576
+** is undefined and probably undesirable.
2577
+*/
2578
+SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
2579
+
24262580
24272581
/*
24282582
** CAPI3REF: Error Codes And Messages
24292583
**
24302584
** ^The sqlite3_errcode() interface returns the numeric [result code] or
@@ -2537,47 +2691,49 @@
25372691
** that can be lowered at run-time using [sqlite3_limit()].
25382692
** The synopsis of the meanings of the various limits is shown below.
25392693
** Additional information is available at [limits | Limits in SQLite].
25402694
**
25412695
** <dl>
2542
-** ^(<dt>SQLITE_LIMIT_LENGTH</dt>
2696
+** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
25432697
** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
25442698
**
2545
-** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
2699
+** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
25462700
** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
25472701
**
2548
-** ^(<dt>SQLITE_LIMIT_COLUMN</dt>
2702
+** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
25492703
** <dd>The maximum number of columns in a table definition or in the
25502704
** result set of a [SELECT] or the maximum number of columns in an index
25512705
** or in an ORDER BY or GROUP BY clause.</dd>)^
25522706
**
2553
-** ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
2707
+** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
25542708
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
25552709
**
2556
-** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
2710
+** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
25572711
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
25582712
**
2559
-** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
2713
+** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
25602714
** <dd>The maximum number of instructions in a virtual machine program
25612715
** used to implement an SQL statement. This limit is not currently
25622716
** enforced, though that might be added in some future release of
25632717
** SQLite.</dd>)^
25642718
**
2565
-** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
2719
+** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
25662720
** <dd>The maximum number of arguments on a function.</dd>)^
25672721
**
2568
-** ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
2722
+** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
25692723
** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
25702724
**
2725
+** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
25712726
** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
25722727
** <dd>The maximum length of the pattern argument to the [LIKE] or
25732728
** [GLOB] operators.</dd>)^
25742729
**
2730
+** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
25752731
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
25762732
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
25772733
**
2578
-** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
2734
+** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
25792735
** <dd>The maximum depth of recursion for triggers.</dd>)^
25802736
** </dl>
25812737
*/
25822738
#define SQLITE_LIMIT_LENGTH 0
25832739
#define SQLITE_LIMIT_SQL_LENGTH 1
@@ -4608,10 +4764,15 @@
46084764
int (*xRollback)(sqlite3_vtab *pVTab);
46094765
int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
46104766
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
46114767
void **ppArg);
46124768
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
4769
+ /* The methods above are in version 1 of the sqlite_module object. Those
4770
+ ** below are for version 2 and greater. */
4771
+ int (*xSavepoint)(sqlite3_vtab *pVTab, int);
4772
+ int (*xRelease)(sqlite3_vtab *pVTab, int);
4773
+ int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
46134774
};
46144775
46154776
/*
46164777
** CAPI3REF: Virtual Table Indexing Information
46174778
** KEYWORDS: sqlite3_index_info
@@ -5422,11 +5583,11 @@
54225583
**
54235584
** ^This interface is used to retrieve runtime status information
54245585
** about the performance of SQLite, and optionally to reset various
54255586
** highwater marks. ^The first argument is an integer code for
54265587
** the specific parameter to measure. ^(Recognized integer codes
5427
-** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
5588
+** are of the form [status parameters | SQLITE_STATUS_...].)^
54285589
** ^The current value of the parameter is returned into *pCurrent.
54295590
** ^The highest recorded value is returned in *pHighwater. ^If the
54305591
** resetFlag is true, then the highest record value is reset after
54315592
** *pHighwater is written. ^(Some parameters do not record the highest
54325593
** value. For those parameters
@@ -5449,82 +5610,84 @@
54495610
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
54505611
54515612
54525613
/*
54535614
** CAPI3REF: Status Parameters
5615
+** KEYWORDS: {status parameters}
54545616
**
54555617
** These integer constants designate various run-time status parameters
54565618
** that can be returned by [sqlite3_status()].
54575619
**
54585620
** <dl>
5459
-** ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
5621
+** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
54605622
** <dd>This parameter is the current amount of memory checked out
54615623
** using [sqlite3_malloc()], either directly or indirectly. The
54625624
** figure includes calls made to [sqlite3_malloc()] by the application
54635625
** and internal memory usage by the SQLite library. Scratch memory
54645626
** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
54655627
** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
54665628
** this parameter. The amount returned is the sum of the allocation
54675629
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
54685630
**
5469
-** ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
5631
+** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
54705632
** <dd>This parameter records the largest memory allocation request
54715633
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
54725634
** internal equivalents). Only the value returned in the
54735635
** *pHighwater parameter to [sqlite3_status()] is of interest.
54745636
** The value written into the *pCurrent parameter is undefined.</dd>)^
54755637
**
5476
-** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
5638
+** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
54775639
** <dd>This parameter records the number of separate memory allocations
54785640
** currently checked out.</dd>)^
54795641
**
5480
-** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
5642
+** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
54815643
** <dd>This parameter returns the number of pages used out of the
54825644
** [pagecache memory allocator] that was configured using
54835645
** [SQLITE_CONFIG_PAGECACHE]. The
54845646
** value returned is in pages, not in bytes.</dd>)^
54855647
**
5648
+** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
54865649
** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
54875650
** <dd>This parameter returns the number of bytes of page cache
54885651
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
54895652
** buffer and where forced to overflow to [sqlite3_malloc()]. The
54905653
** returned value includes allocations that overflowed because they
54915654
** where too large (they were larger than the "sz" parameter to
54925655
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
54935656
** no space was left in the page cache.</dd>)^
54945657
**
5495
-** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
5658
+** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
54965659
** <dd>This parameter records the largest memory allocation request
54975660
** handed to [pagecache memory allocator]. Only the value returned in the
54985661
** *pHighwater parameter to [sqlite3_status()] is of interest.
54995662
** The value written into the *pCurrent parameter is undefined.</dd>)^
55005663
**
5501
-** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
5664
+** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
55025665
** <dd>This parameter returns the number of allocations used out of the
55035666
** [scratch memory allocator] configured using
55045667
** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
55055668
** in bytes. Since a single thread may only have one scratch allocation
55065669
** outstanding at time, this parameter also reports the number of threads
55075670
** using scratch memory at the same time.</dd>)^
55085671
**
5509
-** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
5672
+** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
55105673
** <dd>This parameter returns the number of bytes of scratch memory
55115674
** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
55125675
** buffer and where forced to overflow to [sqlite3_malloc()]. The values
55135676
** returned include overflows because the requested allocation was too
55145677
** larger (that is, because the requested allocation was larger than the
55155678
** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
55165679
** slots were available.
55175680
** </dd>)^
55185681
**
5519
-** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
5682
+** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
55205683
** <dd>This parameter records the largest memory allocation request
55215684
** handed to [scratch memory allocator]. Only the value returned in the
55225685
** *pHighwater parameter to [sqlite3_status()] is of interest.
55235686
** The value written into the *pCurrent parameter is undefined.</dd>)^
55245687
**
5525
-** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
5688
+** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
55265689
** <dd>This parameter records the deepest parser stack. It is only
55275690
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
55285691
** </dl>
55295692
**
55305693
** New status parameters may be added from time to time.
@@ -5545,13 +5708,13 @@
55455708
**
55465709
** ^This interface is used to retrieve runtime status information
55475710
** about a single [database connection]. ^The first argument is the
55485711
** database connection object to be interrogated. ^The second argument
55495712
** is an integer constant, taken from the set of
5550
-** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
5713
+** [SQLITE_DBSTATUS options], that
55515714
** determines the parameter to interrogate. The set of
5552
-** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
5715
+** [SQLITE_DBSTATUS options] is likely
55535716
** to grow in future releases of SQLite.
55545717
**
55555718
** ^The current value of the requested parameter is written into *pCur
55565719
** and the highest instantaneous value is written into *pHiwtr. ^If
55575720
** the resetFlg is true, then the highest instantaneous value is
@@ -5564,10 +5727,11 @@
55645727
*/
55655728
SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
55665729
55675730
/*
55685731
** CAPI3REF: Status Parameters for database connections
5732
+** KEYWORDS: {SQLITE_DBSTATUS options}
55695733
**
55705734
** These constants are the available integer "verbs" that can be passed as
55715735
** the second argument to the [sqlite3_db_status()] interface.
55725736
**
55735737
** New verbs may be added in future releases of SQLite. Existing verbs
@@ -5575,48 +5739,50 @@
55755739
** [sqlite3_db_status()] to make sure that the call worked.
55765740
** The [sqlite3_db_status()] interface will return a non-zero error code
55775741
** if a discontinued or unsupported verb is invoked.
55785742
**
55795743
** <dl>
5580
-** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
5744
+** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
55815745
** <dd>This parameter returns the number of lookaside memory slots currently
55825746
** checked out.</dd>)^
55835747
**
5584
-** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
5748
+** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
55855749
** <dd>This parameter returns the number malloc attempts that were
55865750
** satisfied using lookaside memory. Only the high-water value is meaningful;
55875751
** the current value is always zero.)^
55885752
**
5753
+** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
55895754
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
55905755
** <dd>This parameter returns the number malloc attempts that might have
55915756
** been satisfied using lookaside memory but failed due to the amount of
55925757
** memory requested being larger than the lookaside slot size.
55935758
** Only the high-water value is meaningful;
55945759
** the current value is always zero.)^
55955760
**
5761
+** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
55965762
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
55975763
** <dd>This parameter returns the number malloc attempts that might have
55985764
** been satisfied using lookaside memory but failed due to all lookaside
55995765
** memory already being in use.
56005766
** Only the high-water value is meaningful;
56015767
** the current value is always zero.)^
56025768
**
5603
-** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
5769
+** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
56045770
** <dd>This parameter returns the approximate number of of bytes of heap
56055771
** memory used by all pager caches associated with the database connection.)^
56065772
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
56075773
**
5608
-** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
5774
+** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
56095775
** <dd>This parameter returns the approximate number of of bytes of heap
56105776
** memory used to store the schema for all databases associated
56115777
** with the connection - main, temp, and any [ATTACH]-ed databases.)^
56125778
** ^The full amount of memory used by the schemas is reported, even if the
56135779
** schema memory is shared with other database connections due to
56145780
** [shared cache mode] being enabled.
56155781
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
56165782
**
5617
-** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
5783
+** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
56185784
** <dd>This parameter returns the approximate number of of bytes of heap
56195785
** and lookaside memory used by all prepared statements associated with
56205786
** the database connection.)^
56215787
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
56225788
** </dd>
@@ -5634,11 +5800,11 @@
56345800
56355801
/*
56365802
** CAPI3REF: Prepared Statement Status
56375803
**
56385804
** ^(Each prepared statement maintains various
5639
-** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
5805
+** [SQLITE_STMTSTATUS counters] that measure the number
56405806
** of times it has performed specific operations.)^ These counters can
56415807
** be used to monitor the performance characteristics of the prepared
56425808
** statements. For example, if the number of table steps greatly exceeds
56435809
** the number of table searches or result rows, that would tend to indicate
56445810
** that the prepared statement is using a full table scan rather than
@@ -5645,11 +5811,11 @@
56455811
** an index.
56465812
**
56475813
** ^(This interface is used to retrieve and reset counter values from
56485814
** a [prepared statement]. The first argument is the prepared statement
56495815
** object to be interrogated. The second argument
5650
-** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
5816
+** is an integer code for a specific [SQLITE_STMTSTATUS counter]
56515817
** to be interrogated.)^
56525818
** ^The current value of the requested counter is returned.
56535819
** ^If the resetFlg is true, then the counter is reset to zero after this
56545820
** interface call returns.
56555821
**
@@ -5657,28 +5823,29 @@
56575823
*/
56585824
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
56595825
56605826
/*
56615827
** CAPI3REF: Status Parameters for prepared statements
5828
+** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
56625829
**
56635830
** These preprocessor macros define integer codes that name counter
56645831
** values associated with the [sqlite3_stmt_status()] interface.
56655832
** The meanings of the various counters are as follows:
56665833
**
56675834
** <dl>
5668
-** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
5835
+** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
56695836
** <dd>^This is the number of times that SQLite has stepped forward in
56705837
** a table as part of a full table scan. Large numbers for this counter
56715838
** may indicate opportunities for performance improvement through
56725839
** careful use of indices.</dd>
56735840
**
5674
-** <dt>SQLITE_STMTSTATUS_SORT</dt>
5841
+** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
56755842
** <dd>^This is the number of sort operations that have occurred.
56765843
** A non-zero value in this counter may indicate an opportunity to
56775844
** improvement performance through careful use of indices.</dd>
56785845
**
5679
-** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
5846
+** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
56805847
** <dd>^This is the number of rows inserted into transient indices that
56815848
** were created automatically in order to help joins run faster.
56825849
** A non-zero value in this counter may indicate an opportunity to
56835850
** improvement performance by adding permanent indices that do not
56845851
** need to be reinitialized each time the statement is run.</dd>
@@ -5725,10 +5892,11 @@
57255892
** ^(The contents of the sqlite3_pcache_methods structure are copied to an
57265893
** internal buffer by SQLite within the call to [sqlite3_config]. Hence
57275894
** the application may discard the parameter after the call to
57285895
** [sqlite3_config()] returns.)^
57295896
**
5897
+** [[the xInit() page cache method]]
57305898
** ^(The xInit() method is called once for each effective
57315899
** call to [sqlite3_initialize()])^
57325900
** (usually only once during the lifetime of the process). ^(The xInit()
57335901
** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^
57345902
** The intent of the xInit() method is to set up global data structures
@@ -5735,10 +5903,11 @@
57355903
** required by the custom page cache implementation.
57365904
** ^(If the xInit() method is NULL, then the
57375905
** built-in default page cache is used instead of the application defined
57385906
** page cache.)^
57395907
**
5908
+** [[the xShutdown() page cache method]]
57405909
** ^The xShutdown() method is called by [sqlite3_shutdown()].
57415910
** It can be used to clean up
57425911
** any outstanding resources before process shutdown, if required.
57435912
** ^The xShutdown() method may be NULL.
57445913
**
@@ -5749,10 +5918,11 @@
57495918
** in multithreaded applications.
57505919
**
57515920
** ^SQLite will never invoke xInit() more than once without an intervening
57525921
** call to xShutdown().
57535922
**
5923
+** [[the xCreate() page cache methods]]
57545924
** ^SQLite invokes the xCreate() method to construct a new cache instance.
57555925
** SQLite will typically create one cache instance for each open database file,
57565926
** though this is not guaranteed. ^The
57575927
** first parameter, szPage, is the size in bytes of the pages that must
57585928
** be allocated by the cache. ^szPage will not be a power of two. ^szPage
@@ -5773,20 +5943,23 @@
57735943
** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
57745944
** false will always have the "discard" flag set to true.
57755945
** ^Hence, a cache created with bPurgeable false will
57765946
** never contain any unpinned pages.
57775947
**
5948
+** [[the xCachesize() page cache method]]
57785949
** ^(The xCachesize() method may be called at any time by SQLite to set the
57795950
** suggested maximum cache-size (number of pages stored by) the cache
57805951
** instance passed as the first argument. This is the value configured using
57815952
** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
57825953
** parameter, the implementation is not required to do anything with this
57835954
** value; it is advisory only.
57845955
**
5956
+** [[the xPagecount() page cache methods]]
57855957
** The xPagecount() method must return the number of pages currently
57865958
** stored in the cache, both pinned and unpinned.
57875959
**
5960
+** [[the xFetch() page cache methods]]
57885961
** The xFetch() method locates a page in the cache and returns a pointer to
57895962
** the page, or a NULL pointer.
57905963
** A "page", in this context, means a buffer of szPage bytes aligned at an
57915964
** 8-byte boundary. The page to be fetched is determined by the key. ^The
57925965
** mimimum key value is 1. After it has been retrieved using xFetch, the page
@@ -5811,10 +5984,11 @@
58115984
** will only use a createFlag of 2 after a prior call with a createFlag of 1
58125985
** failed.)^ In between the to xFetch() calls, SQLite may
58135986
** attempt to unpin one or more cache pages by spilling the content of
58145987
** pinned pages to disk and synching the operating system disk cache.
58155988
**
5989
+** [[the xUnpin() page cache method]]
58165990
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
58175991
** as its second argument. If the third parameter, discard, is non-zero,
58185992
** then the page must be evicted from the cache.
58195993
** ^If the discard parameter is
58205994
** zero, then the page may be discarded or retained at the discretion of
@@ -5823,10 +5997,11 @@
58235997
**
58245998
** The cache must not perform any reference counting. A single
58255999
** call to xUnpin() unpins the page regardless of the number of prior calls
58266000
** to xFetch().
58276001
**
6002
+** [[the xRekey() page cache methods]]
58286003
** The xRekey() method is used to change the key value associated with the
58296004
** page passed as the second argument. If the cache
58306005
** previously contains an entry associated with newKey, it must be
58316006
** discarded. ^Any prior cache entry associated with newKey is guaranteed not
58326007
** to be pinned.
@@ -5835,10 +6010,11 @@
58356010
** existing cache entries with page numbers (keys) greater than or equal
58366011
** to the value of the iLimit parameter passed to xTruncate(). If any
58376012
** of these pages are pinned, they are implicitly unpinned, meaning that
58386013
** they can be safely discarded.
58396014
**
6015
+** [[the xDestroy() page cache method]]
58406016
** ^The xDestroy() method is used to delete a cache allocated by xCreate().
58416017
** All resources associated with the specified cache should be freed. ^After
58426018
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
58436019
** handle invalid, and will not use it with any other sqlite3_pcache_methods
58446020
** functions.
@@ -5897,11 +6073,11 @@
58976073
** associated with the backup operation.
58986074
** </ol>)^
58996075
** There should be exactly one call to sqlite3_backup_finish() for each
59006076
** successful call to sqlite3_backup_init().
59016077
**
5902
-** <b>sqlite3_backup_init()</b>
6078
+** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
59036079
**
59046080
** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
59056081
** [database connection] associated with the destination database
59066082
** and the database name, respectively.
59076083
** ^The database name is "main" for the main database, "temp" for the
@@ -5924,11 +6100,11 @@
59246100
** [sqlite3_backup] object.
59256101
** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
59266102
** sqlite3_backup_finish() functions to perform the specified backup
59276103
** operation.
59286104
**
5929
-** <b>sqlite3_backup_step()</b>
6105
+** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
59306106
**
59316107
** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
59326108
** the source and destination databases specified by [sqlite3_backup] object B.
59336109
** ^If N is negative, all remaining source pages are copied.
59346110
** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
@@ -5981,11 +6157,11 @@
59816157
** restarted by the next call to sqlite3_backup_step(). ^If the source
59826158
** database is modified by the using the same database connection as is used
59836159
** by the backup operation, then the backup database is automatically
59846160
** updated at the same time.
59856161
**
5986
-** <b>sqlite3_backup_finish()</b>
6162
+** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
59876163
**
59886164
** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
59896165
** application wishes to abandon the backup operation, the application
59906166
** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
59916167
** ^The sqlite3_backup_finish() interfaces releases all
@@ -6004,11 +6180,12 @@
60046180
**
60056181
** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
60066182
** is not a permanent error and does not affect the return value of
60076183
** sqlite3_backup_finish().
60086184
**
6009
-** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b>
6185
+** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
6186
+** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
60106187
**
60116188
** ^Each call to sqlite3_backup_step() sets two values inside
60126189
** the [sqlite3_backup] object: the number of pages still to be backed
60136190
** up and the total number of pages in the source database file.
60146191
** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
@@ -6389,10 +6566,97 @@
63896566
** each of these values.
63906567
*/
63916568
#define SQLITE_CHECKPOINT_PASSIVE 0
63926569
#define SQLITE_CHECKPOINT_FULL 1
63936570
#define SQLITE_CHECKPOINT_RESTART 2
6571
+
6572
+/*
6573
+** CAPI3REF: Virtual Table Interface Configuration
6574
+**
6575
+** This function may be called by either the [xConnect] or [xCreate] method
6576
+** of a [virtual table] implementation to configure
6577
+** various facets of the virtual table interface.
6578
+**
6579
+** If this interface is invoked outside the context of an xConnect or
6580
+** xCreate virtual table method then the behavior is undefined.
6581
+**
6582
+** At present, there is only one option that may be configured using
6583
+** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
6584
+** may be added in the future.
6585
+*/
6586
+SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
6587
+
6588
+/*
6589
+** CAPI3REF: Virtual Table Configuration Options
6590
+**
6591
+** These macros define the various options to the
6592
+** [sqlite3_vtab_config()] interface that [virtual table] implementations
6593
+** can use to customize and optimize their behavior.
6594
+**
6595
+** <dl>
6596
+** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
6597
+** <dd>Calls of the form
6598
+** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
6599
+** where X is an integer. If X is zero, then the [virtual table] whose
6600
+** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
6601
+** support constraints. In this configuration (which is the default) if
6602
+** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
6603
+** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
6604
+** specified as part of the users SQL statement, regardless of the actual
6605
+** ON CONFLICT mode specified.
6606
+**
6607
+** If X is non-zero, then the virtual table implementation guarantees
6608
+** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
6609
+** any modifications to internal or persistent data structures have been made.
6610
+** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
6611
+** is able to roll back a statement or database transaction, and abandon
6612
+** or continue processing the current SQL statement as appropriate.
6613
+** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
6614
+** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
6615
+** had been ABORT.
6616
+**
6617
+** Virtual table implementations that are required to handle OR REPLACE
6618
+** must do so within the [xUpdate] method. If a call to the
6619
+** [sqlite3_vtab_on_conflict()] function indicates that the current ON
6620
+** CONFLICT policy is REPLACE, the virtual table implementation should
6621
+** silently replace the appropriate rows within the xUpdate callback and
6622
+** return SQLITE_OK. Or, if this is not possible, it may return
6623
+** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
6624
+** constraint handling.
6625
+** </dl>
6626
+*/
6627
+#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
6628
+
6629
+/*
6630
+** CAPI3REF: Determine The Virtual Table Conflict Policy
6631
+**
6632
+** This function may only be called from within a call to the [xUpdate] method
6633
+** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
6634
+** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
6635
+** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
6636
+** of the SQL statement that triggered the call to the [xUpdate] method of the
6637
+** [virtual table].
6638
+*/
6639
+SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
6640
+
6641
+/*
6642
+** CAPI3REF: Conflict resolution modes
6643
+**
6644
+** These constants are returned by [sqlite3_vtab_on_conflict()] to
6645
+** inform a [virtual table] implementation what the [ON CONFLICT] mode
6646
+** is for the SQL statement being evaluated.
6647
+**
6648
+** Note that the [SQLITE_IGNORE] constant is also used as a potential
6649
+** return value from the [sqlite3_set_authorizer()] callback and that
6650
+** [SQLITE_ABORT] is also a [result code].
6651
+*/
6652
+#define SQLITE_ROLLBACK 1
6653
+/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
6654
+#define SQLITE_FAIL 3
6655
+/* #define SQLITE_ABORT 4 // Also an error code */
6656
+#define SQLITE_REPLACE 5
6657
+
63946658
63956659
63966660
/*
63976661
** Undo the hack that converts floating point types to integer for
63986662
** builds on processors without floating point support.
63996663
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.6"
111 #define SQLITE_VERSION_NUMBER 3007006
112 #define SQLITE_SOURCE_ID "2011-04-12 01:58:40 f9d43fa363d54beab6f45db005abac0a7c0c47a7"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -373,11 +373,12 @@
373 ** Many SQLite functions return an integer result code from the set shown
374 ** here in order to indicates success or failure.
375 **
376 ** New error codes may be added in future versions of SQLite.
377 **
378 ** See also: [SQLITE_IOERR_READ | extended result codes]
 
379 */
380 #define SQLITE_OK 0 /* Successful result */
381 /* beginning-of-error-codes */
382 #define SQLITE_ERROR 1 /* SQL error or missing database */
383 #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -450,28 +451,31 @@
450 #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
451 #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
452 #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
453 #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
454 #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
 
 
455 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
456 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
457 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
 
458
459 /*
460 ** CAPI3REF: Flags For File Open Operations
461 **
462 ** These bit values are intended for use in the
463 ** 3rd parameter to the [sqlite3_open_v2()] interface and
464 ** in the 4th parameter to the xOpen method of the
465 ** [sqlite3_vfs] object.
466 */
467 #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
468 #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
469 #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
470 #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
471 #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
472 #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
 
473 #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
474 #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
475 #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
476 #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
477 #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
@@ -578,21 +582,22 @@
578 };
579
580 /*
581 ** CAPI3REF: OS Interface File Virtual Methods Object
582 **
583 ** Every file opened by the [sqlite3_vfs] xOpen method populates an
584 ** [sqlite3_file] object (or, more commonly, a subclass of the
585 ** [sqlite3_file] object) with a pointer to an instance of this object.
586 ** This object defines the methods used to perform various operations
587 ** against the open file represented by the [sqlite3_file] object.
588 **
589 ** If the xOpen method sets the sqlite3_file.pMethods element
590 ** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
591 ** may be invoked even if the xOpen reported that it failed. The
592 ** only way to prevent a call to xClose following a failed xOpen
593 ** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
 
594 **
595 ** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
596 ** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
597 ** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
598 ** flag may be ORed in to indicate that only the data of the file
@@ -757,10 +762,11 @@
757 */
758 typedef struct sqlite3_mutex sqlite3_mutex;
759
760 /*
761 ** CAPI3REF: OS Interface Object
 
762 **
763 ** An instance of the sqlite3_vfs object defines the interface between
764 ** the SQLite core and the underlying operating system. The "vfs"
765 ** in the name of the object stands for "virtual file system".
766 **
@@ -789,10 +795,11 @@
789 ** object once the object has been registered.
790 **
791 ** The zName field holds the name of the VFS module. The name must
792 ** be unique across all VFS modules.
793 **
 
794 ** ^SQLite guarantees that the zFilename parameter to xOpen
795 ** is either a NULL pointer or string obtained
796 ** from xFullPathname() with an optional suffix added.
797 ** ^If a suffix is added to the zFilename parameter, it will
798 ** consist of a single "-" character followed by no more than
@@ -866,10 +873,11 @@
866 ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
867 ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
868 ** element will be valid after xOpen returns regardless of the success
869 ** or failure of the xOpen call.
870 **
 
871 ** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
872 ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
873 ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
874 ** to test whether a file is at least readable. The file can be a
875 ** directory.
@@ -1112,13 +1120,13 @@
1112 ** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
1113 ** Note, however, that ^sqlite3_config() can be called as part of the
1114 ** implementation of an application-defined [sqlite3_os_init()].
1115 **
1116 ** The first argument to sqlite3_config() is an integer
1117 ** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
1118 ** what property of SQLite is to be configured. Subsequent arguments
1119 ** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
1120 ** in the first argument.
1121 **
1122 ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
1123 ** ^If the option is unknown or SQLite is unable to set the option
1124 ** then this routine returns a non-zero [error code].
@@ -1224,10 +1232,11 @@
1224 void *pAppData; /* Argument to xInit() and xShutdown() */
1225 };
1226
1227 /*
1228 ** CAPI3REF: Configuration Options
 
1229 **
1230 ** These constants are the available integer configuration options that
1231 ** can be passed as the first argument to the [sqlite3_config()] interface.
1232 **
1233 ** New configuration options may be added in future releases of SQLite.
@@ -1236,11 +1245,11 @@
1236 ** the call worked. The [sqlite3_config()] interface will return a
1237 ** non-zero [error code] if a discontinued or unsupported configuration option
1238 ** is invoked.
1239 **
1240 ** <dl>
1241 ** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
1242 ** <dd>There are no arguments to this option. ^This option sets the
1243 ** [threading mode] to Single-thread. In other words, it disables
1244 ** all mutexing and puts SQLite into a mode where it can only be used
1245 ** by a single thread. ^If SQLite is compiled with
1246 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
@@ -1247,11 +1256,11 @@
1247 ** it is not possible to change the [threading mode] from its default
1248 ** value of Single-thread and so [sqlite3_config()] will return
1249 ** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
1250 ** configuration option.</dd>
1251 **
1252 ** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
1253 ** <dd>There are no arguments to this option. ^This option sets the
1254 ** [threading mode] to Multi-thread. In other words, it disables
1255 ** mutexing on [database connection] and [prepared statement] objects.
1256 ** The application is responsible for serializing access to
1257 ** [database connections] and [prepared statements]. But other mutexes
@@ -1261,11 +1270,11 @@
1261 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1262 ** it is not possible to set the Multi-thread [threading mode] and
1263 ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
1264 ** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
1265 **
1266 ** <dt>SQLITE_CONFIG_SERIALIZED</dt>
1267 ** <dd>There are no arguments to this option. ^This option sets the
1268 ** [threading mode] to Serialized. In other words, this option enables
1269 ** all mutexes including the recursive
1270 ** mutexes on [database connection] and [prepared statement] objects.
1271 ** In this mode (which is the default when SQLite is compiled with
@@ -1277,27 +1286,27 @@
1277 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1278 ** it is not possible to set the Serialized [threading mode] and
1279 ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
1280 ** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
1281 **
1282 ** <dt>SQLITE_CONFIG_MALLOC</dt>
1283 ** <dd> ^(This option takes a single argument which is a pointer to an
1284 ** instance of the [sqlite3_mem_methods] structure. The argument specifies
1285 ** alternative low-level memory allocation routines to be used in place of
1286 ** the memory allocation routines built into SQLite.)^ ^SQLite makes
1287 ** its own private copy of the content of the [sqlite3_mem_methods] structure
1288 ** before the [sqlite3_config()] call returns.</dd>
1289 **
1290 ** <dt>SQLITE_CONFIG_GETMALLOC</dt>
1291 ** <dd> ^(This option takes a single argument which is a pointer to an
1292 ** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
1293 ** structure is filled with the currently defined memory allocation routines.)^
1294 ** This option can be used to overload the default memory allocation
1295 ** routines with a wrapper that simulations memory allocation failure or
1296 ** tracks memory usage, for example. </dd>
1297 **
1298 ** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
1299 ** <dd> ^This option takes single argument of type int, interpreted as a
1300 ** boolean, which enables or disables the collection of memory allocation
1301 ** statistics. ^(When memory allocation statistics are disabled, the
1302 ** following SQLite interfaces become non-operational:
1303 ** <ul>
@@ -1309,11 +1318,11 @@
1309 ** ^Memory allocation statistics are enabled by default unless SQLite is
1310 ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
1311 ** allocation statistics are disabled by default.
1312 ** </dd>
1313 **
1314 ** <dt>SQLITE_CONFIG_SCRATCH</dt>
1315 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1316 ** scratch memory. There are three arguments: A pointer an 8-byte
1317 ** aligned memory buffer from which the scratch allocations will be
1318 ** drawn, the size of each scratch allocation (sz),
1319 ** and the maximum number of scratch allocations (N). The sz
@@ -1325,11 +1334,11 @@
1325 ** ^SQLite will never require a scratch buffer that is more than 6
1326 ** times the database page size. ^If SQLite needs needs additional
1327 ** scratch memory beyond what is provided by this configuration option, then
1328 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
1329 **
1330 ** <dt>SQLITE_CONFIG_PAGECACHE</dt>
1331 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1332 ** the database page cache with the default page cache implemenation.
1333 ** This configuration should not be used if an application-define page
1334 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
1335 ** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1346,11 +1355,11 @@
1346 ** SQLite goes to [sqlite3_malloc()] for the additional storage space.
1347 ** The pointer in the first argument must
1348 ** be aligned to an 8-byte boundary or subsequent behavior of SQLite
1349 ** will be undefined.</dd>
1350 **
1351 ** <dt>SQLITE_CONFIG_HEAP</dt>
1352 ** <dd> ^This option specifies a static memory buffer that SQLite will use
1353 ** for all of its dynamic memory allocation needs beyond those provided
1354 ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
1355 ** There are three arguments: An 8-byte aligned pointer to the memory,
1356 ** the number of bytes in the memory buffer, and the minimum allocation size.
@@ -1363,11 +1372,11 @@
1363 ** The first pointer (the memory pointer) must be aligned to an 8-byte
1364 ** boundary or subsequent behavior of SQLite will be undefined.
1365 ** The minimum allocation size is capped at 2^12. Reasonable values
1366 ** for the minimum allocation size are 2^5 through 2^8.</dd>
1367 **
1368 ** <dt>SQLITE_CONFIG_MUTEX</dt>
1369 ** <dd> ^(This option takes a single argument which is a pointer to an
1370 ** instance of the [sqlite3_mutex_methods] structure. The argument specifies
1371 ** alternative low-level mutex routines to be used in place
1372 ** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
1373 ** content of the [sqlite3_mutex_methods] structure before the call to
@@ -1375,11 +1384,11 @@
1375 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1376 ** the entire mutexing subsystem is omitted from the build and hence calls to
1377 ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
1378 ** return [SQLITE_ERROR].</dd>
1379 **
1380 ** <dt>SQLITE_CONFIG_GETMUTEX</dt>
1381 ** <dd> ^(This option takes a single argument which is a pointer to an
1382 ** instance of the [sqlite3_mutex_methods] structure. The
1383 ** [sqlite3_mutex_methods]
1384 ** structure is filled with the currently defined mutex routines.)^
1385 ** This option can be used to overload the default mutex allocation
@@ -1388,32 +1397,32 @@
1388 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1389 ** the entire mutexing subsystem is omitted from the build and hence calls to
1390 ** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
1391 ** return [SQLITE_ERROR].</dd>
1392 **
1393 ** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
1394 ** <dd> ^(This option takes two arguments that determine the default
1395 ** memory allocation for the lookaside memory allocator on each
1396 ** [database connection]. The first argument is the
1397 ** size of each lookaside buffer slot and the second is the number of
1398 ** slots allocated to each database connection.)^ ^(This option sets the
1399 ** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
1400 ** verb to [sqlite3_db_config()] can be used to change the lookaside
1401 ** configuration on individual connections.)^ </dd>
1402 **
1403 ** <dt>SQLITE_CONFIG_PCACHE</dt>
1404 ** <dd> ^(This option takes a single argument which is a pointer to
1405 ** an [sqlite3_pcache_methods] object. This object specifies the interface
1406 ** to a custom page cache implementation.)^ ^SQLite makes a copy of the
1407 ** object and uses it for page cache memory allocations.</dd>
1408 **
1409 ** <dt>SQLITE_CONFIG_GETPCACHE</dt>
1410 ** <dd> ^(This option takes a single argument which is a pointer to an
1411 ** [sqlite3_pcache_methods] object. SQLite copies of the current
1412 ** page cache implementation into that object.)^ </dd>
1413 **
1414 ** <dt>SQLITE_CONFIG_LOG</dt>
1415 ** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
1416 ** function with a call signature of void(*)(void*,int,const char*),
1417 ** and a pointer to void. ^If the function pointer is not NULL, it is
1418 ** invoked by [sqlite3_log()] to process each logging event. ^If the
1419 ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
@@ -1427,10 +1436,22 @@
1427 ** The SQLite logging interface is not reentrant; the logger function
1428 ** supplied by the application must not invoke any SQLite interface.
1429 ** In a multi-threaded application, the application-defined logger
1430 ** function must be threadsafe. </dd>
1431 **
 
 
 
 
 
 
 
 
 
 
 
 
1432 ** </dl>
1433 */
1434 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1435 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1436 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1445,10 +1466,11 @@
1445 /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
1446 #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
1447 #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
1448 #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
1449 #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
 
1450
1451 /*
1452 ** CAPI3REF: Database Connection Configuration Options
1453 **
1454 ** These constants are the available integer configuration options that
@@ -1530,17 +1552,21 @@
1530 ** the table has a column of type [INTEGER PRIMARY KEY] then that column
1531 ** is another alias for the rowid.
1532 **
1533 ** ^This routine returns the [rowid] of the most recent
1534 ** successful [INSERT] into the database from the [database connection]
1535 ** in the first argument. ^If no successful [INSERT]s
 
 
1536 ** have ever occurred on that database connection, zero is returned.
1537 **
1538 ** ^(If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
1539 ** row is returned by this routine as long as the trigger is running.
1540 ** But once the trigger terminates, the value returned by this routine
1541 ** reverts to the last value inserted before the trigger fired.)^
 
 
1542 **
1543 ** ^An [INSERT] that fails due to a constraint violation is not a
1544 ** successful [INSERT] and does not change the value returned by this
1545 ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
1546 ** and INSERT OR ABORT make no changes to the return value of this
@@ -2199,10 +2225,13 @@
2199 ** The [sqlite3_set_authorizer | authorizer callback function] must
2200 ** return either [SQLITE_OK] or one of these two constants in order
2201 ** to signal SQLite whether or not the action is permitted. See the
2202 ** [sqlite3_set_authorizer | authorizer documentation] for additional
2203 ** information.
 
 
 
2204 */
2205 #define SQLITE_DENY 1 /* Abort the SQL statement with an error */
2206 #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
2207
2208 /*
@@ -2321,11 +2350,11 @@
2321 SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
2322
2323 /*
2324 ** CAPI3REF: Opening A New Database Connection
2325 **
2326 ** ^These routines open an SQLite database file whose name is given by the
2327 ** filename argument. ^The filename argument is interpreted as UTF-8 for
2328 ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
2329 ** order for sqlite3_open16(). ^(A [database connection] handle is usually
2330 ** returned in *ppDb, even if an error occurs. The only exception is that
2331 ** if SQLite is unable to allocate memory to hold the [sqlite3] object,
@@ -2348,11 +2377,11 @@
2348 ** except that it accepts two additional parameters for additional control
2349 ** over the new database connection. ^(The flags parameter to
2350 ** sqlite3_open_v2() can take one of
2351 ** the following three values, optionally combined with the
2352 ** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
2353 ** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
2354 **
2355 ** <dl>
2356 ** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
2357 ** <dd>The database is opened in read-only mode. If the database does not
2358 ** already exist, an error is returned.</dd>)^
@@ -2367,13 +2396,12 @@
2367 ** it does not already exist. This is the behavior that is always used for
2368 ** sqlite3_open() and sqlite3_open16().</dd>)^
2369 ** </dl>
2370 **
2371 ** If the 3rd parameter to sqlite3_open_v2() is not one of the
2372 ** combinations shown above or one of the combinations shown above combined
2373 ** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX],
2374 ** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags,
2375 ** then the behavior is undefined.
2376 **
2377 ** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
2378 ** opens in the multi-thread [threading mode] as long as the single-thread
2379 ** mode has not been set at compile-time or start-time. ^If the
@@ -2383,10 +2411,15 @@
2383 ** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
2384 ** eligible to use [shared cache mode], regardless of whether or not shared
2385 ** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
2386 ** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
2387 ** participate in [shared cache mode] even if it is enabled.
 
 
 
 
 
2388 **
2389 ** ^If the filename is ":memory:", then a private, temporary in-memory database
2390 ** is created for the connection. ^This in-memory database will vanish when
2391 ** the database connection is closed. Future versions of SQLite might
2392 ** make use of additional special filenames that begin with the ":" character.
@@ -2396,14 +2429,115 @@
2396 **
2397 ** ^If the filename is an empty string, then a private, temporary
2398 ** on-disk database will be created. ^This private database will be
2399 ** automatically deleted as soon as the database connection is closed.
2400 **
2401 ** ^The fourth parameter to sqlite3_open_v2() is the name of the
2402 ** [sqlite3_vfs] object that defines the operating system interface that
2403 ** the new database connection should use. ^If the fourth parameter is
2404 ** a NULL pointer then the default [sqlite3_vfs] object is used.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2405 **
2406 ** <b>Note to Windows users:</b> The encoding used for the filename argument
2407 ** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
2408 ** codepage is currently defined. Filenames containing international
2409 ** characters must be converted to UTF-8 prior to passing them into
@@ -2421,10 +2555,30 @@
2421 const char *filename, /* Database filename (UTF-8) */
2422 sqlite3 **ppDb, /* OUT: SQLite db handle */
2423 int flags, /* Flags */
2424 const char *zVfs /* Name of VFS module to use */
2425 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2426
2427 /*
2428 ** CAPI3REF: Error Codes And Messages
2429 **
2430 ** ^The sqlite3_errcode() interface returns the numeric [result code] or
@@ -2537,47 +2691,49 @@
2537 ** that can be lowered at run-time using [sqlite3_limit()].
2538 ** The synopsis of the meanings of the various limits is shown below.
2539 ** Additional information is available at [limits | Limits in SQLite].
2540 **
2541 ** <dl>
2542 ** ^(<dt>SQLITE_LIMIT_LENGTH</dt>
2543 ** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
2544 **
2545 ** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
2546 ** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
2547 **
2548 ** ^(<dt>SQLITE_LIMIT_COLUMN</dt>
2549 ** <dd>The maximum number of columns in a table definition or in the
2550 ** result set of a [SELECT] or the maximum number of columns in an index
2551 ** or in an ORDER BY or GROUP BY clause.</dd>)^
2552 **
2553 ** ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
2554 ** <dd>The maximum depth of the parse tree on any expression.</dd>)^
2555 **
2556 ** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
2557 ** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
2558 **
2559 ** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
2560 ** <dd>The maximum number of instructions in a virtual machine program
2561 ** used to implement an SQL statement. This limit is not currently
2562 ** enforced, though that might be added in some future release of
2563 ** SQLite.</dd>)^
2564 **
2565 ** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
2566 ** <dd>The maximum number of arguments on a function.</dd>)^
2567 **
2568 ** ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
2569 ** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
2570 **
 
2571 ** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
2572 ** <dd>The maximum length of the pattern argument to the [LIKE] or
2573 ** [GLOB] operators.</dd>)^
2574 **
 
2575 ** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
2576 ** <dd>The maximum index number of any [parameter] in an SQL statement.)^
2577 **
2578 ** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
2579 ** <dd>The maximum depth of recursion for triggers.</dd>)^
2580 ** </dl>
2581 */
2582 #define SQLITE_LIMIT_LENGTH 0
2583 #define SQLITE_LIMIT_SQL_LENGTH 1
@@ -4608,10 +4764,15 @@
4608 int (*xRollback)(sqlite3_vtab *pVTab);
4609 int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
4610 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
4611 void **ppArg);
4612 int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
 
 
 
 
 
4613 };
4614
4615 /*
4616 ** CAPI3REF: Virtual Table Indexing Information
4617 ** KEYWORDS: sqlite3_index_info
@@ -5422,11 +5583,11 @@
5422 **
5423 ** ^This interface is used to retrieve runtime status information
5424 ** about the performance of SQLite, and optionally to reset various
5425 ** highwater marks. ^The first argument is an integer code for
5426 ** the specific parameter to measure. ^(Recognized integer codes
5427 ** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
5428 ** ^The current value of the parameter is returned into *pCurrent.
5429 ** ^The highest recorded value is returned in *pHighwater. ^If the
5430 ** resetFlag is true, then the highest record value is reset after
5431 ** *pHighwater is written. ^(Some parameters do not record the highest
5432 ** value. For those parameters
@@ -5449,82 +5610,84 @@
5449 SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
5450
5451
5452 /*
5453 ** CAPI3REF: Status Parameters
 
5454 **
5455 ** These integer constants designate various run-time status parameters
5456 ** that can be returned by [sqlite3_status()].
5457 **
5458 ** <dl>
5459 ** ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
5460 ** <dd>This parameter is the current amount of memory checked out
5461 ** using [sqlite3_malloc()], either directly or indirectly. The
5462 ** figure includes calls made to [sqlite3_malloc()] by the application
5463 ** and internal memory usage by the SQLite library. Scratch memory
5464 ** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
5465 ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
5466 ** this parameter. The amount returned is the sum of the allocation
5467 ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
5468 **
5469 ** ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
5470 ** <dd>This parameter records the largest memory allocation request
5471 ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
5472 ** internal equivalents). Only the value returned in the
5473 ** *pHighwater parameter to [sqlite3_status()] is of interest.
5474 ** The value written into the *pCurrent parameter is undefined.</dd>)^
5475 **
5476 ** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
5477 ** <dd>This parameter records the number of separate memory allocations
5478 ** currently checked out.</dd>)^
5479 **
5480 ** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
5481 ** <dd>This parameter returns the number of pages used out of the
5482 ** [pagecache memory allocator] that was configured using
5483 ** [SQLITE_CONFIG_PAGECACHE]. The
5484 ** value returned is in pages, not in bytes.</dd>)^
5485 **
 
5486 ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
5487 ** <dd>This parameter returns the number of bytes of page cache
5488 ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
5489 ** buffer and where forced to overflow to [sqlite3_malloc()]. The
5490 ** returned value includes allocations that overflowed because they
5491 ** where too large (they were larger than the "sz" parameter to
5492 ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
5493 ** no space was left in the page cache.</dd>)^
5494 **
5495 ** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
5496 ** <dd>This parameter records the largest memory allocation request
5497 ** handed to [pagecache memory allocator]. Only the value returned in the
5498 ** *pHighwater parameter to [sqlite3_status()] is of interest.
5499 ** The value written into the *pCurrent parameter is undefined.</dd>)^
5500 **
5501 ** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
5502 ** <dd>This parameter returns the number of allocations used out of the
5503 ** [scratch memory allocator] configured using
5504 ** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
5505 ** in bytes. Since a single thread may only have one scratch allocation
5506 ** outstanding at time, this parameter also reports the number of threads
5507 ** using scratch memory at the same time.</dd>)^
5508 **
5509 ** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
5510 ** <dd>This parameter returns the number of bytes of scratch memory
5511 ** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
5512 ** buffer and where forced to overflow to [sqlite3_malloc()]. The values
5513 ** returned include overflows because the requested allocation was too
5514 ** larger (that is, because the requested allocation was larger than the
5515 ** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
5516 ** slots were available.
5517 ** </dd>)^
5518 **
5519 ** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
5520 ** <dd>This parameter records the largest memory allocation request
5521 ** handed to [scratch memory allocator]. Only the value returned in the
5522 ** *pHighwater parameter to [sqlite3_status()] is of interest.
5523 ** The value written into the *pCurrent parameter is undefined.</dd>)^
5524 **
5525 ** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
5526 ** <dd>This parameter records the deepest parser stack. It is only
5527 ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
5528 ** </dl>
5529 **
5530 ** New status parameters may be added from time to time.
@@ -5545,13 +5708,13 @@
5545 **
5546 ** ^This interface is used to retrieve runtime status information
5547 ** about a single [database connection]. ^The first argument is the
5548 ** database connection object to be interrogated. ^The second argument
5549 ** is an integer constant, taken from the set of
5550 ** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
5551 ** determines the parameter to interrogate. The set of
5552 ** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
5553 ** to grow in future releases of SQLite.
5554 **
5555 ** ^The current value of the requested parameter is written into *pCur
5556 ** and the highest instantaneous value is written into *pHiwtr. ^If
5557 ** the resetFlg is true, then the highest instantaneous value is
@@ -5564,10 +5727,11 @@
5564 */
5565 SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
5566
5567 /*
5568 ** CAPI3REF: Status Parameters for database connections
 
5569 **
5570 ** These constants are the available integer "verbs" that can be passed as
5571 ** the second argument to the [sqlite3_db_status()] interface.
5572 **
5573 ** New verbs may be added in future releases of SQLite. Existing verbs
@@ -5575,48 +5739,50 @@
5575 ** [sqlite3_db_status()] to make sure that the call worked.
5576 ** The [sqlite3_db_status()] interface will return a non-zero error code
5577 ** if a discontinued or unsupported verb is invoked.
5578 **
5579 ** <dl>
5580 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
5581 ** <dd>This parameter returns the number of lookaside memory slots currently
5582 ** checked out.</dd>)^
5583 **
5584 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
5585 ** <dd>This parameter returns the number malloc attempts that were
5586 ** satisfied using lookaside memory. Only the high-water value is meaningful;
5587 ** the current value is always zero.)^
5588 **
 
5589 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
5590 ** <dd>This parameter returns the number malloc attempts that might have
5591 ** been satisfied using lookaside memory but failed due to the amount of
5592 ** memory requested being larger than the lookaside slot size.
5593 ** Only the high-water value is meaningful;
5594 ** the current value is always zero.)^
5595 **
 
5596 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
5597 ** <dd>This parameter returns the number malloc attempts that might have
5598 ** been satisfied using lookaside memory but failed due to all lookaside
5599 ** memory already being in use.
5600 ** Only the high-water value is meaningful;
5601 ** the current value is always zero.)^
5602 **
5603 ** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
5604 ** <dd>This parameter returns the approximate number of of bytes of heap
5605 ** memory used by all pager caches associated with the database connection.)^
5606 ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
5607 **
5608 ** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
5609 ** <dd>This parameter returns the approximate number of of bytes of heap
5610 ** memory used to store the schema for all databases associated
5611 ** with the connection - main, temp, and any [ATTACH]-ed databases.)^
5612 ** ^The full amount of memory used by the schemas is reported, even if the
5613 ** schema memory is shared with other database connections due to
5614 ** [shared cache mode] being enabled.
5615 ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
5616 **
5617 ** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
5618 ** <dd>This parameter returns the approximate number of of bytes of heap
5619 ** and lookaside memory used by all prepared statements associated with
5620 ** the database connection.)^
5621 ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
5622 ** </dd>
@@ -5634,11 +5800,11 @@
5634
5635 /*
5636 ** CAPI3REF: Prepared Statement Status
5637 **
5638 ** ^(Each prepared statement maintains various
5639 ** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
5640 ** of times it has performed specific operations.)^ These counters can
5641 ** be used to monitor the performance characteristics of the prepared
5642 ** statements. For example, if the number of table steps greatly exceeds
5643 ** the number of table searches or result rows, that would tend to indicate
5644 ** that the prepared statement is using a full table scan rather than
@@ -5645,11 +5811,11 @@
5645 ** an index.
5646 **
5647 ** ^(This interface is used to retrieve and reset counter values from
5648 ** a [prepared statement]. The first argument is the prepared statement
5649 ** object to be interrogated. The second argument
5650 ** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
5651 ** to be interrogated.)^
5652 ** ^The current value of the requested counter is returned.
5653 ** ^If the resetFlg is true, then the counter is reset to zero after this
5654 ** interface call returns.
5655 **
@@ -5657,28 +5823,29 @@
5657 */
5658 SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
5659
5660 /*
5661 ** CAPI3REF: Status Parameters for prepared statements
 
5662 **
5663 ** These preprocessor macros define integer codes that name counter
5664 ** values associated with the [sqlite3_stmt_status()] interface.
5665 ** The meanings of the various counters are as follows:
5666 **
5667 ** <dl>
5668 ** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
5669 ** <dd>^This is the number of times that SQLite has stepped forward in
5670 ** a table as part of a full table scan. Large numbers for this counter
5671 ** may indicate opportunities for performance improvement through
5672 ** careful use of indices.</dd>
5673 **
5674 ** <dt>SQLITE_STMTSTATUS_SORT</dt>
5675 ** <dd>^This is the number of sort operations that have occurred.
5676 ** A non-zero value in this counter may indicate an opportunity to
5677 ** improvement performance through careful use of indices.</dd>
5678 **
5679 ** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
5680 ** <dd>^This is the number of rows inserted into transient indices that
5681 ** were created automatically in order to help joins run faster.
5682 ** A non-zero value in this counter may indicate an opportunity to
5683 ** improvement performance by adding permanent indices that do not
5684 ** need to be reinitialized each time the statement is run.</dd>
@@ -5725,10 +5892,11 @@
5725 ** ^(The contents of the sqlite3_pcache_methods structure are copied to an
5726 ** internal buffer by SQLite within the call to [sqlite3_config]. Hence
5727 ** the application may discard the parameter after the call to
5728 ** [sqlite3_config()] returns.)^
5729 **
 
5730 ** ^(The xInit() method is called once for each effective
5731 ** call to [sqlite3_initialize()])^
5732 ** (usually only once during the lifetime of the process). ^(The xInit()
5733 ** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^
5734 ** The intent of the xInit() method is to set up global data structures
@@ -5735,10 +5903,11 @@
5735 ** required by the custom page cache implementation.
5736 ** ^(If the xInit() method is NULL, then the
5737 ** built-in default page cache is used instead of the application defined
5738 ** page cache.)^
5739 **
 
5740 ** ^The xShutdown() method is called by [sqlite3_shutdown()].
5741 ** It can be used to clean up
5742 ** any outstanding resources before process shutdown, if required.
5743 ** ^The xShutdown() method may be NULL.
5744 **
@@ -5749,10 +5918,11 @@
5749 ** in multithreaded applications.
5750 **
5751 ** ^SQLite will never invoke xInit() more than once without an intervening
5752 ** call to xShutdown().
5753 **
 
5754 ** ^SQLite invokes the xCreate() method to construct a new cache instance.
5755 ** SQLite will typically create one cache instance for each open database file,
5756 ** though this is not guaranteed. ^The
5757 ** first parameter, szPage, is the size in bytes of the pages that must
5758 ** be allocated by the cache. ^szPage will not be a power of two. ^szPage
@@ -5773,20 +5943,23 @@
5773 ** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
5774 ** false will always have the "discard" flag set to true.
5775 ** ^Hence, a cache created with bPurgeable false will
5776 ** never contain any unpinned pages.
5777 **
 
5778 ** ^(The xCachesize() method may be called at any time by SQLite to set the
5779 ** suggested maximum cache-size (number of pages stored by) the cache
5780 ** instance passed as the first argument. This is the value configured using
5781 ** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
5782 ** parameter, the implementation is not required to do anything with this
5783 ** value; it is advisory only.
5784 **
 
5785 ** The xPagecount() method must return the number of pages currently
5786 ** stored in the cache, both pinned and unpinned.
5787 **
 
5788 ** The xFetch() method locates a page in the cache and returns a pointer to
5789 ** the page, or a NULL pointer.
5790 ** A "page", in this context, means a buffer of szPage bytes aligned at an
5791 ** 8-byte boundary. The page to be fetched is determined by the key. ^The
5792 ** mimimum key value is 1. After it has been retrieved using xFetch, the page
@@ -5811,10 +5984,11 @@
5811 ** will only use a createFlag of 2 after a prior call with a createFlag of 1
5812 ** failed.)^ In between the to xFetch() calls, SQLite may
5813 ** attempt to unpin one or more cache pages by spilling the content of
5814 ** pinned pages to disk and synching the operating system disk cache.
5815 **
 
5816 ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
5817 ** as its second argument. If the third parameter, discard, is non-zero,
5818 ** then the page must be evicted from the cache.
5819 ** ^If the discard parameter is
5820 ** zero, then the page may be discarded or retained at the discretion of
@@ -5823,10 +5997,11 @@
5823 **
5824 ** The cache must not perform any reference counting. A single
5825 ** call to xUnpin() unpins the page regardless of the number of prior calls
5826 ** to xFetch().
5827 **
 
5828 ** The xRekey() method is used to change the key value associated with the
5829 ** page passed as the second argument. If the cache
5830 ** previously contains an entry associated with newKey, it must be
5831 ** discarded. ^Any prior cache entry associated with newKey is guaranteed not
5832 ** to be pinned.
@@ -5835,10 +6010,11 @@
5835 ** existing cache entries with page numbers (keys) greater than or equal
5836 ** to the value of the iLimit parameter passed to xTruncate(). If any
5837 ** of these pages are pinned, they are implicitly unpinned, meaning that
5838 ** they can be safely discarded.
5839 **
 
5840 ** ^The xDestroy() method is used to delete a cache allocated by xCreate().
5841 ** All resources associated with the specified cache should be freed. ^After
5842 ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
5843 ** handle invalid, and will not use it with any other sqlite3_pcache_methods
5844 ** functions.
@@ -5897,11 +6073,11 @@
5897 ** associated with the backup operation.
5898 ** </ol>)^
5899 ** There should be exactly one call to sqlite3_backup_finish() for each
5900 ** successful call to sqlite3_backup_init().
5901 **
5902 ** <b>sqlite3_backup_init()</b>
5903 **
5904 ** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
5905 ** [database connection] associated with the destination database
5906 ** and the database name, respectively.
5907 ** ^The database name is "main" for the main database, "temp" for the
@@ -5924,11 +6100,11 @@
5924 ** [sqlite3_backup] object.
5925 ** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
5926 ** sqlite3_backup_finish() functions to perform the specified backup
5927 ** operation.
5928 **
5929 ** <b>sqlite3_backup_step()</b>
5930 **
5931 ** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
5932 ** the source and destination databases specified by [sqlite3_backup] object B.
5933 ** ^If N is negative, all remaining source pages are copied.
5934 ** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
@@ -5981,11 +6157,11 @@
5981 ** restarted by the next call to sqlite3_backup_step(). ^If the source
5982 ** database is modified by the using the same database connection as is used
5983 ** by the backup operation, then the backup database is automatically
5984 ** updated at the same time.
5985 **
5986 ** <b>sqlite3_backup_finish()</b>
5987 **
5988 ** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
5989 ** application wishes to abandon the backup operation, the application
5990 ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
5991 ** ^The sqlite3_backup_finish() interfaces releases all
@@ -6004,11 +6180,12 @@
6004 **
6005 ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
6006 ** is not a permanent error and does not affect the return value of
6007 ** sqlite3_backup_finish().
6008 **
6009 ** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b>
 
6010 **
6011 ** ^Each call to sqlite3_backup_step() sets two values inside
6012 ** the [sqlite3_backup] object: the number of pages still to be backed
6013 ** up and the total number of pages in the source database file.
6014 ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
@@ -6389,10 +6566,97 @@
6389 ** each of these values.
6390 */
6391 #define SQLITE_CHECKPOINT_PASSIVE 0
6392 #define SQLITE_CHECKPOINT_FULL 1
6393 #define SQLITE_CHECKPOINT_RESTART 2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6394
6395
6396 /*
6397 ** Undo the hack that converts floating point types to integer for
6398 ** builds on processors without floating point support.
6399
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.7.7"
111 #define SQLITE_VERSION_NUMBER 3007007
112 #define SQLITE_SOURCE_ID "2011-05-20 01:50:01 2018d4e108872f2436df046636401b89cfde589d"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -373,11 +373,12 @@
373 ** Many SQLite functions return an integer result code from the set shown
374 ** here in order to indicates success or failure.
375 **
376 ** New error codes may be added in future versions of SQLite.
377 **
378 ** See also: [SQLITE_IOERR_READ | extended result codes],
379 ** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
380 */
381 #define SQLITE_OK 0 /* Successful result */
382 /* beginning-of-error-codes */
383 #define SQLITE_ERROR 1 /* SQL error or missing database */
384 #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
@@ -450,28 +451,31 @@
451 #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
452 #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
453 #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
454 #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
455 #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
456 #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
457 #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
458 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
459 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
460 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
461 #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
462
463 /*
464 ** CAPI3REF: Flags For File Open Operations
465 **
466 ** These bit values are intended for use in the
467 ** 3rd parameter to the [sqlite3_open_v2()] interface and
468 ** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
 
469 */
470 #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
471 #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
472 #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
473 #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
474 #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
475 #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
476 #define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
477 #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
478 #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
479 #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
480 #define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
481 #define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
@@ -578,21 +582,22 @@
582 };
583
584 /*
585 ** CAPI3REF: OS Interface File Virtual Methods Object
586 **
587 ** Every file opened by the [sqlite3_vfs.xOpen] method populates an
588 ** [sqlite3_file] object (or, more commonly, a subclass of the
589 ** [sqlite3_file] object) with a pointer to an instance of this object.
590 ** This object defines the methods used to perform various operations
591 ** against the open file represented by the [sqlite3_file] object.
592 **
593 ** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
594 ** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
595 ** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
596 ** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
597 ** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
598 ** to NULL.
599 **
600 ** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
601 ** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
602 ** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
603 ** flag may be ORed in to indicate that only the data of the file
@@ -757,10 +762,11 @@
762 */
763 typedef struct sqlite3_mutex sqlite3_mutex;
764
765 /*
766 ** CAPI3REF: OS Interface Object
767 ** KEYWORDS: VFS VFSes
768 **
769 ** An instance of the sqlite3_vfs object defines the interface between
770 ** the SQLite core and the underlying operating system. The "vfs"
771 ** in the name of the object stands for "virtual file system".
772 **
@@ -789,10 +795,11 @@
795 ** object once the object has been registered.
796 **
797 ** The zName field holds the name of the VFS module. The name must
798 ** be unique across all VFS modules.
799 **
800 ** [[sqlite3_vfs.xOpen]]
801 ** ^SQLite guarantees that the zFilename parameter to xOpen
802 ** is either a NULL pointer or string obtained
803 ** from xFullPathname() with an optional suffix added.
804 ** ^If a suffix is added to the zFilename parameter, it will
805 ** consist of a single "-" character followed by no more than
@@ -866,10 +873,11 @@
873 ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
874 ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
875 ** element will be valid after xOpen returns regardless of the success
876 ** or failure of the xOpen call.
877 **
878 ** [[sqlite3_vfs.xAccess]]
879 ** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
880 ** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
881 ** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
882 ** to test whether a file is at least readable. The file can be a
883 ** directory.
@@ -1112,13 +1120,13 @@
1120 ** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
1121 ** Note, however, that ^sqlite3_config() can be called as part of the
1122 ** implementation of an application-defined [sqlite3_os_init()].
1123 **
1124 ** The first argument to sqlite3_config() is an integer
1125 ** [configuration option] that determines
1126 ** what property of SQLite is to be configured. Subsequent arguments
1127 ** vary depending on the [configuration option]
1128 ** in the first argument.
1129 **
1130 ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
1131 ** ^If the option is unknown or SQLite is unable to set the option
1132 ** then this routine returns a non-zero [error code].
@@ -1224,10 +1232,11 @@
1232 void *pAppData; /* Argument to xInit() and xShutdown() */
1233 };
1234
1235 /*
1236 ** CAPI3REF: Configuration Options
1237 ** KEYWORDS: {configuration option}
1238 **
1239 ** These constants are the available integer configuration options that
1240 ** can be passed as the first argument to the [sqlite3_config()] interface.
1241 **
1242 ** New configuration options may be added in future releases of SQLite.
@@ -1236,11 +1245,11 @@
1245 ** the call worked. The [sqlite3_config()] interface will return a
1246 ** non-zero [error code] if a discontinued or unsupported configuration option
1247 ** is invoked.
1248 **
1249 ** <dl>
1250 ** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
1251 ** <dd>There are no arguments to this option. ^This option sets the
1252 ** [threading mode] to Single-thread. In other words, it disables
1253 ** all mutexing and puts SQLite into a mode where it can only be used
1254 ** by a single thread. ^If SQLite is compiled with
1255 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
@@ -1247,11 +1256,11 @@
1256 ** it is not possible to change the [threading mode] from its default
1257 ** value of Single-thread and so [sqlite3_config()] will return
1258 ** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
1259 ** configuration option.</dd>
1260 **
1261 ** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
1262 ** <dd>There are no arguments to this option. ^This option sets the
1263 ** [threading mode] to Multi-thread. In other words, it disables
1264 ** mutexing on [database connection] and [prepared statement] objects.
1265 ** The application is responsible for serializing access to
1266 ** [database connections] and [prepared statements]. But other mutexes
@@ -1261,11 +1270,11 @@
1270 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1271 ** it is not possible to set the Multi-thread [threading mode] and
1272 ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
1273 ** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
1274 **
1275 ** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
1276 ** <dd>There are no arguments to this option. ^This option sets the
1277 ** [threading mode] to Serialized. In other words, this option enables
1278 ** all mutexes including the recursive
1279 ** mutexes on [database connection] and [prepared statement] objects.
1280 ** In this mode (which is the default when SQLite is compiled with
@@ -1277,27 +1286,27 @@
1286 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1287 ** it is not possible to set the Serialized [threading mode] and
1288 ** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
1289 ** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
1290 **
1291 ** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
1292 ** <dd> ^(This option takes a single argument which is a pointer to an
1293 ** instance of the [sqlite3_mem_methods] structure. The argument specifies
1294 ** alternative low-level memory allocation routines to be used in place of
1295 ** the memory allocation routines built into SQLite.)^ ^SQLite makes
1296 ** its own private copy of the content of the [sqlite3_mem_methods] structure
1297 ** before the [sqlite3_config()] call returns.</dd>
1298 **
1299 ** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
1300 ** <dd> ^(This option takes a single argument which is a pointer to an
1301 ** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
1302 ** structure is filled with the currently defined memory allocation routines.)^
1303 ** This option can be used to overload the default memory allocation
1304 ** routines with a wrapper that simulations memory allocation failure or
1305 ** tracks memory usage, for example. </dd>
1306 **
1307 ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
1308 ** <dd> ^This option takes single argument of type int, interpreted as a
1309 ** boolean, which enables or disables the collection of memory allocation
1310 ** statistics. ^(When memory allocation statistics are disabled, the
1311 ** following SQLite interfaces become non-operational:
1312 ** <ul>
@@ -1309,11 +1318,11 @@
1318 ** ^Memory allocation statistics are enabled by default unless SQLite is
1319 ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
1320 ** allocation statistics are disabled by default.
1321 ** </dd>
1322 **
1323 ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
1324 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1325 ** scratch memory. There are three arguments: A pointer an 8-byte
1326 ** aligned memory buffer from which the scratch allocations will be
1327 ** drawn, the size of each scratch allocation (sz),
1328 ** and the maximum number of scratch allocations (N). The sz
@@ -1325,11 +1334,11 @@
1334 ** ^SQLite will never require a scratch buffer that is more than 6
1335 ** times the database page size. ^If SQLite needs needs additional
1336 ** scratch memory beyond what is provided by this configuration option, then
1337 ** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
1338 **
1339 ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
1340 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
1341 ** the database page cache with the default page cache implemenation.
1342 ** This configuration should not be used if an application-define page
1343 ** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
1344 ** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1346,11 +1355,11 @@
1355 ** SQLite goes to [sqlite3_malloc()] for the additional storage space.
1356 ** The pointer in the first argument must
1357 ** be aligned to an 8-byte boundary or subsequent behavior of SQLite
1358 ** will be undefined.</dd>
1359 **
1360 ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
1361 ** <dd> ^This option specifies a static memory buffer that SQLite will use
1362 ** for all of its dynamic memory allocation needs beyond those provided
1363 ** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
1364 ** There are three arguments: An 8-byte aligned pointer to the memory,
1365 ** the number of bytes in the memory buffer, and the minimum allocation size.
@@ -1363,11 +1372,11 @@
1372 ** The first pointer (the memory pointer) must be aligned to an 8-byte
1373 ** boundary or subsequent behavior of SQLite will be undefined.
1374 ** The minimum allocation size is capped at 2^12. Reasonable values
1375 ** for the minimum allocation size are 2^5 through 2^8.</dd>
1376 **
1377 ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
1378 ** <dd> ^(This option takes a single argument which is a pointer to an
1379 ** instance of the [sqlite3_mutex_methods] structure. The argument specifies
1380 ** alternative low-level mutex routines to be used in place
1381 ** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
1382 ** content of the [sqlite3_mutex_methods] structure before the call to
@@ -1375,11 +1384,11 @@
1384 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1385 ** the entire mutexing subsystem is omitted from the build and hence calls to
1386 ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
1387 ** return [SQLITE_ERROR].</dd>
1388 **
1389 ** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
1390 ** <dd> ^(This option takes a single argument which is a pointer to an
1391 ** instance of the [sqlite3_mutex_methods] structure. The
1392 ** [sqlite3_mutex_methods]
1393 ** structure is filled with the currently defined mutex routines.)^
1394 ** This option can be used to overload the default mutex allocation
@@ -1388,32 +1397,32 @@
1397 ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
1398 ** the entire mutexing subsystem is omitted from the build and hence calls to
1399 ** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
1400 ** return [SQLITE_ERROR].</dd>
1401 **
1402 ** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
1403 ** <dd> ^(This option takes two arguments that determine the default
1404 ** memory allocation for the lookaside memory allocator on each
1405 ** [database connection]. The first argument is the
1406 ** size of each lookaside buffer slot and the second is the number of
1407 ** slots allocated to each database connection.)^ ^(This option sets the
1408 ** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
1409 ** verb to [sqlite3_db_config()] can be used to change the lookaside
1410 ** configuration on individual connections.)^ </dd>
1411 **
1412 ** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
1413 ** <dd> ^(This option takes a single argument which is a pointer to
1414 ** an [sqlite3_pcache_methods] object. This object specifies the interface
1415 ** to a custom page cache implementation.)^ ^SQLite makes a copy of the
1416 ** object and uses it for page cache memory allocations.</dd>
1417 **
1418 ** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
1419 ** <dd> ^(This option takes a single argument which is a pointer to an
1420 ** [sqlite3_pcache_methods] object. SQLite copies of the current
1421 ** page cache implementation into that object.)^ </dd>
1422 **
1423 ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
1424 ** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
1425 ** function with a call signature of void(*)(void*,int,const char*),
1426 ** and a pointer to void. ^If the function pointer is not NULL, it is
1427 ** invoked by [sqlite3_log()] to process each logging event. ^If the
1428 ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
@@ -1427,10 +1436,22 @@
1436 ** The SQLite logging interface is not reentrant; the logger function
1437 ** supplied by the application must not invoke any SQLite interface.
1438 ** In a multi-threaded application, the application-defined logger
1439 ** function must be threadsafe. </dd>
1440 **
1441 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
1442 ** <dd> This option takes a single argument of type int. If non-zero, then
1443 ** URI handling is globally enabled. If the parameter is zero, then URI handling
1444 ** is globally disabled. If URI handling is globally enabled, all filenames
1445 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
1446 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
1447 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
1448 ** connection is opened. If it is globally disabled, filenames are
1449 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
1450 ** database connection is opened. By default, URI handling is globally
1451 ** disabled. The default value may be changed by compiling with the
1452 ** [SQLITE_USE_URI] symbol defined.
1453 ** </dl>
1454 */
1455 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1456 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1457 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1445,10 +1466,11 @@
1466 /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
1467 #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
1468 #define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
1469 #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
1470 #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
1471 #define SQLITE_CONFIG_URI 17 /* int */
1472
1473 /*
1474 ** CAPI3REF: Database Connection Configuration Options
1475 **
1476 ** These constants are the available integer configuration options that
@@ -1530,17 +1552,21 @@
1552 ** the table has a column of type [INTEGER PRIMARY KEY] then that column
1553 ** is another alias for the rowid.
1554 **
1555 ** ^This routine returns the [rowid] of the most recent
1556 ** successful [INSERT] into the database from the [database connection]
1557 ** in the first argument. ^As of SQLite version 3.7.7, this routines
1558 ** records the last insert rowid of both ordinary tables and [virtual tables].
1559 ** ^If no successful [INSERT]s
1560 ** have ever occurred on that database connection, zero is returned.
1561 **
1562 ** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
1563 ** method, then this routine will return the [rowid] of the inserted
1564 ** row as long as the trigger or virtual table method is running.
1565 ** But once the trigger or virtual table method ends, the value returned
1566 ** by this routine reverts to what it was before the trigger or virtual
1567 ** table method began.)^
1568 **
1569 ** ^An [INSERT] that fails due to a constraint violation is not a
1570 ** successful [INSERT] and does not change the value returned by this
1571 ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
1572 ** and INSERT OR ABORT make no changes to the return value of this
@@ -2199,10 +2225,13 @@
2225 ** The [sqlite3_set_authorizer | authorizer callback function] must
2226 ** return either [SQLITE_OK] or one of these two constants in order
2227 ** to signal SQLite whether or not the action is permitted. See the
2228 ** [sqlite3_set_authorizer | authorizer documentation] for additional
2229 ** information.
2230 **
2231 ** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
2232 ** from the [sqlite3_vtab_on_conflict()] interface.
2233 */
2234 #define SQLITE_DENY 1 /* Abort the SQL statement with an error */
2235 #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
2236
2237 /*
@@ -2321,11 +2350,11 @@
2350 SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
2351
2352 /*
2353 ** CAPI3REF: Opening A New Database Connection
2354 **
2355 ** ^These routines open an SQLite database file as specified by the
2356 ** filename argument. ^The filename argument is interpreted as UTF-8 for
2357 ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
2358 ** order for sqlite3_open16(). ^(A [database connection] handle is usually
2359 ** returned in *ppDb, even if an error occurs. The only exception is that
2360 ** if SQLite is unable to allocate memory to hold the [sqlite3] object,
@@ -2348,11 +2377,11 @@
2377 ** except that it accepts two additional parameters for additional control
2378 ** over the new database connection. ^(The flags parameter to
2379 ** sqlite3_open_v2() can take one of
2380 ** the following three values, optionally combined with the
2381 ** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
2382 ** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
2383 **
2384 ** <dl>
2385 ** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
2386 ** <dd>The database is opened in read-only mode. If the database does not
2387 ** already exist, an error is returned.</dd>)^
@@ -2367,13 +2396,12 @@
2396 ** it does not already exist. This is the behavior that is always used for
2397 ** sqlite3_open() and sqlite3_open16().</dd>)^
2398 ** </dl>
2399 **
2400 ** If the 3rd parameter to sqlite3_open_v2() is not one of the
2401 ** combinations shown above optionally combined with other
2402 ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
 
2403 ** then the behavior is undefined.
2404 **
2405 ** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
2406 ** opens in the multi-thread [threading mode] as long as the single-thread
2407 ** mode has not been set at compile-time or start-time. ^If the
@@ -2383,10 +2411,15 @@
2411 ** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
2412 ** eligible to use [shared cache mode], regardless of whether or not shared
2413 ** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
2414 ** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
2415 ** participate in [shared cache mode] even if it is enabled.
2416 **
2417 ** ^The fourth parameter to sqlite3_open_v2() is the name of the
2418 ** [sqlite3_vfs] object that defines the operating system interface that
2419 ** the new database connection should use. ^If the fourth parameter is
2420 ** a NULL pointer then the default [sqlite3_vfs] object is used.
2421 **
2422 ** ^If the filename is ":memory:", then a private, temporary in-memory database
2423 ** is created for the connection. ^This in-memory database will vanish when
2424 ** the database connection is closed. Future versions of SQLite might
2425 ** make use of additional special filenames that begin with the ":" character.
@@ -2396,14 +2429,115 @@
2429 **
2430 ** ^If the filename is an empty string, then a private, temporary
2431 ** on-disk database will be created. ^This private database will be
2432 ** automatically deleted as soon as the database connection is closed.
2433 **
2434 ** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
2435 **
2436 ** ^If [URI filename] interpretation is enabled, and the filename argument
2437 ** begins with "file:", then the filename is interpreted as a URI. ^URI
2438 ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
2439 ** is set in the fourth argument to sqlite3_open_v2(), or if it has
2440 ** been enabled globally using the [SQLITE_CONFIG_URI] option with the
2441 ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
2442 ** As of SQLite version 3.7.7, URI filename interpretation is turned off
2443 ** by default, but future releases of SQLite might enable URI filename
2444 ** intepretation by default. See "[URI filenames]" for additional
2445 ** information.
2446 **
2447 ** URI filenames are parsed according to RFC 3986. ^If the URI contains an
2448 ** authority, then it must be either an empty string or the string
2449 ** "localhost". ^If the authority is not an empty string or "localhost", an
2450 ** error is returned to the caller. ^The fragment component of a URI, if
2451 ** present, is ignored.
2452 **
2453 ** ^SQLite uses the path component of the URI as the name of the disk file
2454 ** which contains the database. ^If the path begins with a '/' character,
2455 ** then it is interpreted as an absolute path. ^If the path does not begin
2456 ** with a '/' (meaning that the authority section is omitted from the URI)
2457 ** then the path is interpreted as a relative path.
2458 ** ^On windows, the first component of an absolute path
2459 ** is a drive specification (e.g. "C:").
2460 **
2461 ** [[core URI query parameters]]
2462 ** The query component of a URI may contain parameters that are interpreted
2463 ** either by SQLite itself, or by a [VFS | custom VFS implementation].
2464 ** SQLite interprets the following three query parameters:
2465 **
2466 ** <ul>
2467 ** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
2468 ** a VFS object that provides the operating system interface that should
2469 ** be used to access the database file on disk. ^If this option is set to
2470 ** an empty string the default VFS object is used. ^Specifying an unknown
2471 ** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
2472 ** present, then the VFS specified by the option takes precedence over
2473 ** the value passed as the fourth parameter to sqlite3_open_v2().
2474 **
2475 ** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
2476 ** "rwc". Attempting to set it to any other value is an error)^.
2477 ** ^If "ro" is specified, then the database is opened for read-only
2478 ** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
2479 ** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
2480 ** "rw", then the database is opened for read-write (but not create)
2481 ** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
2482 ** been set. ^Value "rwc" is equivalent to setting both
2483 ** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
2484 ** used, it is an error to specify a value for the mode parameter that is
2485 ** less restrictive than that specified by the flags passed as the third
2486 ** parameter.
2487 **
2488 ** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
2489 ** "private". ^Setting it to "shared" is equivalent to setting the
2490 ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
2491 ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
2492 ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
2493 ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
2494 ** a URI filename, its value overrides any behaviour requested by setting
2495 ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
2496 ** </ul>
2497 **
2498 ** ^Specifying an unknown parameter in the query component of a URI is not an
2499 ** error. Future versions of SQLite might understand additional query
2500 ** parameters. See "[query parameters with special meaning to SQLite]" for
2501 ** additional information.
2502 **
2503 ** [[URI filename examples]] <h3>URI filename examples</h3>
2504 **
2505 ** <table border="1" align=center cellpadding=5>
2506 ** <tr><th> URI filenames <th> Results
2507 ** <tr><td> file:data.db <td>
2508 ** Open the file "data.db" in the current directory.
2509 ** <tr><td> file:/home/fred/data.db<br>
2510 ** file:///home/fred/data.db <br>
2511 ** file://localhost/home/fred/data.db <br> <td>
2512 ** Open the database file "/home/fred/data.db".
2513 ** <tr><td> file://darkstar/home/fred/data.db <td>
2514 ** An error. "darkstar" is not a recognized authority.
2515 ** <tr><td style="white-space:nowrap">
2516 ** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
2517 ** <td> Windows only: Open the file "data.db" on fred's desktop on drive
2518 ** C:. Note that the %20 escaping in this example is not strictly
2519 ** necessary - space characters can be used literally
2520 ** in URI filenames.
2521 ** <tr><td> file:data.db?mode=ro&cache=private <td>
2522 ** Open file "data.db" in the current directory for read-only access.
2523 ** Regardless of whether or not shared-cache mode is enabled by
2524 ** default, use a private cache.
2525 ** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
2526 ** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
2527 ** <tr><td> file:data.db?mode=readonly <td>
2528 ** An error. "readonly" is not a valid option for the "mode" parameter.
2529 ** </table>
2530 **
2531 ** ^URI hexadecimal escape sequences (%HH) are supported within the path and
2532 ** query components of a URI. A hexadecimal escape sequence consists of a
2533 ** percent sign - "%" - followed by exactly two hexadecimal digits
2534 ** specifying an octet value. ^Before the path or query components of a
2535 ** URI filename are interpreted, they are encoded using UTF-8 and all
2536 ** hexadecimal escape sequences replaced by a single byte containing the
2537 ** corresponding octet. If this process generates an invalid UTF-8 encoding,
2538 ** the results are undefined.
2539 **
2540 ** <b>Note to Windows users:</b> The encoding used for the filename argument
2541 ** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
2542 ** codepage is currently defined. Filenames containing international
2543 ** characters must be converted to UTF-8 prior to passing them into
@@ -2421,10 +2555,30 @@
2555 const char *filename, /* Database filename (UTF-8) */
2556 sqlite3 **ppDb, /* OUT: SQLite db handle */
2557 int flags, /* Flags */
2558 const char *zVfs /* Name of VFS module to use */
2559 );
2560
2561 /*
2562 ** CAPI3REF: Obtain Values For URI Parameters
2563 **
2564 ** This is a utility routine, useful to VFS implementations, that checks
2565 ** to see if a database file was a URI that contained a specific query
2566 ** parameter, and if so obtains the value of the query parameter.
2567 **
2568 ** The zFilename argument is the filename pointer passed into the xOpen()
2569 ** method of a VFS implementation. The zParam argument is the name of the
2570 ** query parameter we seek. This routine returns the value of the zParam
2571 ** parameter if it exists. If the parameter does not exist, this routine
2572 ** returns a NULL pointer.
2573 **
2574 ** If the zFilename argument to this function is not a pointer that SQLite
2575 ** passed into the xOpen VFS method, then the behavior of this routine
2576 ** is undefined and probably undesirable.
2577 */
2578 SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
2579
2580
2581 /*
2582 ** CAPI3REF: Error Codes And Messages
2583 **
2584 ** ^The sqlite3_errcode() interface returns the numeric [result code] or
@@ -2537,47 +2691,49 @@
2691 ** that can be lowered at run-time using [sqlite3_limit()].
2692 ** The synopsis of the meanings of the various limits is shown below.
2693 ** Additional information is available at [limits | Limits in SQLite].
2694 **
2695 ** <dl>
2696 ** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
2697 ** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
2698 **
2699 ** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
2700 ** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
2701 **
2702 ** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
2703 ** <dd>The maximum number of columns in a table definition or in the
2704 ** result set of a [SELECT] or the maximum number of columns in an index
2705 ** or in an ORDER BY or GROUP BY clause.</dd>)^
2706 **
2707 ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
2708 ** <dd>The maximum depth of the parse tree on any expression.</dd>)^
2709 **
2710 ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
2711 ** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
2712 **
2713 ** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
2714 ** <dd>The maximum number of instructions in a virtual machine program
2715 ** used to implement an SQL statement. This limit is not currently
2716 ** enforced, though that might be added in some future release of
2717 ** SQLite.</dd>)^
2718 **
2719 ** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
2720 ** <dd>The maximum number of arguments on a function.</dd>)^
2721 **
2722 ** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
2723 ** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
2724 **
2725 ** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
2726 ** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
2727 ** <dd>The maximum length of the pattern argument to the [LIKE] or
2728 ** [GLOB] operators.</dd>)^
2729 **
2730 ** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
2731 ** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
2732 ** <dd>The maximum index number of any [parameter] in an SQL statement.)^
2733 **
2734 ** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
2735 ** <dd>The maximum depth of recursion for triggers.</dd>)^
2736 ** </dl>
2737 */
2738 #define SQLITE_LIMIT_LENGTH 0
2739 #define SQLITE_LIMIT_SQL_LENGTH 1
@@ -4608,10 +4764,15 @@
4764 int (*xRollback)(sqlite3_vtab *pVTab);
4765 int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
4766 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
4767 void **ppArg);
4768 int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
4769 /* The methods above are in version 1 of the sqlite_module object. Those
4770 ** below are for version 2 and greater. */
4771 int (*xSavepoint)(sqlite3_vtab *pVTab, int);
4772 int (*xRelease)(sqlite3_vtab *pVTab, int);
4773 int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
4774 };
4775
4776 /*
4777 ** CAPI3REF: Virtual Table Indexing Information
4778 ** KEYWORDS: sqlite3_index_info
@@ -5422,11 +5583,11 @@
5583 **
5584 ** ^This interface is used to retrieve runtime status information
5585 ** about the performance of SQLite, and optionally to reset various
5586 ** highwater marks. ^The first argument is an integer code for
5587 ** the specific parameter to measure. ^(Recognized integer codes
5588 ** are of the form [status parameters | SQLITE_STATUS_...].)^
5589 ** ^The current value of the parameter is returned into *pCurrent.
5590 ** ^The highest recorded value is returned in *pHighwater. ^If the
5591 ** resetFlag is true, then the highest record value is reset after
5592 ** *pHighwater is written. ^(Some parameters do not record the highest
5593 ** value. For those parameters
@@ -5449,82 +5610,84 @@
5610 SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
5611
5612
5613 /*
5614 ** CAPI3REF: Status Parameters
5615 ** KEYWORDS: {status parameters}
5616 **
5617 ** These integer constants designate various run-time status parameters
5618 ** that can be returned by [sqlite3_status()].
5619 **
5620 ** <dl>
5621 ** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
5622 ** <dd>This parameter is the current amount of memory checked out
5623 ** using [sqlite3_malloc()], either directly or indirectly. The
5624 ** figure includes calls made to [sqlite3_malloc()] by the application
5625 ** and internal memory usage by the SQLite library. Scratch memory
5626 ** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
5627 ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
5628 ** this parameter. The amount returned is the sum of the allocation
5629 ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
5630 **
5631 ** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
5632 ** <dd>This parameter records the largest memory allocation request
5633 ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
5634 ** internal equivalents). Only the value returned in the
5635 ** *pHighwater parameter to [sqlite3_status()] is of interest.
5636 ** The value written into the *pCurrent parameter is undefined.</dd>)^
5637 **
5638 ** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
5639 ** <dd>This parameter records the number of separate memory allocations
5640 ** currently checked out.</dd>)^
5641 **
5642 ** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
5643 ** <dd>This parameter returns the number of pages used out of the
5644 ** [pagecache memory allocator] that was configured using
5645 ** [SQLITE_CONFIG_PAGECACHE]. The
5646 ** value returned is in pages, not in bytes.</dd>)^
5647 **
5648 ** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
5649 ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
5650 ** <dd>This parameter returns the number of bytes of page cache
5651 ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
5652 ** buffer and where forced to overflow to [sqlite3_malloc()]. The
5653 ** returned value includes allocations that overflowed because they
5654 ** where too large (they were larger than the "sz" parameter to
5655 ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
5656 ** no space was left in the page cache.</dd>)^
5657 **
5658 ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
5659 ** <dd>This parameter records the largest memory allocation request
5660 ** handed to [pagecache memory allocator]. Only the value returned in the
5661 ** *pHighwater parameter to [sqlite3_status()] is of interest.
5662 ** The value written into the *pCurrent parameter is undefined.</dd>)^
5663 **
5664 ** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
5665 ** <dd>This parameter returns the number of allocations used out of the
5666 ** [scratch memory allocator] configured using
5667 ** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
5668 ** in bytes. Since a single thread may only have one scratch allocation
5669 ** outstanding at time, this parameter also reports the number of threads
5670 ** using scratch memory at the same time.</dd>)^
5671 **
5672 ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
5673 ** <dd>This parameter returns the number of bytes of scratch memory
5674 ** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
5675 ** buffer and where forced to overflow to [sqlite3_malloc()]. The values
5676 ** returned include overflows because the requested allocation was too
5677 ** larger (that is, because the requested allocation was larger than the
5678 ** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
5679 ** slots were available.
5680 ** </dd>)^
5681 **
5682 ** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
5683 ** <dd>This parameter records the largest memory allocation request
5684 ** handed to [scratch memory allocator]. Only the value returned in the
5685 ** *pHighwater parameter to [sqlite3_status()] is of interest.
5686 ** The value written into the *pCurrent parameter is undefined.</dd>)^
5687 **
5688 ** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
5689 ** <dd>This parameter records the deepest parser stack. It is only
5690 ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
5691 ** </dl>
5692 **
5693 ** New status parameters may be added from time to time.
@@ -5545,13 +5708,13 @@
5708 **
5709 ** ^This interface is used to retrieve runtime status information
5710 ** about a single [database connection]. ^The first argument is the
5711 ** database connection object to be interrogated. ^The second argument
5712 ** is an integer constant, taken from the set of
5713 ** [SQLITE_DBSTATUS options], that
5714 ** determines the parameter to interrogate. The set of
5715 ** [SQLITE_DBSTATUS options] is likely
5716 ** to grow in future releases of SQLite.
5717 **
5718 ** ^The current value of the requested parameter is written into *pCur
5719 ** and the highest instantaneous value is written into *pHiwtr. ^If
5720 ** the resetFlg is true, then the highest instantaneous value is
@@ -5564,10 +5727,11 @@
5727 */
5728 SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
5729
5730 /*
5731 ** CAPI3REF: Status Parameters for database connections
5732 ** KEYWORDS: {SQLITE_DBSTATUS options}
5733 **
5734 ** These constants are the available integer "verbs" that can be passed as
5735 ** the second argument to the [sqlite3_db_status()] interface.
5736 **
5737 ** New verbs may be added in future releases of SQLite. Existing verbs
@@ -5575,48 +5739,50 @@
5739 ** [sqlite3_db_status()] to make sure that the call worked.
5740 ** The [sqlite3_db_status()] interface will return a non-zero error code
5741 ** if a discontinued or unsupported verb is invoked.
5742 **
5743 ** <dl>
5744 ** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
5745 ** <dd>This parameter returns the number of lookaside memory slots currently
5746 ** checked out.</dd>)^
5747 **
5748 ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
5749 ** <dd>This parameter returns the number malloc attempts that were
5750 ** satisfied using lookaside memory. Only the high-water value is meaningful;
5751 ** the current value is always zero.)^
5752 **
5753 ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
5754 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
5755 ** <dd>This parameter returns the number malloc attempts that might have
5756 ** been satisfied using lookaside memory but failed due to the amount of
5757 ** memory requested being larger than the lookaside slot size.
5758 ** Only the high-water value is meaningful;
5759 ** the current value is always zero.)^
5760 **
5761 ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
5762 ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
5763 ** <dd>This parameter returns the number malloc attempts that might have
5764 ** been satisfied using lookaside memory but failed due to all lookaside
5765 ** memory already being in use.
5766 ** Only the high-water value is meaningful;
5767 ** the current value is always zero.)^
5768 **
5769 ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
5770 ** <dd>This parameter returns the approximate number of of bytes of heap
5771 ** memory used by all pager caches associated with the database connection.)^
5772 ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
5773 **
5774 ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
5775 ** <dd>This parameter returns the approximate number of of bytes of heap
5776 ** memory used to store the schema for all databases associated
5777 ** with the connection - main, temp, and any [ATTACH]-ed databases.)^
5778 ** ^The full amount of memory used by the schemas is reported, even if the
5779 ** schema memory is shared with other database connections due to
5780 ** [shared cache mode] being enabled.
5781 ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
5782 **
5783 ** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
5784 ** <dd>This parameter returns the approximate number of of bytes of heap
5785 ** and lookaside memory used by all prepared statements associated with
5786 ** the database connection.)^
5787 ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
5788 ** </dd>
@@ -5634,11 +5800,11 @@
5800
5801 /*
5802 ** CAPI3REF: Prepared Statement Status
5803 **
5804 ** ^(Each prepared statement maintains various
5805 ** [SQLITE_STMTSTATUS counters] that measure the number
5806 ** of times it has performed specific operations.)^ These counters can
5807 ** be used to monitor the performance characteristics of the prepared
5808 ** statements. For example, if the number of table steps greatly exceeds
5809 ** the number of table searches or result rows, that would tend to indicate
5810 ** that the prepared statement is using a full table scan rather than
@@ -5645,11 +5811,11 @@
5811 ** an index.
5812 **
5813 ** ^(This interface is used to retrieve and reset counter values from
5814 ** a [prepared statement]. The first argument is the prepared statement
5815 ** object to be interrogated. The second argument
5816 ** is an integer code for a specific [SQLITE_STMTSTATUS counter]
5817 ** to be interrogated.)^
5818 ** ^The current value of the requested counter is returned.
5819 ** ^If the resetFlg is true, then the counter is reset to zero after this
5820 ** interface call returns.
5821 **
@@ -5657,28 +5823,29 @@
5823 */
5824 SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
5825
5826 /*
5827 ** CAPI3REF: Status Parameters for prepared statements
5828 ** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
5829 **
5830 ** These preprocessor macros define integer codes that name counter
5831 ** values associated with the [sqlite3_stmt_status()] interface.
5832 ** The meanings of the various counters are as follows:
5833 **
5834 ** <dl>
5835 ** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
5836 ** <dd>^This is the number of times that SQLite has stepped forward in
5837 ** a table as part of a full table scan. Large numbers for this counter
5838 ** may indicate opportunities for performance improvement through
5839 ** careful use of indices.</dd>
5840 **
5841 ** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
5842 ** <dd>^This is the number of sort operations that have occurred.
5843 ** A non-zero value in this counter may indicate an opportunity to
5844 ** improvement performance through careful use of indices.</dd>
5845 **
5846 ** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
5847 ** <dd>^This is the number of rows inserted into transient indices that
5848 ** were created automatically in order to help joins run faster.
5849 ** A non-zero value in this counter may indicate an opportunity to
5850 ** improvement performance by adding permanent indices that do not
5851 ** need to be reinitialized each time the statement is run.</dd>
@@ -5725,10 +5892,11 @@
5892 ** ^(The contents of the sqlite3_pcache_methods structure are copied to an
5893 ** internal buffer by SQLite within the call to [sqlite3_config]. Hence
5894 ** the application may discard the parameter after the call to
5895 ** [sqlite3_config()] returns.)^
5896 **
5897 ** [[the xInit() page cache method]]
5898 ** ^(The xInit() method is called once for each effective
5899 ** call to [sqlite3_initialize()])^
5900 ** (usually only once during the lifetime of the process). ^(The xInit()
5901 ** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^
5902 ** The intent of the xInit() method is to set up global data structures
@@ -5735,10 +5903,11 @@
5903 ** required by the custom page cache implementation.
5904 ** ^(If the xInit() method is NULL, then the
5905 ** built-in default page cache is used instead of the application defined
5906 ** page cache.)^
5907 **
5908 ** [[the xShutdown() page cache method]]
5909 ** ^The xShutdown() method is called by [sqlite3_shutdown()].
5910 ** It can be used to clean up
5911 ** any outstanding resources before process shutdown, if required.
5912 ** ^The xShutdown() method may be NULL.
5913 **
@@ -5749,10 +5918,11 @@
5918 ** in multithreaded applications.
5919 **
5920 ** ^SQLite will never invoke xInit() more than once without an intervening
5921 ** call to xShutdown().
5922 **
5923 ** [[the xCreate() page cache methods]]
5924 ** ^SQLite invokes the xCreate() method to construct a new cache instance.
5925 ** SQLite will typically create one cache instance for each open database file,
5926 ** though this is not guaranteed. ^The
5927 ** first parameter, szPage, is the size in bytes of the pages that must
5928 ** be allocated by the cache. ^szPage will not be a power of two. ^szPage
@@ -5773,20 +5943,23 @@
5943 ** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
5944 ** false will always have the "discard" flag set to true.
5945 ** ^Hence, a cache created with bPurgeable false will
5946 ** never contain any unpinned pages.
5947 **
5948 ** [[the xCachesize() page cache method]]
5949 ** ^(The xCachesize() method may be called at any time by SQLite to set the
5950 ** suggested maximum cache-size (number of pages stored by) the cache
5951 ** instance passed as the first argument. This is the value configured using
5952 ** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
5953 ** parameter, the implementation is not required to do anything with this
5954 ** value; it is advisory only.
5955 **
5956 ** [[the xPagecount() page cache methods]]
5957 ** The xPagecount() method must return the number of pages currently
5958 ** stored in the cache, both pinned and unpinned.
5959 **
5960 ** [[the xFetch() page cache methods]]
5961 ** The xFetch() method locates a page in the cache and returns a pointer to
5962 ** the page, or a NULL pointer.
5963 ** A "page", in this context, means a buffer of szPage bytes aligned at an
5964 ** 8-byte boundary. The page to be fetched is determined by the key. ^The
5965 ** mimimum key value is 1. After it has been retrieved using xFetch, the page
@@ -5811,10 +5984,11 @@
5984 ** will only use a createFlag of 2 after a prior call with a createFlag of 1
5985 ** failed.)^ In between the to xFetch() calls, SQLite may
5986 ** attempt to unpin one or more cache pages by spilling the content of
5987 ** pinned pages to disk and synching the operating system disk cache.
5988 **
5989 ** [[the xUnpin() page cache method]]
5990 ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
5991 ** as its second argument. If the third parameter, discard, is non-zero,
5992 ** then the page must be evicted from the cache.
5993 ** ^If the discard parameter is
5994 ** zero, then the page may be discarded or retained at the discretion of
@@ -5823,10 +5997,11 @@
5997 **
5998 ** The cache must not perform any reference counting. A single
5999 ** call to xUnpin() unpins the page regardless of the number of prior calls
6000 ** to xFetch().
6001 **
6002 ** [[the xRekey() page cache methods]]
6003 ** The xRekey() method is used to change the key value associated with the
6004 ** page passed as the second argument. If the cache
6005 ** previously contains an entry associated with newKey, it must be
6006 ** discarded. ^Any prior cache entry associated with newKey is guaranteed not
6007 ** to be pinned.
@@ -5835,10 +6010,11 @@
6010 ** existing cache entries with page numbers (keys) greater than or equal
6011 ** to the value of the iLimit parameter passed to xTruncate(). If any
6012 ** of these pages are pinned, they are implicitly unpinned, meaning that
6013 ** they can be safely discarded.
6014 **
6015 ** [[the xDestroy() page cache method]]
6016 ** ^The xDestroy() method is used to delete a cache allocated by xCreate().
6017 ** All resources associated with the specified cache should be freed. ^After
6018 ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
6019 ** handle invalid, and will not use it with any other sqlite3_pcache_methods
6020 ** functions.
@@ -5897,11 +6073,11 @@
6073 ** associated with the backup operation.
6074 ** </ol>)^
6075 ** There should be exactly one call to sqlite3_backup_finish() for each
6076 ** successful call to sqlite3_backup_init().
6077 **
6078 ** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
6079 **
6080 ** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
6081 ** [database connection] associated with the destination database
6082 ** and the database name, respectively.
6083 ** ^The database name is "main" for the main database, "temp" for the
@@ -5924,11 +6100,11 @@
6100 ** [sqlite3_backup] object.
6101 ** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
6102 ** sqlite3_backup_finish() functions to perform the specified backup
6103 ** operation.
6104 **
6105 ** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
6106 **
6107 ** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
6108 ** the source and destination databases specified by [sqlite3_backup] object B.
6109 ** ^If N is negative, all remaining source pages are copied.
6110 ** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
@@ -5981,11 +6157,11 @@
6157 ** restarted by the next call to sqlite3_backup_step(). ^If the source
6158 ** database is modified by the using the same database connection as is used
6159 ** by the backup operation, then the backup database is automatically
6160 ** updated at the same time.
6161 **
6162 ** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
6163 **
6164 ** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
6165 ** application wishes to abandon the backup operation, the application
6166 ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
6167 ** ^The sqlite3_backup_finish() interfaces releases all
@@ -6004,11 +6180,12 @@
6180 **
6181 ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
6182 ** is not a permanent error and does not affect the return value of
6183 ** sqlite3_backup_finish().
6184 **
6185 ** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
6186 ** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
6187 **
6188 ** ^Each call to sqlite3_backup_step() sets two values inside
6189 ** the [sqlite3_backup] object: the number of pages still to be backed
6190 ** up and the total number of pages in the source database file.
6191 ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
@@ -6389,10 +6566,97 @@
6566 ** each of these values.
6567 */
6568 #define SQLITE_CHECKPOINT_PASSIVE 0
6569 #define SQLITE_CHECKPOINT_FULL 1
6570 #define SQLITE_CHECKPOINT_RESTART 2
6571
6572 /*
6573 ** CAPI3REF: Virtual Table Interface Configuration
6574 **
6575 ** This function may be called by either the [xConnect] or [xCreate] method
6576 ** of a [virtual table] implementation to configure
6577 ** various facets of the virtual table interface.
6578 **
6579 ** If this interface is invoked outside the context of an xConnect or
6580 ** xCreate virtual table method then the behavior is undefined.
6581 **
6582 ** At present, there is only one option that may be configured using
6583 ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
6584 ** may be added in the future.
6585 */
6586 SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
6587
6588 /*
6589 ** CAPI3REF: Virtual Table Configuration Options
6590 **
6591 ** These macros define the various options to the
6592 ** [sqlite3_vtab_config()] interface that [virtual table] implementations
6593 ** can use to customize and optimize their behavior.
6594 **
6595 ** <dl>
6596 ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
6597 ** <dd>Calls of the form
6598 ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
6599 ** where X is an integer. If X is zero, then the [virtual table] whose
6600 ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
6601 ** support constraints. In this configuration (which is the default) if
6602 ** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
6603 ** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
6604 ** specified as part of the users SQL statement, regardless of the actual
6605 ** ON CONFLICT mode specified.
6606 **
6607 ** If X is non-zero, then the virtual table implementation guarantees
6608 ** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
6609 ** any modifications to internal or persistent data structures have been made.
6610 ** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
6611 ** is able to roll back a statement or database transaction, and abandon
6612 ** or continue processing the current SQL statement as appropriate.
6613 ** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
6614 ** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
6615 ** had been ABORT.
6616 **
6617 ** Virtual table implementations that are required to handle OR REPLACE
6618 ** must do so within the [xUpdate] method. If a call to the
6619 ** [sqlite3_vtab_on_conflict()] function indicates that the current ON
6620 ** CONFLICT policy is REPLACE, the virtual table implementation should
6621 ** silently replace the appropriate rows within the xUpdate callback and
6622 ** return SQLITE_OK. Or, if this is not possible, it may return
6623 ** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
6624 ** constraint handling.
6625 ** </dl>
6626 */
6627 #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
6628
6629 /*
6630 ** CAPI3REF: Determine The Virtual Table Conflict Policy
6631 **
6632 ** This function may only be called from within a call to the [xUpdate] method
6633 ** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
6634 ** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
6635 ** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
6636 ** of the SQL statement that triggered the call to the [xUpdate] method of the
6637 ** [virtual table].
6638 */
6639 SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
6640
6641 /*
6642 ** CAPI3REF: Conflict resolution modes
6643 **
6644 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
6645 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
6646 ** is for the SQL statement being evaluated.
6647 **
6648 ** Note that the [SQLITE_IGNORE] constant is also used as a potential
6649 ** return value from the [sqlite3_set_authorizer()] callback and that
6650 ** [SQLITE_ABORT] is also a [result code].
6651 */
6652 #define SQLITE_ROLLBACK 1
6653 /* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
6654 #define SQLITE_FAIL 3
6655 /* #define SQLITE_ABORT 4 // Also an error code */
6656 #define SQLITE_REPLACE 5
6657
6658
6659
6660 /*
6661 ** Undo the hack that converts floating point types to integer for
6662 ** builds on processors without floating point support.
6663
+14 -14
--- src/stash.c
+++ src/stash.c
@@ -185,33 +185,33 @@
185185
blob_zero(&delta);
186186
if( rid==0 ){
187187
db_ephemeral_blob(&q, 5, &delta);
188188
blob_write_to_file(&delta, zNPath);
189189
file_setexe(zNPath, isExec);
190
- printf("ADD %s\n", zNew);
190
+ fossil_print("ADD %s\n", zNew);
191191
}else if( isRemoved ){
192
- printf("DELETE %s\n", zOrig);
193
- unlink(zOPath);
192
+ fossil_print("DELETE %s\n", zOrig);
193
+ file_delete(zOPath);
194194
}else{
195195
Blob a, b, out, disk;
196196
db_ephemeral_blob(&q, 5, &delta);
197197
blob_read_from_file(&disk, zOPath);
198198
content_get(rid, &a);
199199
blob_delta_apply(&a, &delta, &b);
200200
if( blob_compare(&disk, &a)==0 ){
201201
blob_write_to_file(&b, zNPath);
202202
file_setexe(zNPath, isExec);
203
- printf("UPDATE %s\n", zNew);
203
+ fossil_print("UPDATE %s\n", zNew);
204204
}else{
205205
int rc = merge_3way(&a, zOPath, &b, &out);
206206
blob_write_to_file(&out, zNPath);
207207
file_setexe(zNPath, isExec);
208208
if( rc ){
209
- printf("CONFLICT %s\n", zNew);
209
+ fossil_print("CONFLICT %s\n", zNew);
210210
nConflict++;
211211
}else{
212
- printf("MERGE %s\n", zNew);
212
+ fossil_print("MERGE %s\n", zNew);
213213
}
214214
blob_reset(&out);
215215
}
216216
blob_reset(&a);
217217
blob_reset(&b);
@@ -218,16 +218,16 @@
218218
blob_reset(&disk);
219219
}
220220
blob_reset(&delta);
221221
if( fossil_strcmp(zOrig,zNew)!=0 ){
222222
undo_save(zOrig);
223
- unlink(zOPath);
223
+ file_delete(zOPath);
224224
}
225225
}
226226
db_finalize(&q);
227227
if( nConflict ){
228
- printf("WARNING: merge conflicts - see messages above for details.\n");
228
+ fossil_print("WARNING: merge conflicts - see messages above for details.\n");
229229
}
230230
}
231231
232232
/*
233233
** Show the diffs associate with a single stash.
@@ -248,25 +248,25 @@
248248
const char *zNew = db_column_text(&q, 4);
249249
char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig);
250250
Blob delta;
251251
if( rid==0 ){
252252
db_ephemeral_blob(&q, 5, &delta);
253
- printf("ADDED %s\n", zNew);
253
+ fossil_print("ADDED %s\n", zNew);
254254
diff_print_index(zNew);
255255
diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0);
256256
}else if( isRemoved ){
257
- printf("DELETE %s\n", zOrig);
257
+ fossil_print("DELETE %s\n", zOrig);
258258
blob_read_from_file(&delta, zOPath);
259259
diff_print_index(zNew);
260260
diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0);
261261
}else{
262262
Blob a, b, disk;
263263
db_ephemeral_blob(&q, 5, &delta);
264264
blob_read_from_file(&disk, zOPath);
265265
content_get(rid, &a);
266266
blob_delta_apply(&a, &delta, &b);
267
- printf("CHANGED %s\n", zNew);
267
+ fossil_print("CHANGED %s\n", zNew);
268268
diff_file_mem(&disk, &b, zNew, zDiffCmd, 0);
269269
blob_reset(&a);
270270
blob_reset(&b);
271271
blob_reset(&disk);
272272
}
@@ -413,23 +413,23 @@
413413
" ORDER BY ctime DESC"
414414
);
415415
while( db_step(&q)==SQLITE_ROW ){
416416
const char *zCom;
417417
n++;
418
- printf("%5d: [%.14s] on %s\n",
418
+ fossil_print("%5d: [%.14s] on %s\n",
419419
db_column_int(&q, 0),
420420
db_column_text(&q, 1),
421421
db_column_text(&q, 3)
422422
);
423423
zCom = db_column_text(&q, 2);
424424
if( zCom && zCom[0] ){
425
- printf(" ");
425
+ fossil_print(" ");
426426
comment_print(zCom, 7, 79);
427427
}
428428
}
429429
db_finalize(&q);
430
- if( n==0 ) printf("empty stash\n");
430
+ if( n==0 ) fossil_print("empty stash\n");
431431
}else
432432
if( memcmp(zCmd, "drop", nCmd)==0 ){
433433
int allFlag = find_option("all", 0, 0)!=0;
434434
if( g.argc>4 ) usage("stash apply STASHID");
435435
if( allFlag ){
436436
--- src/stash.c
+++ src/stash.c
@@ -185,33 +185,33 @@
185 blob_zero(&delta);
186 if( rid==0 ){
187 db_ephemeral_blob(&q, 5, &delta);
188 blob_write_to_file(&delta, zNPath);
189 file_setexe(zNPath, isExec);
190 printf("ADD %s\n", zNew);
191 }else if( isRemoved ){
192 printf("DELETE %s\n", zOrig);
193 unlink(zOPath);
194 }else{
195 Blob a, b, out, disk;
196 db_ephemeral_blob(&q, 5, &delta);
197 blob_read_from_file(&disk, zOPath);
198 content_get(rid, &a);
199 blob_delta_apply(&a, &delta, &b);
200 if( blob_compare(&disk, &a)==0 ){
201 blob_write_to_file(&b, zNPath);
202 file_setexe(zNPath, isExec);
203 printf("UPDATE %s\n", zNew);
204 }else{
205 int rc = merge_3way(&a, zOPath, &b, &out);
206 blob_write_to_file(&out, zNPath);
207 file_setexe(zNPath, isExec);
208 if( rc ){
209 printf("CONFLICT %s\n", zNew);
210 nConflict++;
211 }else{
212 printf("MERGE %s\n", zNew);
213 }
214 blob_reset(&out);
215 }
216 blob_reset(&a);
217 blob_reset(&b);
@@ -218,16 +218,16 @@
218 blob_reset(&disk);
219 }
220 blob_reset(&delta);
221 if( fossil_strcmp(zOrig,zNew)!=0 ){
222 undo_save(zOrig);
223 unlink(zOPath);
224 }
225 }
226 db_finalize(&q);
227 if( nConflict ){
228 printf("WARNING: merge conflicts - see messages above for details.\n");
229 }
230 }
231
232 /*
233 ** Show the diffs associate with a single stash.
@@ -248,25 +248,25 @@
248 const char *zNew = db_column_text(&q, 4);
249 char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig);
250 Blob delta;
251 if( rid==0 ){
252 db_ephemeral_blob(&q, 5, &delta);
253 printf("ADDED %s\n", zNew);
254 diff_print_index(zNew);
255 diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0);
256 }else if( isRemoved ){
257 printf("DELETE %s\n", zOrig);
258 blob_read_from_file(&delta, zOPath);
259 diff_print_index(zNew);
260 diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0);
261 }else{
262 Blob a, b, disk;
263 db_ephemeral_blob(&q, 5, &delta);
264 blob_read_from_file(&disk, zOPath);
265 content_get(rid, &a);
266 blob_delta_apply(&a, &delta, &b);
267 printf("CHANGED %s\n", zNew);
268 diff_file_mem(&disk, &b, zNew, zDiffCmd, 0);
269 blob_reset(&a);
270 blob_reset(&b);
271 blob_reset(&disk);
272 }
@@ -413,23 +413,23 @@
413 " ORDER BY ctime DESC"
414 );
415 while( db_step(&q)==SQLITE_ROW ){
416 const char *zCom;
417 n++;
418 printf("%5d: [%.14s] on %s\n",
419 db_column_int(&q, 0),
420 db_column_text(&q, 1),
421 db_column_text(&q, 3)
422 );
423 zCom = db_column_text(&q, 2);
424 if( zCom && zCom[0] ){
425 printf(" ");
426 comment_print(zCom, 7, 79);
427 }
428 }
429 db_finalize(&q);
430 if( n==0 ) printf("empty stash\n");
431 }else
432 if( memcmp(zCmd, "drop", nCmd)==0 ){
433 int allFlag = find_option("all", 0, 0)!=0;
434 if( g.argc>4 ) usage("stash apply STASHID");
435 if( allFlag ){
436
--- src/stash.c
+++ src/stash.c
@@ -185,33 +185,33 @@
185 blob_zero(&delta);
186 if( rid==0 ){
187 db_ephemeral_blob(&q, 5, &delta);
188 blob_write_to_file(&delta, zNPath);
189 file_setexe(zNPath, isExec);
190 fossil_print("ADD %s\n", zNew);
191 }else if( isRemoved ){
192 fossil_print("DELETE %s\n", zOrig);
193 file_delete(zOPath);
194 }else{
195 Blob a, b, out, disk;
196 db_ephemeral_blob(&q, 5, &delta);
197 blob_read_from_file(&disk, zOPath);
198 content_get(rid, &a);
199 blob_delta_apply(&a, &delta, &b);
200 if( blob_compare(&disk, &a)==0 ){
201 blob_write_to_file(&b, zNPath);
202 file_setexe(zNPath, isExec);
203 fossil_print("UPDATE %s\n", zNew);
204 }else{
205 int rc = merge_3way(&a, zOPath, &b, &out);
206 blob_write_to_file(&out, zNPath);
207 file_setexe(zNPath, isExec);
208 if( rc ){
209 fossil_print("CONFLICT %s\n", zNew);
210 nConflict++;
211 }else{
212 fossil_print("MERGE %s\n", zNew);
213 }
214 blob_reset(&out);
215 }
216 blob_reset(&a);
217 blob_reset(&b);
@@ -218,16 +218,16 @@
218 blob_reset(&disk);
219 }
220 blob_reset(&delta);
221 if( fossil_strcmp(zOrig,zNew)!=0 ){
222 undo_save(zOrig);
223 file_delete(zOPath);
224 }
225 }
226 db_finalize(&q);
227 if( nConflict ){
228 fossil_print("WARNING: merge conflicts - see messages above for details.\n");
229 }
230 }
231
232 /*
233 ** Show the diffs associate with a single stash.
@@ -248,25 +248,25 @@
248 const char *zNew = db_column_text(&q, 4);
249 char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig);
250 Blob delta;
251 if( rid==0 ){
252 db_ephemeral_blob(&q, 5, &delta);
253 fossil_print("ADDED %s\n", zNew);
254 diff_print_index(zNew);
255 diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0);
256 }else if( isRemoved ){
257 fossil_print("DELETE %s\n", zOrig);
258 blob_read_from_file(&delta, zOPath);
259 diff_print_index(zNew);
260 diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0);
261 }else{
262 Blob a, b, disk;
263 db_ephemeral_blob(&q, 5, &delta);
264 blob_read_from_file(&disk, zOPath);
265 content_get(rid, &a);
266 blob_delta_apply(&a, &delta, &b);
267 fossil_print("CHANGED %s\n", zNew);
268 diff_file_mem(&disk, &b, zNew, zDiffCmd, 0);
269 blob_reset(&a);
270 blob_reset(&b);
271 blob_reset(&disk);
272 }
@@ -413,23 +413,23 @@
413 " ORDER BY ctime DESC"
414 );
415 while( db_step(&q)==SQLITE_ROW ){
416 const char *zCom;
417 n++;
418 fossil_print("%5d: [%.14s] on %s\n",
419 db_column_int(&q, 0),
420 db_column_text(&q, 1),
421 db_column_text(&q, 3)
422 );
423 zCom = db_column_text(&q, 2);
424 if( zCom && zCom[0] ){
425 fossil_print(" ");
426 comment_print(zCom, 7, 79);
427 }
428 }
429 db_finalize(&q);
430 if( n==0 ) fossil_print("empty stash\n");
431 }else
432 if( memcmp(zCmd, "drop", nCmd)==0 ){
433 int allFlag = find_option("all", 0, 0)!=0;
434 if( g.argc>4 ) usage("stash apply STASHID");
435 if( allFlag ){
436
+11
--- src/style.c
+++ src/style.c
@@ -800,17 +800,28 @@
800800
801801
/*
802802
** WEBPAGE: test_env
803803
*/
804804
void page_test_env(void){
805
+ char c;
806
+ int i;
807
+ char zCap[30];
805808
login_check_credentials();
806809
style_header("Environment Test");
807810
#if !defined(_WIN32)
808811
@ uid=%d(getuid()), gid=%d(getgid())<br />
809812
#endif
810813
@ g.zBaseURL = %h(g.zBaseURL)<br />
811814
@ g.zTop = %h(g.zTop)<br />
815
+ for(i=0, c='a'; c<='z'; c++){
816
+ if( login_has_capability(&c, 1) ) zCap[i++] = c;
817
+ }
818
+ zCap[i] = 0;
819
+ @ g.userUid = %d(g.userUid)<br />
820
+ @ g.zLogin = %h(g.zLogin)<br />
821
+ @ capabilities = %s(zCap)<br />
822
+ @ <hr>
812823
cgi_print_all();
813824
if( g.okSetup ){
814825
const char *zRedir = P("redirect");
815826
if( zRedir ) cgi_redirect(zRedir);
816827
}
817828
--- src/style.c
+++ src/style.c
@@ -800,17 +800,28 @@
800
801 /*
802 ** WEBPAGE: test_env
803 */
804 void page_test_env(void){
 
 
 
805 login_check_credentials();
806 style_header("Environment Test");
807 #if !defined(_WIN32)
808 @ uid=%d(getuid()), gid=%d(getgid())<br />
809 #endif
810 @ g.zBaseURL = %h(g.zBaseURL)<br />
811 @ g.zTop = %h(g.zTop)<br />
 
 
 
 
 
 
 
 
812 cgi_print_all();
813 if( g.okSetup ){
814 const char *zRedir = P("redirect");
815 if( zRedir ) cgi_redirect(zRedir);
816 }
817
--- src/style.c
+++ src/style.c
@@ -800,17 +800,28 @@
800
801 /*
802 ** WEBPAGE: test_env
803 */
804 void page_test_env(void){
805 char c;
806 int i;
807 char zCap[30];
808 login_check_credentials();
809 style_header("Environment Test");
810 #if !defined(_WIN32)
811 @ uid=%d(getuid()), gid=%d(getgid())<br />
812 #endif
813 @ g.zBaseURL = %h(g.zBaseURL)<br />
814 @ g.zTop = %h(g.zTop)<br />
815 for(i=0, c='a'; c<='z'; c++){
816 if( login_has_capability(&c, 1) ) zCap[i++] = c;
817 }
818 zCap[i] = 0;
819 @ g.userUid = %d(g.userUid)<br />
820 @ g.zLogin = %h(g.zLogin)<br />
821 @ capabilities = %s(zCap)<br />
822 @ <hr>
823 cgi_print_all();
824 if( g.okSetup ){
825 const char *zRedir = P("redirect");
826 if( zRedir ) cgi_redirect(zRedir);
827 }
828
+5 -5
--- src/sync.c
+++ src/sync.c
@@ -76,11 +76,11 @@
7676
** autosync, or something?
7777
*/
7878
configSync = CONFIGSET_SHUN;
7979
}
8080
#endif
81
- printf("Autosync: %s\n", g.urlCanonical);
81
+ fossil_print("Autosync: %s\n", g.urlCanonical);
8282
url_enable_proxy("via proxy: ");
8383
rc = client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, configSync, 0);
8484
if( rc ) fossil_warning("Autosync failed");
8585
return rc;
8686
}
@@ -102,11 +102,11 @@
102102
db_find_and_open_repository(0, 0);
103103
db_open_config(0);
104104
if( g.argc==2 ){
105105
zUrl = db_get("last-sync-url", 0);
106106
zPw = unobscure(db_get("last-sync-pw", 0));
107
- if( db_get_boolean("auto-sync",1) ) configSync = CONFIGSET_SHUN;
107
+ if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
108108
}else if( g.argc==3 ){
109109
zUrl = g.argv[2];
110110
}
111111
if( zUrl==0 ){
112112
if( urlOptional ) fossil_exit(0);
@@ -124,11 +124,11 @@
124124
db_set("last-sync-url", g.urlCanonical, 0);
125125
if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0);
126126
}
127127
user_select();
128128
if( g.argc==2 ){
129
- printf("Server: %s\n", g.urlCanonical);
129
+ fossil_print("Server: %s\n", g.urlCanonical);
130130
}
131131
url_enable_proxy("via proxy: ");
132132
*pConfigSync = configSync;
133133
}
134134
@@ -263,12 +263,12 @@
263263
}
264264
}
265265
}
266266
zUrl = db_get("last-sync-url", 0);
267267
if( zUrl==0 ){
268
- printf("off\n");
268
+ fossil_print("off\n");
269269
return;
270270
}else{
271271
url_parse(zUrl);
272
- printf("%s\n", g.urlCanonical);
272
+ fossil_print("%s\n", g.urlCanonical);
273273
}
274274
}
275275
--- src/sync.c
+++ src/sync.c
@@ -76,11 +76,11 @@
76 ** autosync, or something?
77 */
78 configSync = CONFIGSET_SHUN;
79 }
80 #endif
81 printf("Autosync: %s\n", g.urlCanonical);
82 url_enable_proxy("via proxy: ");
83 rc = client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, configSync, 0);
84 if( rc ) fossil_warning("Autosync failed");
85 return rc;
86 }
@@ -102,11 +102,11 @@
102 db_find_and_open_repository(0, 0);
103 db_open_config(0);
104 if( g.argc==2 ){
105 zUrl = db_get("last-sync-url", 0);
106 zPw = unobscure(db_get("last-sync-pw", 0));
107 if( db_get_boolean("auto-sync",1) ) configSync = CONFIGSET_SHUN;
108 }else if( g.argc==3 ){
109 zUrl = g.argv[2];
110 }
111 if( zUrl==0 ){
112 if( urlOptional ) fossil_exit(0);
@@ -124,11 +124,11 @@
124 db_set("last-sync-url", g.urlCanonical, 0);
125 if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0);
126 }
127 user_select();
128 if( g.argc==2 ){
129 printf("Server: %s\n", g.urlCanonical);
130 }
131 url_enable_proxy("via proxy: ");
132 *pConfigSync = configSync;
133 }
134
@@ -263,12 +263,12 @@
263 }
264 }
265 }
266 zUrl = db_get("last-sync-url", 0);
267 if( zUrl==0 ){
268 printf("off\n");
269 return;
270 }else{
271 url_parse(zUrl);
272 printf("%s\n", g.urlCanonical);
273 }
274 }
275
--- src/sync.c
+++ src/sync.c
@@ -76,11 +76,11 @@
76 ** autosync, or something?
77 */
78 configSync = CONFIGSET_SHUN;
79 }
80 #endif
81 fossil_print("Autosync: %s\n", g.urlCanonical);
82 url_enable_proxy("via proxy: ");
83 rc = client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, configSync, 0);
84 if( rc ) fossil_warning("Autosync failed");
85 return rc;
86 }
@@ -102,11 +102,11 @@
102 db_find_and_open_repository(0, 0);
103 db_open_config(0);
104 if( g.argc==2 ){
105 zUrl = db_get("last-sync-url", 0);
106 zPw = unobscure(db_get("last-sync-pw", 0));
107 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
108 }else if( g.argc==3 ){
109 zUrl = g.argv[2];
110 }
111 if( zUrl==0 ){
112 if( urlOptional ) fossil_exit(0);
@@ -124,11 +124,11 @@
124 db_set("last-sync-url", g.urlCanonical, 0);
125 if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0);
126 }
127 user_select();
128 if( g.argc==2 ){
129 fossil_print("Server: %s\n", g.urlCanonical);
130 }
131 url_enable_proxy("via proxy: ");
132 *pConfigSync = configSync;
133 }
134
@@ -263,12 +263,12 @@
263 }
264 }
265 }
266 zUrl = db_get("last-sync-url", 0);
267 if( zUrl==0 ){
268 fossil_print("off\n");
269 return;
270 }else{
271 url_parse(zUrl);
272 fossil_print("%s\n", g.urlCanonical);
273 }
274 }
275
+5 -5
--- src/tag.c
+++ src/tag.c
@@ -438,11 +438,11 @@
438438
" AND tagxref.tagtype>0"
439439
" AND blob.rid=tagxref.rid",
440440
g.argv[3]
441441
);
442442
while( db_step(&q)==SQLITE_ROW ){
443
- printf("%s\n", db_column_text(&q, 0));
443
+ fossil_print("%s\n", db_column_text(&q, 0));
444444
}
445445
db_finalize(&q);
446446
}else{
447447
int tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",
448448
g.argv[3]);
@@ -473,13 +473,13 @@
473473
" ORDER BY tagname"
474474
);
475475
while( db_step(&q)==SQLITE_ROW ){
476476
const char *zName = db_column_text(&q, 0);
477477
if( fRaw ){
478
- printf("%s\n", zName);
478
+ fossil_print("%s\n", zName);
479479
}else if( strncmp(zName, "sym-", 4)==0 ){
480
- printf("%s\n", &zName[4]);
480
+ fossil_print("%s\n", &zName[4]);
481481
}
482482
}
483483
db_finalize(&q);
484484
}else if( g.argc==4 ){
485485
int rid = name_to_rid(g.argv[3]);
@@ -497,13 +497,13 @@
497497
if( fRaw==0 ){
498498
if( strncmp(zName, "sym-", 4)!=0 ) continue;
499499
zName += 4;
500500
}
501501
if( zValue && zValue[0] ){
502
- printf("%s=%s\n", zName, zValue);
502
+ fossil_print("%s=%s\n", zName, zValue);
503503
}else{
504
- printf("%s\n", zName);
504
+ fossil_print("%s\n", zName);
505505
}
506506
}
507507
db_finalize(&q);
508508
}else{
509509
usage("tag list ?CHECK-IN?");
510510
--- src/tag.c
+++ src/tag.c
@@ -438,11 +438,11 @@
438 " AND tagxref.tagtype>0"
439 " AND blob.rid=tagxref.rid",
440 g.argv[3]
441 );
442 while( db_step(&q)==SQLITE_ROW ){
443 printf("%s\n", db_column_text(&q, 0));
444 }
445 db_finalize(&q);
446 }else{
447 int tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",
448 g.argv[3]);
@@ -473,13 +473,13 @@
473 " ORDER BY tagname"
474 );
475 while( db_step(&q)==SQLITE_ROW ){
476 const char *zName = db_column_text(&q, 0);
477 if( fRaw ){
478 printf("%s\n", zName);
479 }else if( strncmp(zName, "sym-", 4)==0 ){
480 printf("%s\n", &zName[4]);
481 }
482 }
483 db_finalize(&q);
484 }else if( g.argc==4 ){
485 int rid = name_to_rid(g.argv[3]);
@@ -497,13 +497,13 @@
497 if( fRaw==0 ){
498 if( strncmp(zName, "sym-", 4)!=0 ) continue;
499 zName += 4;
500 }
501 if( zValue && zValue[0] ){
502 printf("%s=%s\n", zName, zValue);
503 }else{
504 printf("%s\n", zName);
505 }
506 }
507 db_finalize(&q);
508 }else{
509 usage("tag list ?CHECK-IN?");
510
--- src/tag.c
+++ src/tag.c
@@ -438,11 +438,11 @@
438 " AND tagxref.tagtype>0"
439 " AND blob.rid=tagxref.rid",
440 g.argv[3]
441 );
442 while( db_step(&q)==SQLITE_ROW ){
443 fossil_print("%s\n", db_column_text(&q, 0));
444 }
445 db_finalize(&q);
446 }else{
447 int tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",
448 g.argv[3]);
@@ -473,13 +473,13 @@
473 " ORDER BY tagname"
474 );
475 while( db_step(&q)==SQLITE_ROW ){
476 const char *zName = db_column_text(&q, 0);
477 if( fRaw ){
478 fossil_print("%s\n", zName);
479 }else if( strncmp(zName, "sym-", 4)==0 ){
480 fossil_print("%s\n", &zName[4]);
481 }
482 }
483 db_finalize(&q);
484 }else if( g.argc==4 ){
485 int rid = name_to_rid(g.argv[3]);
@@ -497,13 +497,13 @@
497 if( fRaw==0 ){
498 if( strncmp(zName, "sym-", 4)!=0 ) continue;
499 zName += 4;
500 }
501 if( zValue && zValue[0] ){
502 fossil_print("%s=%s\n", zName, zValue);
503 }else{
504 fossil_print("%s\n", zName);
505 }
506 }
507 db_finalize(&q);
508 }else{
509 usage("tag list ?CHECK-IN?");
510
+19 -33
--- src/timeline.c
+++ src/timeline.c
@@ -97,32 +97,10 @@
9797
}else{
9898
@ %s(zU)
9999
}
100100
}
101101
102
-/*
103
-** Count the number of primary non-branch children for the given check-in.
104
-**
105
-** A primary child is one where the parent is the primary parent, not
106
-** a merge parent.
107
-**
108
-** A non-branch child is one which is on the same branch as the parent.
109
-*/
110
-int count_nonbranch_children(int pid){
111
- int nNonBranch;
112
- static const char zSql[] =
113
- @ SELECT count(*) FROM plink
114
- @ WHERE pid=%d AND isprim
115
- @ AND coalesce((SELECT value FROM tagxref
116
- @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
117
- @ =coalesce((SELECT value FROM tagxref
118
- @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
119
- ;
120
- nNonBranch = db_int(0, zSql, pid, TAG_BRANCH, TAG_BRANCH);
121
- return nNonBranch;
122
-}
123
-
124102
/*
125103
** Allowed flags for the tmFlags argument to www_print_timeline
126104
*/
127105
#if INTERFACE
128106
#define TIMELINE_ARTID 0x0001 /* Show artifact IDs on non-check-in lines */
@@ -344,17 +322,19 @@
344322
if( xExtra ){
345323
xExtra(rid);
346324
}
347325
348326
/* Generate the file-change list if requested */
349
- if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' ){
327
+ if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.okHistory ){
350328
int inUl = 0;
351329
if( !fchngQueryInit ){
352330
db_prepare(&fchngQuery,
353331
"SELECT (pid==0) AS isnew,"
354332
" (fid==0) AS isdel,"
355
- " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name"
333
+ " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
334
+ " (SELECT uuid FROM blob WHERE rid=fid),"
335
+ " (SELECT uuid FROM blob WHERE rid=pid)"
356336
" FROM mlink"
357337
" WHERE mid=:mid AND pid!=fid"
358338
" ORDER BY 3"
359339
);
360340
fchngQueryInit = 1;
@@ -362,20 +342,26 @@
362342
db_bind_int(&fchngQuery, ":mid", rid);
363343
while( db_step(&fchngQuery)==SQLITE_ROW ){
364344
const char *zFilename = db_column_text(&fchngQuery, 2);
365345
int isNew = db_column_int(&fchngQuery, 0);
366346
int isDel = db_column_int(&fchngQuery, 1);
347
+ const char *zOld = db_column_text(&fchngQuery, 4);
348
+ const char *zNew = db_column_text(&fchngQuery, 3);
367349
if( !inUl ){
368350
@ <ul class="filelist">
369351
inUl = 1;
370352
}
371353
if( isNew ){
372
- @ <li> %h(zFilename) (new file)</li>
354
+ @ <li> %h(zFilename) (new file) &nbsp;
355
+ @ <a href="%s(g.zTop)/artifact/%S(zNew)" target="diffwindow">[view]
356
+ @ </a></li>
373357
}else if( isDel ){
374358
@ <li> %h(zFilename) (deleted)</li>
375359
}else{
376
- @ <li> %h(zFilename) </li>
360
+ @ <li> %h(zFilename) &nbsp;
361
+ @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)"
362
+ @ target="diffwindow">[diff]</a></li>
377363
}
378364
}
379365
db_reset(&fchngQuery);
380366
if( inUl ){
381367
@ </ul>
@@ -740,23 +726,23 @@
740726
** the event identified by rid.
741727
*/
742728
static void timeline_add_dividers(const char *zDate, int rid){
743729
char *zToDel = 0;
744730
if( zDate==0 ){
745
- zToDel = db_text(0,"SELECT datetime(mtime,'localtime') FROM event"
731
+ zToDel = db_text(0,"SELECT julianday(mtime,'localtime') FROM event"
746732
" WHERE objid=%d", rid);
747733
zDate = zToDel;
748734
if( zDate==0 ) zDate = "1";
749735
}
750736
db_multi_exec(
751737
"INSERT INTO timeline(rid,sortby,etype)"
752
- "VALUES(-1,julianday(%Q,'utc')-5.0e-6,'div')",
738
+ "VALUES(-1,julianday(%Q,'utc')-1.0e-5,'div')",
753739
zDate
754740
);
755741
db_multi_exec(
756742
"INSERT INTO timeline(rid,sortby,etype)"
757
- "VALUES(-2,julianday(%Q,'utc')+5.0e-6,'div')",
743
+ "VALUES(-2,julianday(%Q,'utc')+1.0e-5,'div')",
758744
zDate
759745
);
760746
fossil_free(zToDel);
761747
}
762748
@@ -1217,16 +1203,16 @@
12171203
char zPrefix[80];
12181204
char zUuid[UUID_SIZE+1];
12191205
12201206
sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
12211207
if( memcmp(zDate, zPrevDate, 10) ){
1222
- printf("=== %.10s ===\n", zDate);
1208
+ fossil_print("=== %.10s ===\n", zDate);
12231209
memcpy(zPrevDate, zDate, 10);
12241210
nLine++;
12251211
}
12261212
if( zCom==0 ) zCom = "";
1227
- printf("%.8s ", &zDate[11]);
1213
+ fossil_print("%.8s ", &zDate[11]);
12281214
zPrefix[0] = 0;
12291215
if( nParent>1 ){
12301216
sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
12311217
n = strlen(zPrefix);
12321218
}
@@ -1467,13 +1453,13 @@
14671453
" FROM plink p, plink c"
14681454
" WHERE p.cid=c.pid AND p.mtime>c.mtime"
14691455
);
14701456
while( db_step(&q)==SQLITE_ROW ){
14711457
if( !showDetail ){
1472
- printf("%s\n", db_column_text(&q, 1));
1458
+ fossil_print("%s\n", db_column_text(&q, 1));
14731459
}else{
1474
- printf("%.14s -> %.14s %s -> %s\n",
1460
+ fossil_print("%.14s -> %.14s %s -> %s\n",
14751461
db_column_text(&q, 0),
14761462
db_column_text(&q, 1),
14771463
db_column_text(&q, 2),
14781464
db_column_text(&q, 3));
14791465
}
14801466
--- src/timeline.c
+++ src/timeline.c
@@ -97,32 +97,10 @@
97 }else{
98 @ %s(zU)
99 }
100 }
101
102 /*
103 ** Count the number of primary non-branch children for the given check-in.
104 **
105 ** A primary child is one where the parent is the primary parent, not
106 ** a merge parent.
107 **
108 ** A non-branch child is one which is on the same branch as the parent.
109 */
110 int count_nonbranch_children(int pid){
111 int nNonBranch;
112 static const char zSql[] =
113 @ SELECT count(*) FROM plink
114 @ WHERE pid=%d AND isprim
115 @ AND coalesce((SELECT value FROM tagxref
116 @ WHERE tagid=%d AND rid=plink.pid), 'trunk')
117 @ =coalesce((SELECT value FROM tagxref
118 @ WHERE tagid=%d AND rid=plink.cid), 'trunk')
119 ;
120 nNonBranch = db_int(0, zSql, pid, TAG_BRANCH, TAG_BRANCH);
121 return nNonBranch;
122 }
123
124 /*
125 ** Allowed flags for the tmFlags argument to www_print_timeline
126 */
127 #if INTERFACE
128 #define TIMELINE_ARTID 0x0001 /* Show artifact IDs on non-check-in lines */
@@ -344,17 +322,19 @@
344 if( xExtra ){
345 xExtra(rid);
346 }
347
348 /* Generate the file-change list if requested */
349 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' ){
350 int inUl = 0;
351 if( !fchngQueryInit ){
352 db_prepare(&fchngQuery,
353 "SELECT (pid==0) AS isnew,"
354 " (fid==0) AS isdel,"
355 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name"
 
 
356 " FROM mlink"
357 " WHERE mid=:mid AND pid!=fid"
358 " ORDER BY 3"
359 );
360 fchngQueryInit = 1;
@@ -362,20 +342,26 @@
362 db_bind_int(&fchngQuery, ":mid", rid);
363 while( db_step(&fchngQuery)==SQLITE_ROW ){
364 const char *zFilename = db_column_text(&fchngQuery, 2);
365 int isNew = db_column_int(&fchngQuery, 0);
366 int isDel = db_column_int(&fchngQuery, 1);
 
 
367 if( !inUl ){
368 @ <ul class="filelist">
369 inUl = 1;
370 }
371 if( isNew ){
372 @ <li> %h(zFilename) (new file)</li>
 
 
373 }else if( isDel ){
374 @ <li> %h(zFilename) (deleted)</li>
375 }else{
376 @ <li> %h(zFilename) </li>
 
 
377 }
378 }
379 db_reset(&fchngQuery);
380 if( inUl ){
381 @ </ul>
@@ -740,23 +726,23 @@
740 ** the event identified by rid.
741 */
742 static void timeline_add_dividers(const char *zDate, int rid){
743 char *zToDel = 0;
744 if( zDate==0 ){
745 zToDel = db_text(0,"SELECT datetime(mtime,'localtime') FROM event"
746 " WHERE objid=%d", rid);
747 zDate = zToDel;
748 if( zDate==0 ) zDate = "1";
749 }
750 db_multi_exec(
751 "INSERT INTO timeline(rid,sortby,etype)"
752 "VALUES(-1,julianday(%Q,'utc')-5.0e-6,'div')",
753 zDate
754 );
755 db_multi_exec(
756 "INSERT INTO timeline(rid,sortby,etype)"
757 "VALUES(-2,julianday(%Q,'utc')+5.0e-6,'div')",
758 zDate
759 );
760 fossil_free(zToDel);
761 }
762
@@ -1217,16 +1203,16 @@
1217 char zPrefix[80];
1218 char zUuid[UUID_SIZE+1];
1219
1220 sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
1221 if( memcmp(zDate, zPrevDate, 10) ){
1222 printf("=== %.10s ===\n", zDate);
1223 memcpy(zPrevDate, zDate, 10);
1224 nLine++;
1225 }
1226 if( zCom==0 ) zCom = "";
1227 printf("%.8s ", &zDate[11]);
1228 zPrefix[0] = 0;
1229 if( nParent>1 ){
1230 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
1231 n = strlen(zPrefix);
1232 }
@@ -1467,13 +1453,13 @@
1467 " FROM plink p, plink c"
1468 " WHERE p.cid=c.pid AND p.mtime>c.mtime"
1469 );
1470 while( db_step(&q)==SQLITE_ROW ){
1471 if( !showDetail ){
1472 printf("%s\n", db_column_text(&q, 1));
1473 }else{
1474 printf("%.14s -> %.14s %s -> %s\n",
1475 db_column_text(&q, 0),
1476 db_column_text(&q, 1),
1477 db_column_text(&q, 2),
1478 db_column_text(&q, 3));
1479 }
1480
--- src/timeline.c
+++ src/timeline.c
@@ -97,32 +97,10 @@
97 }else{
98 @ %s(zU)
99 }
100 }
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102 /*
103 ** Allowed flags for the tmFlags argument to www_print_timeline
104 */
105 #if INTERFACE
106 #define TIMELINE_ARTID 0x0001 /* Show artifact IDs on non-check-in lines */
@@ -344,17 +322,19 @@
322 if( xExtra ){
323 xExtra(rid);
324 }
325
326 /* Generate the file-change list if requested */
327 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.okHistory ){
328 int inUl = 0;
329 if( !fchngQueryInit ){
330 db_prepare(&fchngQuery,
331 "SELECT (pid==0) AS isnew,"
332 " (fid==0) AS isdel,"
333 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
334 " (SELECT uuid FROM blob WHERE rid=fid),"
335 " (SELECT uuid FROM blob WHERE rid=pid)"
336 " FROM mlink"
337 " WHERE mid=:mid AND pid!=fid"
338 " ORDER BY 3"
339 );
340 fchngQueryInit = 1;
@@ -362,20 +342,26 @@
342 db_bind_int(&fchngQuery, ":mid", rid);
343 while( db_step(&fchngQuery)==SQLITE_ROW ){
344 const char *zFilename = db_column_text(&fchngQuery, 2);
345 int isNew = db_column_int(&fchngQuery, 0);
346 int isDel = db_column_int(&fchngQuery, 1);
347 const char *zOld = db_column_text(&fchngQuery, 4);
348 const char *zNew = db_column_text(&fchngQuery, 3);
349 if( !inUl ){
350 @ <ul class="filelist">
351 inUl = 1;
352 }
353 if( isNew ){
354 @ <li> %h(zFilename) (new file) &nbsp;
355 @ <a href="%s(g.zTop)/artifact/%S(zNew)" target="diffwindow">[view]
356 @ </a></li>
357 }else if( isDel ){
358 @ <li> %h(zFilename) (deleted)</li>
359 }else{
360 @ <li> %h(zFilename) &nbsp;
361 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)"
362 @ target="diffwindow">[diff]</a></li>
363 }
364 }
365 db_reset(&fchngQuery);
366 if( inUl ){
367 @ </ul>
@@ -740,23 +726,23 @@
726 ** the event identified by rid.
727 */
728 static void timeline_add_dividers(const char *zDate, int rid){
729 char *zToDel = 0;
730 if( zDate==0 ){
731 zToDel = db_text(0,"SELECT julianday(mtime,'localtime') FROM event"
732 " WHERE objid=%d", rid);
733 zDate = zToDel;
734 if( zDate==0 ) zDate = "1";
735 }
736 db_multi_exec(
737 "INSERT INTO timeline(rid,sortby,etype)"
738 "VALUES(-1,julianday(%Q,'utc')-1.0e-5,'div')",
739 zDate
740 );
741 db_multi_exec(
742 "INSERT INTO timeline(rid,sortby,etype)"
743 "VALUES(-2,julianday(%Q,'utc')+1.0e-5,'div')",
744 zDate
745 );
746 fossil_free(zToDel);
747 }
748
@@ -1217,16 +1203,16 @@
1203 char zPrefix[80];
1204 char zUuid[UUID_SIZE+1];
1205
1206 sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
1207 if( memcmp(zDate, zPrevDate, 10) ){
1208 fossil_print("=== %.10s ===\n", zDate);
1209 memcpy(zPrevDate, zDate, 10);
1210 nLine++;
1211 }
1212 if( zCom==0 ) zCom = "";
1213 fossil_print("%.8s ", &zDate[11]);
1214 zPrefix[0] = 0;
1215 if( nParent>1 ){
1216 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
1217 n = strlen(zPrefix);
1218 }
@@ -1467,13 +1453,13 @@
1453 " FROM plink p, plink c"
1454 " WHERE p.cid=c.pid AND p.mtime>c.mtime"
1455 );
1456 while( db_step(&q)==SQLITE_ROW ){
1457 if( !showDetail ){
1458 fossil_print("%s\n", db_column_text(&q, 1));
1459 }else{
1460 fossil_print("%.14s -> %.14s %s -> %s\n",
1461 db_column_text(&q, 0),
1462 db_column_text(&q, 1),
1463 db_column_text(&q, 2),
1464 db_column_text(&q, 3));
1465 }
1466
+2 -1
--- src/tkt.c
+++ src/tkt.c
@@ -216,11 +216,12 @@
216216
char *zTag = mprintf("tkt-%s", zTktUuid);
217217
int tagid = tag_findid(zTag, 1);
218218
Stmt q;
219219
Manifest *pTicket;
220220
int createFlag = 1;
221
-
221
+
222
+ fossil_free(zTag);
222223
db_multi_exec(
223224
"DELETE FROM ticket WHERE tkt_uuid=%Q", zTktUuid
224225
);
225226
db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid);
226227
while( db_step(&q)==SQLITE_ROW ){
227228
--- src/tkt.c
+++ src/tkt.c
@@ -216,11 +216,12 @@
216 char *zTag = mprintf("tkt-%s", zTktUuid);
217 int tagid = tag_findid(zTag, 1);
218 Stmt q;
219 Manifest *pTicket;
220 int createFlag = 1;
221
 
222 db_multi_exec(
223 "DELETE FROM ticket WHERE tkt_uuid=%Q", zTktUuid
224 );
225 db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid);
226 while( db_step(&q)==SQLITE_ROW ){
227
--- src/tkt.c
+++ src/tkt.c
@@ -216,11 +216,12 @@
216 char *zTag = mprintf("tkt-%s", zTktUuid);
217 int tagid = tag_findid(zTag, 1);
218 Stmt q;
219 Manifest *pTicket;
220 int createFlag = 1;
221
222 fossil_free(zTag);
223 db_multi_exec(
224 "DELETE FROM ticket WHERE tkt_uuid=%Q", zTktUuid
225 );
226 db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid);
227 while( db_step(&q)==SQLITE_ROW ){
228
+15 -14
--- src/undo.c
+++ src/undo.c
@@ -58,19 +58,19 @@
5858
if( old_exists ){
5959
db_ephemeral_blob(&q, 0, &new);
6060
}
6161
if( old_exists ){
6262
if( new_exists ){
63
- printf("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
63
+ fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
6464
}else{
65
- printf("NEW %s\n", zPathname);
65
+ fossil_print("NEW %s\n", zPathname);
6666
}
6767
blob_write_to_file(&new, zFullname);
6868
file_setexe(zFullname, old_exe);
6969
}else{
70
- printf("DELETE %s\n", zPathname);
71
- unlink(zFullname);
70
+ fossil_print("DELETE %s\n", zPathname);
71
+ file_delete(zFullname);
7272
}
7373
blob_reset(&new);
7474
free(zFullname);
7575
db_finalize(&q);
7676
db_prepare(&q,
@@ -297,11 +297,11 @@
297297
** Complete the undo process is one is currently in process.
298298
*/
299299
void undo_finish(void){
300300
if( undoActive ){
301301
if( undoNeedRollback ){
302
- printf("\"fossil undo\" is available to undo changes"
302
+ fossil_print("\"fossil undo\" is available to undo changes"
303303
" to the working checkout.\n");
304304
}
305305
undoActive = 0;
306306
undoNeedRollback = 0;
307307
}
@@ -319,11 +319,11 @@
319319
void undo_rollback(void){
320320
if( !undoNeedRollback ) return;
321321
assert( undoActive );
322322
undoNeedRollback = 0;
323323
undoActive = 0;
324
- printf("Rolling back prior filesystem changes...\n");
324
+ fossil_print("Rolling back prior filesystem changes...\n");
325325
undo_all_filesystem(0);
326326
}
327327
328328
/*
329329
** COMMAND: undo
@@ -360,34 +360,35 @@
360360
verify_all_options();
361361
db_begin_transaction();
362362
undo_available = db_lget_int("undo_available", 0);
363363
if( explainFlag ){
364364
if( undo_available==0 ){
365
- printf("No undo or redo is available\n");
365
+ fossil_print("No undo or redo is available\n");
366366
}else{
367367
Stmt q;
368368
int nChng = 0;
369369
zCmd = undo_available==1 ? "undo" : "redo";
370
- printf("A %s is available for the following command:\n\n %s %s\n\n",
371
- zCmd, g.argv[0], db_lget("undo_cmdline", "???"));
370
+ fossil_print("A %s is available for the following command:\n\n"
371
+ " %s %s\n\n",
372
+ zCmd, g.argv[0], db_lget("undo_cmdline", "???"));
372373
db_prepare(&q,
373374
"SELECT existsflag, pathname FROM undo ORDER BY pathname"
374375
);
375376
while( db_step(&q)==SQLITE_ROW ){
376377
if( nChng==0 ){
377
- printf("The following file changes would occur if the "
378
- "command above is %sne:\n\n", zCmd);
378
+ fossil_print("The following file changes would occur if the "
379
+ "command above is %sne:\n\n", zCmd);
379380
}
380381
nChng++;
381
- printf("%s %s\n",
382
+ fossil_print("%s %s\n",
382383
db_column_int(&q,0) ? "UPDATE" : "DELETE",
383384
db_column_text(&q, 1)
384385
);
385386
}
386387
db_finalize(&q);
387388
if( nChng==0 ){
388
- printf("No file changes would occur with this undo/redo.\n");
389
+ fossil_print("No file changes would occur with this undo/redo.\n");
389390
}
390391
}
391392
}else{
392393
int vid1 = db_lget_int("checkout", 0);
393394
int vid2;
@@ -410,11 +411,11 @@
410411
blob_reset(&path);
411412
}
412413
}
413414
vid2 = db_lget_int("checkout", 0);
414415
if( vid1!=vid2 ){
415
- printf("--------------------\n");
416
+ fossil_print("--------------------\n");
416417
show_common_info(vid2, "updated-to:", 1, 0);
417418
}
418419
}
419420
db_end_transaction(0);
420421
}
421422
--- src/undo.c
+++ src/undo.c
@@ -58,19 +58,19 @@
58 if( old_exists ){
59 db_ephemeral_blob(&q, 0, &new);
60 }
61 if( old_exists ){
62 if( new_exists ){
63 printf("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
64 }else{
65 printf("NEW %s\n", zPathname);
66 }
67 blob_write_to_file(&new, zFullname);
68 file_setexe(zFullname, old_exe);
69 }else{
70 printf("DELETE %s\n", zPathname);
71 unlink(zFullname);
72 }
73 blob_reset(&new);
74 free(zFullname);
75 db_finalize(&q);
76 db_prepare(&q,
@@ -297,11 +297,11 @@
297 ** Complete the undo process is one is currently in process.
298 */
299 void undo_finish(void){
300 if( undoActive ){
301 if( undoNeedRollback ){
302 printf("\"fossil undo\" is available to undo changes"
303 " to the working checkout.\n");
304 }
305 undoActive = 0;
306 undoNeedRollback = 0;
307 }
@@ -319,11 +319,11 @@
319 void undo_rollback(void){
320 if( !undoNeedRollback ) return;
321 assert( undoActive );
322 undoNeedRollback = 0;
323 undoActive = 0;
324 printf("Rolling back prior filesystem changes...\n");
325 undo_all_filesystem(0);
326 }
327
328 /*
329 ** COMMAND: undo
@@ -360,34 +360,35 @@
360 verify_all_options();
361 db_begin_transaction();
362 undo_available = db_lget_int("undo_available", 0);
363 if( explainFlag ){
364 if( undo_available==0 ){
365 printf("No undo or redo is available\n");
366 }else{
367 Stmt q;
368 int nChng = 0;
369 zCmd = undo_available==1 ? "undo" : "redo";
370 printf("A %s is available for the following command:\n\n %s %s\n\n",
371 zCmd, g.argv[0], db_lget("undo_cmdline", "???"));
 
372 db_prepare(&q,
373 "SELECT existsflag, pathname FROM undo ORDER BY pathname"
374 );
375 while( db_step(&q)==SQLITE_ROW ){
376 if( nChng==0 ){
377 printf("The following file changes would occur if the "
378 "command above is %sne:\n\n", zCmd);
379 }
380 nChng++;
381 printf("%s %s\n",
382 db_column_int(&q,0) ? "UPDATE" : "DELETE",
383 db_column_text(&q, 1)
384 );
385 }
386 db_finalize(&q);
387 if( nChng==0 ){
388 printf("No file changes would occur with this undo/redo.\n");
389 }
390 }
391 }else{
392 int vid1 = db_lget_int("checkout", 0);
393 int vid2;
@@ -410,11 +411,11 @@
410 blob_reset(&path);
411 }
412 }
413 vid2 = db_lget_int("checkout", 0);
414 if( vid1!=vid2 ){
415 printf("--------------------\n");
416 show_common_info(vid2, "updated-to:", 1, 0);
417 }
418 }
419 db_end_transaction(0);
420 }
421
--- src/undo.c
+++ src/undo.c
@@ -58,19 +58,19 @@
58 if( old_exists ){
59 db_ephemeral_blob(&q, 0, &new);
60 }
61 if( old_exists ){
62 if( new_exists ){
63 fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
64 }else{
65 fossil_print("NEW %s\n", zPathname);
66 }
67 blob_write_to_file(&new, zFullname);
68 file_setexe(zFullname, old_exe);
69 }else{
70 fossil_print("DELETE %s\n", zPathname);
71 file_delete(zFullname);
72 }
73 blob_reset(&new);
74 free(zFullname);
75 db_finalize(&q);
76 db_prepare(&q,
@@ -297,11 +297,11 @@
297 ** Complete the undo process is one is currently in process.
298 */
299 void undo_finish(void){
300 if( undoActive ){
301 if( undoNeedRollback ){
302 fossil_print("\"fossil undo\" is available to undo changes"
303 " to the working checkout.\n");
304 }
305 undoActive = 0;
306 undoNeedRollback = 0;
307 }
@@ -319,11 +319,11 @@
319 void undo_rollback(void){
320 if( !undoNeedRollback ) return;
321 assert( undoActive );
322 undoNeedRollback = 0;
323 undoActive = 0;
324 fossil_print("Rolling back prior filesystem changes...\n");
325 undo_all_filesystem(0);
326 }
327
328 /*
329 ** COMMAND: undo
@@ -360,34 +360,35 @@
360 verify_all_options();
361 db_begin_transaction();
362 undo_available = db_lget_int("undo_available", 0);
363 if( explainFlag ){
364 if( undo_available==0 ){
365 fossil_print("No undo or redo is available\n");
366 }else{
367 Stmt q;
368 int nChng = 0;
369 zCmd = undo_available==1 ? "undo" : "redo";
370 fossil_print("A %s is available for the following command:\n\n"
371 " %s %s\n\n",
372 zCmd, g.argv[0], db_lget("undo_cmdline", "???"));
373 db_prepare(&q,
374 "SELECT existsflag, pathname FROM undo ORDER BY pathname"
375 );
376 while( db_step(&q)==SQLITE_ROW ){
377 if( nChng==0 ){
378 fossil_print("The following file changes would occur if the "
379 "command above is %sne:\n\n", zCmd);
380 }
381 nChng++;
382 fossil_print("%s %s\n",
383 db_column_int(&q,0) ? "UPDATE" : "DELETE",
384 db_column_text(&q, 1)
385 );
386 }
387 db_finalize(&q);
388 if( nChng==0 ){
389 fossil_print("No file changes would occur with this undo/redo.\n");
390 }
391 }
392 }else{
393 int vid1 = db_lget_int("checkout", 0);
394 int vid2;
@@ -410,11 +411,11 @@
411 blob_reset(&path);
412 }
413 }
414 vid2 = db_lget_int("checkout", 0);
415 if( vid1!=vid2 ){
416 fossil_print("--------------------\n");
417 show_common_info(vid2, "updated-to:", 1, 0);
418 }
419 }
420 db_end_transaction(0);
421 }
422
+30 -24
--- src/update.c
+++ src/update.c
@@ -175,13 +175,18 @@
175175
}
176176
}
177177
tid = db_int(0, "SELECT rid FROM leaves, event"
178178
" WHERE event.objid=leaves.rid"
179179
" ORDER BY event.mtime DESC");
180
+ if( tid==0 ) tid = vid;
181
+ }
182
+
183
+ if( tid==0 ){
184
+ fossil_panic("Internal Error: unable to find a version to update to.");
180185
}
181186
182
- if( !verboseFlag && (tid==vid)) return; /* Nothing to update */
187
+ if( tid==vid && !verboseFlag ) return; /* Nothing to update */
183188
db_begin_transaction();
184189
vfile_check_signature(vid, 1, 0);
185190
if( !nochangeFlag && !internalUpdate ) undo_begin();
186191
load_vfile_from_rid(tid);
187192
@@ -253,18 +258,18 @@
253258
if( debugFlag ){
254259
db_prepare(&q,
255260
"SELECT rowid, fn, fnt, chnged, ridv, ridt, isexe FROM fv"
256261
);
257262
while( db_step(&q)==SQLITE_ROW ){
258
- printf("%3d: ridv=%-4d ridt=%-4d chnged=%d isexe=%d\n",
263
+ fossil_print("%3d: ridv=%-4d ridt=%-4d chnged=%d isexe=%d\n",
259264
db_column_int(&q, 0),
260265
db_column_int(&q, 4),
261266
db_column_int(&q, 5),
262267
db_column_int(&q, 3),
263268
db_column_int(&q, 6));
264
- printf(" fnv = [%s]\n", db_column_text(&q, 1));
265
- printf(" fnt = [%s]\n", db_column_text(&q, 2));
269
+ fossil_print(" fnv = [%s]\n", db_column_text(&q, 1));
270
+ fossil_print(" fnt = [%s]\n", db_column_text(&q, 2));
266271
}
267272
db_finalize(&q);
268273
}
269274
270275
/* If FILES appear on the command-line, remove from the "fv" table
@@ -331,26 +336,26 @@
331336
nameChng = fossil_strcmp(zName, zNewName);
332337
if( idv>0 && ridv==0 && idt>0 && ridt>0 ){
333338
/* Conflict. This file has been added to the current checkout
334339
** but also exists in the target checkout. Use the current version.
335340
*/
336
- printf("CONFLICT %s\n", zName);
341
+ fossil_print("CONFLICT %s\n", zName);
337342
nConflict++;
338343
}else if( idt>0 && idv==0 ){
339344
/* File added in the target. */
340
- printf("ADD %s\n", zName);
345
+ fossil_print("ADD %s\n", zName);
341346
undo_save(zName);
342347
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
343348
}else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
344349
/* The file is unedited. Change it to the target version */
345350
undo_save(zName);
346
- printf("UPDATE %s\n", zName);
351
+ fossil_print("UPDATE %s\n", zName);
347352
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
348353
}else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
349354
/* The file missing from the local check-out. Restore it to the
350355
** version that appears in the target. */
351
- printf("UPDATE %s\n", zName);
356
+ fossil_print("UPDATE %s\n", zName);
352357
undo_save(zName);
353358
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
354359
}else if( idt==0 && idv>0 ){
355360
if( ridv==0 ){
356361
/* Added in current checkout. Continue to hold the file as
@@ -357,25 +362,26 @@
357362
** as an addition */
358363
db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
359364
}else if( chnged ){
360365
/* Edited locally but deleted from the target. Do not track the
361366
** file but keep the edited version around. */
362
- printf("CONFLICT %s - edited locally but deleted by update\n", zName);
367
+ fossil_print("CONFLICT %s - edited locally but deleted by update\n",
368
+ zName);
363369
nConflict++;
364370
}else{
365
- printf("REMOVE %s\n", zName);
371
+ fossil_print("REMOVE %s\n", zName);
366372
undo_save(zName);
367
- if( !nochangeFlag ) unlink(zFullPath);
373
+ if( !nochangeFlag ) file_delete(zFullPath);
368374
}
369375
}else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
370376
/* Merge the changes in the current tree into the target version */
371377
Blob r, t, v;
372378
int rc;
373379
if( nameChng ){
374
- printf("MERGE %s -> %s\n", zName, zNewName);
380
+ fossil_print("MERGE %s -> %s\n", zName, zNewName);
375381
}else{
376
- printf("MERGE %s\n", zName);
382
+ fossil_print("MERGE %s\n", zName);
377383
}
378384
undo_save(zName);
379385
content_get(ridt, &t);
380386
content_get(ridv, &v);
381387
rc = merge_3way(&v, zFullPath, &t, &r);
@@ -383,51 +389,51 @@
383389
if( !nochangeFlag ){
384390
blob_write_to_file(&r, zFullNewPath);
385391
file_setexe(zFullNewPath, isexe);
386392
}
387393
if( rc>0 ){
388
- printf("***** %d merge conflicts in %s\n", rc, zNewName);
394
+ fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
389395
nConflict++;
390396
}
391397
}else{
392398
if( !nochangeFlag ){
393399
blob_write_to_file(&t, zFullNewPath);
394400
file_setexe(zFullNewPath, isexe);
395401
}
396
- printf("***** Cannot merge binary file %s\n", zNewName);
402
+ fossil_print("***** Cannot merge binary file %s\n", zNewName);
397403
nConflict++;
398404
}
399
- if( nameChng && !nochangeFlag ) unlink(zFullPath);
405
+ if( nameChng && !nochangeFlag ) file_delete(zFullPath);
400406
blob_reset(&v);
401407
blob_reset(&t);
402408
blob_reset(&r);
403409
}else{
404410
if( chnged ){
405
- if( verboseFlag ) printf("EDITED %s\n", zName);
411
+ if( verboseFlag ) fossil_print("EDITED %s\n", zName);
406412
}else{
407413
db_bind_int(&mtimeXfer, ":idv", idv);
408414
db_bind_int(&mtimeXfer, ":idt", idt);
409415
db_step(&mtimeXfer);
410416
db_reset(&mtimeXfer);
411
- if( verboseFlag ) printf("UNCHANGED %s\n", zName);
417
+ if( verboseFlag ) fossil_print("UNCHANGED %s\n", zName);
412418
}
413419
}
414420
free(zFullPath);
415421
free(zFullNewPath);
416422
}
417423
db_finalize(&q);
418424
db_finalize(&mtimeXfer);
419
- printf("--------------\n");
425
+ fossil_print("--------------\n");
420426
show_common_info(tid, "updated-to:", 1, 0);
421427
422428
/* Report on conflicts
423429
*/
424430
if( nConflict && !nochangeFlag ){
425431
if( internalUpdate ){
426432
internalConflictCnt = nConflict;
427433
}else{
428
- printf("WARNING: %d merge conflicts - see messages above for details.\n",
434
+ fossil_print("WARNING: %d merge conflicts - see messages above for details.\n",
429435
nConflict);
430436
}
431437
}
432438
433439
/*
@@ -570,23 +576,23 @@
570576
zFile = db_column_text(&q, 0);
571577
zFull = mprintf("%/%/", g.zLocalRoot, zFile);
572578
errCode = historical_version_of_file(zRevision, zFile, &record, &isExe,2);
573579
if( errCode==2 ){
574580
if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){
575
- printf("UNMANAGE: %s\n", zFile);
581
+ fossil_print("UNMANAGE: %s\n", zFile);
576582
}else{
577583
undo_save(zFile);
578
- unlink(zFull);
579
- printf("DELETE: %s\n", zFile);
584
+ file_delete(zFull);
585
+ fossil_print("DELETE: %s\n", zFile);
580586
}
581587
db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
582588
}else{
583589
sqlite3_int64 mtime;
584590
undo_save(zFile);
585591
blob_write_to_file(&record, zFull);
586592
file_setexe(zFull, isExe);
587
- printf("REVERTED: %s\n", zFile);
593
+ fossil_print("REVERTED: %s\n", zFile);
588594
mtime = file_mtime(zFull);
589595
db_multi_exec(
590596
"UPDATE vfile"
591597
" SET mtime=%lld, chnged=0, deleted=0, isexe=%d, mrid=rid,"
592598
" pathname=coalesce(origname,pathname), origname=NULL"
593599
--- src/update.c
+++ src/update.c
@@ -175,13 +175,18 @@
175 }
176 }
177 tid = db_int(0, "SELECT rid FROM leaves, event"
178 " WHERE event.objid=leaves.rid"
179 " ORDER BY event.mtime DESC");
 
 
 
 
 
180 }
181
182 if( !verboseFlag && (tid==vid)) return; /* Nothing to update */
183 db_begin_transaction();
184 vfile_check_signature(vid, 1, 0);
185 if( !nochangeFlag && !internalUpdate ) undo_begin();
186 load_vfile_from_rid(tid);
187
@@ -253,18 +258,18 @@
253 if( debugFlag ){
254 db_prepare(&q,
255 "SELECT rowid, fn, fnt, chnged, ridv, ridt, isexe FROM fv"
256 );
257 while( db_step(&q)==SQLITE_ROW ){
258 printf("%3d: ridv=%-4d ridt=%-4d chnged=%d isexe=%d\n",
259 db_column_int(&q, 0),
260 db_column_int(&q, 4),
261 db_column_int(&q, 5),
262 db_column_int(&q, 3),
263 db_column_int(&q, 6));
264 printf(" fnv = [%s]\n", db_column_text(&q, 1));
265 printf(" fnt = [%s]\n", db_column_text(&q, 2));
266 }
267 db_finalize(&q);
268 }
269
270 /* If FILES appear on the command-line, remove from the "fv" table
@@ -331,26 +336,26 @@
331 nameChng = fossil_strcmp(zName, zNewName);
332 if( idv>0 && ridv==0 && idt>0 && ridt>0 ){
333 /* Conflict. This file has been added to the current checkout
334 ** but also exists in the target checkout. Use the current version.
335 */
336 printf("CONFLICT %s\n", zName);
337 nConflict++;
338 }else if( idt>0 && idv==0 ){
339 /* File added in the target. */
340 printf("ADD %s\n", zName);
341 undo_save(zName);
342 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
343 }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
344 /* The file is unedited. Change it to the target version */
345 undo_save(zName);
346 printf("UPDATE %s\n", zName);
347 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
348 }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
349 /* The file missing from the local check-out. Restore it to the
350 ** version that appears in the target. */
351 printf("UPDATE %s\n", zName);
352 undo_save(zName);
353 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
354 }else if( idt==0 && idv>0 ){
355 if( ridv==0 ){
356 /* Added in current checkout. Continue to hold the file as
@@ -357,25 +362,26 @@
357 ** as an addition */
358 db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
359 }else if( chnged ){
360 /* Edited locally but deleted from the target. Do not track the
361 ** file but keep the edited version around. */
362 printf("CONFLICT %s - edited locally but deleted by update\n", zName);
 
363 nConflict++;
364 }else{
365 printf("REMOVE %s\n", zName);
366 undo_save(zName);
367 if( !nochangeFlag ) unlink(zFullPath);
368 }
369 }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
370 /* Merge the changes in the current tree into the target version */
371 Blob r, t, v;
372 int rc;
373 if( nameChng ){
374 printf("MERGE %s -> %s\n", zName, zNewName);
375 }else{
376 printf("MERGE %s\n", zName);
377 }
378 undo_save(zName);
379 content_get(ridt, &t);
380 content_get(ridv, &v);
381 rc = merge_3way(&v, zFullPath, &t, &r);
@@ -383,51 +389,51 @@
383 if( !nochangeFlag ){
384 blob_write_to_file(&r, zFullNewPath);
385 file_setexe(zFullNewPath, isexe);
386 }
387 if( rc>0 ){
388 printf("***** %d merge conflicts in %s\n", rc, zNewName);
389 nConflict++;
390 }
391 }else{
392 if( !nochangeFlag ){
393 blob_write_to_file(&t, zFullNewPath);
394 file_setexe(zFullNewPath, isexe);
395 }
396 printf("***** Cannot merge binary file %s\n", zNewName);
397 nConflict++;
398 }
399 if( nameChng && !nochangeFlag ) unlink(zFullPath);
400 blob_reset(&v);
401 blob_reset(&t);
402 blob_reset(&r);
403 }else{
404 if( chnged ){
405 if( verboseFlag ) printf("EDITED %s\n", zName);
406 }else{
407 db_bind_int(&mtimeXfer, ":idv", idv);
408 db_bind_int(&mtimeXfer, ":idt", idt);
409 db_step(&mtimeXfer);
410 db_reset(&mtimeXfer);
411 if( verboseFlag ) printf("UNCHANGED %s\n", zName);
412 }
413 }
414 free(zFullPath);
415 free(zFullNewPath);
416 }
417 db_finalize(&q);
418 db_finalize(&mtimeXfer);
419 printf("--------------\n");
420 show_common_info(tid, "updated-to:", 1, 0);
421
422 /* Report on conflicts
423 */
424 if( nConflict && !nochangeFlag ){
425 if( internalUpdate ){
426 internalConflictCnt = nConflict;
427 }else{
428 printf("WARNING: %d merge conflicts - see messages above for details.\n",
429 nConflict);
430 }
431 }
432
433 /*
@@ -570,23 +576,23 @@
570 zFile = db_column_text(&q, 0);
571 zFull = mprintf("%/%/", g.zLocalRoot, zFile);
572 errCode = historical_version_of_file(zRevision, zFile, &record, &isExe,2);
573 if( errCode==2 ){
574 if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){
575 printf("UNMANAGE: %s\n", zFile);
576 }else{
577 undo_save(zFile);
578 unlink(zFull);
579 printf("DELETE: %s\n", zFile);
580 }
581 db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
582 }else{
583 sqlite3_int64 mtime;
584 undo_save(zFile);
585 blob_write_to_file(&record, zFull);
586 file_setexe(zFull, isExe);
587 printf("REVERTED: %s\n", zFile);
588 mtime = file_mtime(zFull);
589 db_multi_exec(
590 "UPDATE vfile"
591 " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, mrid=rid,"
592 " pathname=coalesce(origname,pathname), origname=NULL"
593
--- src/update.c
+++ src/update.c
@@ -175,13 +175,18 @@
175 }
176 }
177 tid = db_int(0, "SELECT rid FROM leaves, event"
178 " WHERE event.objid=leaves.rid"
179 " ORDER BY event.mtime DESC");
180 if( tid==0 ) tid = vid;
181 }
182
183 if( tid==0 ){
184 fossil_panic("Internal Error: unable to find a version to update to.");
185 }
186
187 if( tid==vid && !verboseFlag ) return; /* Nothing to update */
188 db_begin_transaction();
189 vfile_check_signature(vid, 1, 0);
190 if( !nochangeFlag && !internalUpdate ) undo_begin();
191 load_vfile_from_rid(tid);
192
@@ -253,18 +258,18 @@
258 if( debugFlag ){
259 db_prepare(&q,
260 "SELECT rowid, fn, fnt, chnged, ridv, ridt, isexe FROM fv"
261 );
262 while( db_step(&q)==SQLITE_ROW ){
263 fossil_print("%3d: ridv=%-4d ridt=%-4d chnged=%d isexe=%d\n",
264 db_column_int(&q, 0),
265 db_column_int(&q, 4),
266 db_column_int(&q, 5),
267 db_column_int(&q, 3),
268 db_column_int(&q, 6));
269 fossil_print(" fnv = [%s]\n", db_column_text(&q, 1));
270 fossil_print(" fnt = [%s]\n", db_column_text(&q, 2));
271 }
272 db_finalize(&q);
273 }
274
275 /* If FILES appear on the command-line, remove from the "fv" table
@@ -331,26 +336,26 @@
336 nameChng = fossil_strcmp(zName, zNewName);
337 if( idv>0 && ridv==0 && idt>0 && ridt>0 ){
338 /* Conflict. This file has been added to the current checkout
339 ** but also exists in the target checkout. Use the current version.
340 */
341 fossil_print("CONFLICT %s\n", zName);
342 nConflict++;
343 }else if( idt>0 && idv==0 ){
344 /* File added in the target. */
345 fossil_print("ADD %s\n", zName);
346 undo_save(zName);
347 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
348 }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
349 /* The file is unedited. Change it to the target version */
350 undo_save(zName);
351 fossil_print("UPDATE %s\n", zName);
352 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
353 }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
354 /* The file missing from the local check-out. Restore it to the
355 ** version that appears in the target. */
356 fossil_print("UPDATE %s\n", zName);
357 undo_save(zName);
358 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
359 }else if( idt==0 && idv>0 ){
360 if( ridv==0 ){
361 /* Added in current checkout. Continue to hold the file as
@@ -357,25 +362,26 @@
362 ** as an addition */
363 db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
364 }else if( chnged ){
365 /* Edited locally but deleted from the target. Do not track the
366 ** file but keep the edited version around. */
367 fossil_print("CONFLICT %s - edited locally but deleted by update\n",
368 zName);
369 nConflict++;
370 }else{
371 fossil_print("REMOVE %s\n", zName);
372 undo_save(zName);
373 if( !nochangeFlag ) file_delete(zFullPath);
374 }
375 }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
376 /* Merge the changes in the current tree into the target version */
377 Blob r, t, v;
378 int rc;
379 if( nameChng ){
380 fossil_print("MERGE %s -> %s\n", zName, zNewName);
381 }else{
382 fossil_print("MERGE %s\n", zName);
383 }
384 undo_save(zName);
385 content_get(ridt, &t);
386 content_get(ridv, &v);
387 rc = merge_3way(&v, zFullPath, &t, &r);
@@ -383,51 +389,51 @@
389 if( !nochangeFlag ){
390 blob_write_to_file(&r, zFullNewPath);
391 file_setexe(zFullNewPath, isexe);
392 }
393 if( rc>0 ){
394 fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
395 nConflict++;
396 }
397 }else{
398 if( !nochangeFlag ){
399 blob_write_to_file(&t, zFullNewPath);
400 file_setexe(zFullNewPath, isexe);
401 }
402 fossil_print("***** Cannot merge binary file %s\n", zNewName);
403 nConflict++;
404 }
405 if( nameChng && !nochangeFlag ) file_delete(zFullPath);
406 blob_reset(&v);
407 blob_reset(&t);
408 blob_reset(&r);
409 }else{
410 if( chnged ){
411 if( verboseFlag ) fossil_print("EDITED %s\n", zName);
412 }else{
413 db_bind_int(&mtimeXfer, ":idv", idv);
414 db_bind_int(&mtimeXfer, ":idt", idt);
415 db_step(&mtimeXfer);
416 db_reset(&mtimeXfer);
417 if( verboseFlag ) fossil_print("UNCHANGED %s\n", zName);
418 }
419 }
420 free(zFullPath);
421 free(zFullNewPath);
422 }
423 db_finalize(&q);
424 db_finalize(&mtimeXfer);
425 fossil_print("--------------\n");
426 show_common_info(tid, "updated-to:", 1, 0);
427
428 /* Report on conflicts
429 */
430 if( nConflict && !nochangeFlag ){
431 if( internalUpdate ){
432 internalConflictCnt = nConflict;
433 }else{
434 fossil_print("WARNING: %d merge conflicts - see messages above for details.\n",
435 nConflict);
436 }
437 }
438
439 /*
@@ -570,23 +576,23 @@
576 zFile = db_column_text(&q, 0);
577 zFull = mprintf("%/%/", g.zLocalRoot, zFile);
578 errCode = historical_version_of_file(zRevision, zFile, &record, &isExe,2);
579 if( errCode==2 ){
580 if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){
581 fossil_print("UNMANAGE: %s\n", zFile);
582 }else{
583 undo_save(zFile);
584 file_delete(zFull);
585 fossil_print("DELETE: %s\n", zFile);
586 }
587 db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
588 }else{
589 sqlite3_int64 mtime;
590 undo_save(zFile);
591 blob_write_to_file(&record, zFull);
592 file_setexe(zFull, isExe);
593 fossil_print("REVERTED: %s\n", zFile);
594 mtime = file_mtime(zFull);
595 db_multi_exec(
596 "UPDATE vfile"
597 " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, mrid=rid,"
598 " pathname=coalesce(origname,pathname), origname=NULL"
599
+15 -15
--- src/url.c
+++ src/url.c
@@ -208,26 +208,26 @@
208208
if( g.argc!=3 && g.argc!=4 ){
209209
usage("URL");
210210
}
211211
url_parse(g.argv[2]);
212212
for(i=0; i<2; i++){
213
- printf("g.urlIsFile = %d\n", g.urlIsFile);
214
- printf("g.urlIsHttps = %d\n", g.urlIsHttps);
215
- printf("g.urlIsSsh = %d\n", g.urlIsSsh);
216
- printf("g.urlProtocol = %s\n", g.urlProtocol);
217
- printf("g.urlName = %s\n", g.urlName);
218
- printf("g.urlPort = %d\n", g.urlPort);
219
- printf("g.urlDfltPort = %d\n", g.urlDfltPort);
220
- printf("g.urlHostname = %s\n", g.urlHostname);
221
- printf("g.urlPath = %s\n", g.urlPath);
222
- printf("g.urlUser = %s\n", g.urlUser);
223
- printf("g.urlPasswd = %s\n", g.urlPasswd);
224
- printf("g.urlCanonical = %s\n", g.urlCanonical);
225
- printf("g.urlFossil = %s\n", g.urlFossil);
213
+ fossil_print("g.urlIsFile = %d\n", g.urlIsFile);
214
+ fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps);
215
+ fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh);
216
+ fossil_print("g.urlProtocol = %s\n", g.urlProtocol);
217
+ fossil_print("g.urlName = %s\n", g.urlName);
218
+ fossil_print("g.urlPort = %d\n", g.urlPort);
219
+ fossil_print("g.urlDfltPort = %d\n", g.urlDfltPort);
220
+ fossil_print("g.urlHostname = %s\n", g.urlHostname);
221
+ fossil_print("g.urlPath = %s\n", g.urlPath);
222
+ fossil_print("g.urlUser = %s\n", g.urlUser);
223
+ fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
224
+ fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
225
+ fossil_print("g.urlFossil = %s\n", g.urlFossil);
226226
if( g.urlIsFile || g.urlIsSsh ) break;
227227
if( i==0 ){
228
- printf("********\n");
228
+ fossil_print("********\n");
229229
url_enable_proxy("Using proxy: ");
230230
}
231231
}
232232
}
233233
@@ -276,11 +276,11 @@
276276
char *zOriginalUser = g.urlUser;
277277
char *zOriginalPasswd = g.urlPasswd;
278278
g.urlUser = 0;
279279
g.urlPasswd = "";
280280
url_parse(zProxy);
281
- if( zMsg ) printf("%s%s\n", zMsg, g.urlCanonical);
281
+ if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
282282
g.urlPath = zOriginalUrl;
283283
g.urlHostname = zOriginalHost;
284284
if( g.urlUser ){
285285
char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
286286
char *zCredentials2 = encode64(zCredentials1, -1);
287287
--- src/url.c
+++ src/url.c
@@ -208,26 +208,26 @@
208 if( g.argc!=3 && g.argc!=4 ){
209 usage("URL");
210 }
211 url_parse(g.argv[2]);
212 for(i=0; i<2; i++){
213 printf("g.urlIsFile = %d\n", g.urlIsFile);
214 printf("g.urlIsHttps = %d\n", g.urlIsHttps);
215 printf("g.urlIsSsh = %d\n", g.urlIsSsh);
216 printf("g.urlProtocol = %s\n", g.urlProtocol);
217 printf("g.urlName = %s\n", g.urlName);
218 printf("g.urlPort = %d\n", g.urlPort);
219 printf("g.urlDfltPort = %d\n", g.urlDfltPort);
220 printf("g.urlHostname = %s\n", g.urlHostname);
221 printf("g.urlPath = %s\n", g.urlPath);
222 printf("g.urlUser = %s\n", g.urlUser);
223 printf("g.urlPasswd = %s\n", g.urlPasswd);
224 printf("g.urlCanonical = %s\n", g.urlCanonical);
225 printf("g.urlFossil = %s\n", g.urlFossil);
226 if( g.urlIsFile || g.urlIsSsh ) break;
227 if( i==0 ){
228 printf("********\n");
229 url_enable_proxy("Using proxy: ");
230 }
231 }
232 }
233
@@ -276,11 +276,11 @@
276 char *zOriginalUser = g.urlUser;
277 char *zOriginalPasswd = g.urlPasswd;
278 g.urlUser = 0;
279 g.urlPasswd = "";
280 url_parse(zProxy);
281 if( zMsg ) printf("%s%s\n", zMsg, g.urlCanonical);
282 g.urlPath = zOriginalUrl;
283 g.urlHostname = zOriginalHost;
284 if( g.urlUser ){
285 char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
286 char *zCredentials2 = encode64(zCredentials1, -1);
287
--- src/url.c
+++ src/url.c
@@ -208,26 +208,26 @@
208 if( g.argc!=3 && g.argc!=4 ){
209 usage("URL");
210 }
211 url_parse(g.argv[2]);
212 for(i=0; i<2; i++){
213 fossil_print("g.urlIsFile = %d\n", g.urlIsFile);
214 fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps);
215 fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh);
216 fossil_print("g.urlProtocol = %s\n", g.urlProtocol);
217 fossil_print("g.urlName = %s\n", g.urlName);
218 fossil_print("g.urlPort = %d\n", g.urlPort);
219 fossil_print("g.urlDfltPort = %d\n", g.urlDfltPort);
220 fossil_print("g.urlHostname = %s\n", g.urlHostname);
221 fossil_print("g.urlPath = %s\n", g.urlPath);
222 fossil_print("g.urlUser = %s\n", g.urlUser);
223 fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
224 fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
225 fossil_print("g.urlFossil = %s\n", g.urlFossil);
226 if( g.urlIsFile || g.urlIsSsh ) break;
227 if( i==0 ){
228 fossil_print("********\n");
229 url_enable_proxy("Using proxy: ");
230 }
231 }
232 }
233
@@ -276,11 +276,11 @@
276 char *zOriginalUser = g.urlUser;
277 char *zOriginalPasswd = g.urlPasswd;
278 g.urlUser = 0;
279 g.urlPasswd = "";
280 url_parse(zProxy);
281 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
282 g.urlPath = zOriginalUrl;
283 g.urlHostname = zOriginalHost;
284 if( g.urlUser ){
285 char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
286 char *zCredentials2 = encode64(zCredentials1, -1);
287
+15 -14
--- src/user.c
+++ src/user.c
@@ -117,11 +117,11 @@
117117
prompt_for_passphrase(zPrompt, pPassphrase);
118118
if( verify==0 ) break;
119119
if( verify==1 && blob_size(pPassphrase)==0 ) break;
120120
prompt_for_passphrase("Retype new password: ", &secondTry);
121121
if( blob_compare(pPassphrase, &secondTry) ){
122
- printf("Passphrases do not match. Try again...\n");
122
+ fossil_print("Passphrases do not match. Try again...\n");
123123
}else{
124124
break;
125125
}
126126
}
127127
blob_reset(&secondTry);
@@ -132,11 +132,11 @@
132132
*/
133133
void prompt_user(const char *zPrompt, Blob *pIn){
134134
char *z;
135135
char zLine[1000];
136136
blob_zero(pIn);
137
- printf("%s", zPrompt);
137
+ fossil_print("%s", zPrompt);
138138
fflush(stdout);
139139
z = fgets(zLine, sizeof(zLine), stdin);
140140
if( z ){
141141
strip_string(pIn, z);
142142
}
@@ -204,19 +204,19 @@
204204
}else{
205205
prompt_for_password("password: ", &passwd, 1);
206206
}
207207
zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
208208
db_multi_exec(
209
- "INSERT INTO user(login,pw,cap,info)"
210
- "VALUES(%B,%Q,%B,%B)",
209
+ "INSERT INTO user(login,pw,cap,info,mtime)"
210
+ "VALUES(%B,%Q,%B,%B,now())",
211211
&login, zPw, &caps, &contact
212212
);
213213
free(zPw);
214214
}else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){
215215
user_select();
216216
if( g.argc==3 ){
217
- printf("%s\n", g.zLogin);
217
+ fossil_print("%s\n", g.zLogin);
218218
}else{
219219
if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.argv[3]) ){
220220
fossil_fatal("no such user: %s", g.argv[3]);
221221
}
222222
if( g.localOpen ){
@@ -227,11 +227,11 @@
227227
}
228228
}else if( n>=2 && strncmp(g.argv[2],"list",n)==0 ){
229229
Stmt q;
230230
db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
231231
while( db_step(&q)==SQLITE_ROW ){
232
- printf("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
232
+ fossil_print("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
233233
}
234234
db_finalize(&q);
235235
}else if( n>=2 && strncmp(g.argv[2],"password",2)==0 ){
236236
char *zPrompt;
237237
int uid;
@@ -246,14 +246,15 @@
246246
}else{
247247
zPrompt = mprintf("New password for %s: ", g.argv[3]);
248248
prompt_for_password(zPrompt, &pw, 1);
249249
}
250250
if( blob_size(&pw)==0 ){
251
- printf("password unchanged\n");
251
+ fossil_print("password unchanged\n");
252252
}else{
253253
char *zSecret = sha1_shared_secret(blob_str(&pw), g.argv[3], 0);
254
- db_multi_exec("UPDATE user SET pw=%Q WHERE uid=%d", zSecret, uid);
254
+ db_multi_exec("UPDATE user SET pw=%Q, mtime=now() WHERE uid=%d",
255
+ zSecret, uid);
255256
free(zSecret);
256257
}
257258
}else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
258259
int uid;
259260
if( g.argc!=4 && g.argc!=5 ){
@@ -263,15 +264,15 @@
263264
if( uid==0 ){
264265
fossil_fatal("no such user: %s", g.argv[3]);
265266
}
266267
if( g.argc==5 ){
267268
db_multi_exec(
268
- "UPDATE user SET cap=%Q WHERE uid=%d", g.argv[4],
269
- uid
269
+ "UPDATE user SET cap=%Q, mtime=now() WHERE uid=%d",
270
+ g.argv[4], uid
270271
);
271272
}
272
- printf("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
273
+ fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
273274
}else{
274275
fossil_panic("user subcommand should be one of: "
275276
"capabilities default list new password");
276277
}
277278
}
@@ -340,12 +341,12 @@
340341
db_finalize(&s);
341342
}
342343
343344
if( g.userUid==0 ){
344345
db_multi_exec(
345
- "INSERT INTO user(login, pw, cap, info)"
346
- "VALUES('anonymous', '', 'cfghjkmnoqw', '')"
346
+ "INSERT INTO user(login, pw, cap, info, mtime)"
347
+ "VALUES('anonymous', '', 'cfghjkmnoqw', '', now())"
347348
);
348349
g.userUid = db_last_insert_rowid();
349350
g.zLogin = "anonymous";
350351
}
351352
}
@@ -364,11 +365,11 @@
364365
if( g.argc!=3 ) usage("REPOSITORY");
365366
db_open_repository(g.argv[2]);
366367
sqlite3_create_function(g.db, "shared_secret", 2, SQLITE_UTF8, 0,
367368
sha1_shared_secret_sql_function, 0, 0);
368369
db_multi_exec(
369
- "UPDATE user SET pw=shared_secret(pw,login)"
370
+ "UPDATE user SET pw=shared_secret(pw,login), mtime=now()"
370371
" WHERE length(pw)>0 AND length(pw)!=40"
371372
);
372373
}
373374
374375
/*
375376
--- src/user.c
+++ src/user.c
@@ -117,11 +117,11 @@
117 prompt_for_passphrase(zPrompt, pPassphrase);
118 if( verify==0 ) break;
119 if( verify==1 && blob_size(pPassphrase)==0 ) break;
120 prompt_for_passphrase("Retype new password: ", &secondTry);
121 if( blob_compare(pPassphrase, &secondTry) ){
122 printf("Passphrases do not match. Try again...\n");
123 }else{
124 break;
125 }
126 }
127 blob_reset(&secondTry);
@@ -132,11 +132,11 @@
132 */
133 void prompt_user(const char *zPrompt, Blob *pIn){
134 char *z;
135 char zLine[1000];
136 blob_zero(pIn);
137 printf("%s", zPrompt);
138 fflush(stdout);
139 z = fgets(zLine, sizeof(zLine), stdin);
140 if( z ){
141 strip_string(pIn, z);
142 }
@@ -204,19 +204,19 @@
204 }else{
205 prompt_for_password("password: ", &passwd, 1);
206 }
207 zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
208 db_multi_exec(
209 "INSERT INTO user(login,pw,cap,info)"
210 "VALUES(%B,%Q,%B,%B)",
211 &login, zPw, &caps, &contact
212 );
213 free(zPw);
214 }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){
215 user_select();
216 if( g.argc==3 ){
217 printf("%s\n", g.zLogin);
218 }else{
219 if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.argv[3]) ){
220 fossil_fatal("no such user: %s", g.argv[3]);
221 }
222 if( g.localOpen ){
@@ -227,11 +227,11 @@
227 }
228 }else if( n>=2 && strncmp(g.argv[2],"list",n)==0 ){
229 Stmt q;
230 db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
231 while( db_step(&q)==SQLITE_ROW ){
232 printf("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
233 }
234 db_finalize(&q);
235 }else if( n>=2 && strncmp(g.argv[2],"password",2)==0 ){
236 char *zPrompt;
237 int uid;
@@ -246,14 +246,15 @@
246 }else{
247 zPrompt = mprintf("New password for %s: ", g.argv[3]);
248 prompt_for_password(zPrompt, &pw, 1);
249 }
250 if( blob_size(&pw)==0 ){
251 printf("password unchanged\n");
252 }else{
253 char *zSecret = sha1_shared_secret(blob_str(&pw), g.argv[3], 0);
254 db_multi_exec("UPDATE user SET pw=%Q WHERE uid=%d", zSecret, uid);
 
255 free(zSecret);
256 }
257 }else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
258 int uid;
259 if( g.argc!=4 && g.argc!=5 ){
@@ -263,15 +264,15 @@
263 if( uid==0 ){
264 fossil_fatal("no such user: %s", g.argv[3]);
265 }
266 if( g.argc==5 ){
267 db_multi_exec(
268 "UPDATE user SET cap=%Q WHERE uid=%d", g.argv[4],
269 uid
270 );
271 }
272 printf("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
273 }else{
274 fossil_panic("user subcommand should be one of: "
275 "capabilities default list new password");
276 }
277 }
@@ -340,12 +341,12 @@
340 db_finalize(&s);
341 }
342
343 if( g.userUid==0 ){
344 db_multi_exec(
345 "INSERT INTO user(login, pw, cap, info)"
346 "VALUES('anonymous', '', 'cfghjkmnoqw', '')"
347 );
348 g.userUid = db_last_insert_rowid();
349 g.zLogin = "anonymous";
350 }
351 }
@@ -364,11 +365,11 @@
364 if( g.argc!=3 ) usage("REPOSITORY");
365 db_open_repository(g.argv[2]);
366 sqlite3_create_function(g.db, "shared_secret", 2, SQLITE_UTF8, 0,
367 sha1_shared_secret_sql_function, 0, 0);
368 db_multi_exec(
369 "UPDATE user SET pw=shared_secret(pw,login)"
370 " WHERE length(pw)>0 AND length(pw)!=40"
371 );
372 }
373
374 /*
375
--- src/user.c
+++ src/user.c
@@ -117,11 +117,11 @@
117 prompt_for_passphrase(zPrompt, pPassphrase);
118 if( verify==0 ) break;
119 if( verify==1 && blob_size(pPassphrase)==0 ) break;
120 prompt_for_passphrase("Retype new password: ", &secondTry);
121 if( blob_compare(pPassphrase, &secondTry) ){
122 fossil_print("Passphrases do not match. Try again...\n");
123 }else{
124 break;
125 }
126 }
127 blob_reset(&secondTry);
@@ -132,11 +132,11 @@
132 */
133 void prompt_user(const char *zPrompt, Blob *pIn){
134 char *z;
135 char zLine[1000];
136 blob_zero(pIn);
137 fossil_print("%s", zPrompt);
138 fflush(stdout);
139 z = fgets(zLine, sizeof(zLine), stdin);
140 if( z ){
141 strip_string(pIn, z);
142 }
@@ -204,19 +204,19 @@
204 }else{
205 prompt_for_password("password: ", &passwd, 1);
206 }
207 zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
208 db_multi_exec(
209 "INSERT INTO user(login,pw,cap,info,mtime)"
210 "VALUES(%B,%Q,%B,%B,now())",
211 &login, zPw, &caps, &contact
212 );
213 free(zPw);
214 }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){
215 user_select();
216 if( g.argc==3 ){
217 fossil_print("%s\n", g.zLogin);
218 }else{
219 if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.argv[3]) ){
220 fossil_fatal("no such user: %s", g.argv[3]);
221 }
222 if( g.localOpen ){
@@ -227,11 +227,11 @@
227 }
228 }else if( n>=2 && strncmp(g.argv[2],"list",n)==0 ){
229 Stmt q;
230 db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
231 while( db_step(&q)==SQLITE_ROW ){
232 fossil_print("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
233 }
234 db_finalize(&q);
235 }else if( n>=2 && strncmp(g.argv[2],"password",2)==0 ){
236 char *zPrompt;
237 int uid;
@@ -246,14 +246,15 @@
246 }else{
247 zPrompt = mprintf("New password for %s: ", g.argv[3]);
248 prompt_for_password(zPrompt, &pw, 1);
249 }
250 if( blob_size(&pw)==0 ){
251 fossil_print("password unchanged\n");
252 }else{
253 char *zSecret = sha1_shared_secret(blob_str(&pw), g.argv[3], 0);
254 db_multi_exec("UPDATE user SET pw=%Q, mtime=now() WHERE uid=%d",
255 zSecret, uid);
256 free(zSecret);
257 }
258 }else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
259 int uid;
260 if( g.argc!=4 && g.argc!=5 ){
@@ -263,15 +264,15 @@
264 if( uid==0 ){
265 fossil_fatal("no such user: %s", g.argv[3]);
266 }
267 if( g.argc==5 ){
268 db_multi_exec(
269 "UPDATE user SET cap=%Q, mtime=now() WHERE uid=%d",
270 g.argv[4], uid
271 );
272 }
273 fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
274 }else{
275 fossil_panic("user subcommand should be one of: "
276 "capabilities default list new password");
277 }
278 }
@@ -340,12 +341,12 @@
341 db_finalize(&s);
342 }
343
344 if( g.userUid==0 ){
345 db_multi_exec(
346 "INSERT INTO user(login, pw, cap, info, mtime)"
347 "VALUES('anonymous', '', 'cfghjkmnoqw', '', now())"
348 );
349 g.userUid = db_last_insert_rowid();
350 g.zLogin = "anonymous";
351 }
352 }
@@ -364,11 +365,11 @@
365 if( g.argc!=3 ) usage("REPOSITORY");
366 db_open_repository(g.argv[2]);
367 sqlite3_create_function(g.db, "shared_secret", 2, SQLITE_UTF8, 0,
368 sha1_shared_secret_sql_function, 0, 0);
369 db_multi_exec(
370 "UPDATE user SET pw=shared_secret(pw,login), mtime=now()"
371 " WHERE length(pw)>0 AND length(pw)!=40"
372 );
373 }
374
375 /*
376
+70 -15
--- src/vfile.c
+++ src/vfile.c
@@ -264,11 +264,11 @@
264264
if( cReply=='n' || cReply=='N' ){
265265
blob_reset(&content);
266266
continue;
267267
}
268268
}
269
- if( verbose ) printf("%s\n", &zName[nRepos]);
269
+ if( verbose ) fossil_print("%s\n", &zName[nRepos]);
270270
blob_write_to_file(&content, zName);
271271
file_setexe(zName, isExe);
272272
blob_reset(&content);
273273
db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
274274
file_mtime(zName), id);
@@ -286,33 +286,76 @@
286286
" WHERE vid=%d AND mrid>0", g.zLocalRoot, vid);
287287
while( db_step(&q)==SQLITE_ROW ){
288288
const char *zName;
289289
290290
zName = db_column_text(&q, 0);
291
- unlink(zName);
291
+ file_delete(zName);
292292
}
293293
db_finalize(&q);
294294
db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid);
295295
}
296
+
297
+/*
298
+** Check to see if the directory named in zPath is the top of a checkout.
299
+** In other words, check to see if directory pPath contains a file named
300
+** "_FOSSIL_" or ".fos". Return true or false.
301
+*/
302
+int vfile_top_of_checkout(const char *zPath){
303
+ char *zFile;
304
+ int fileFound = 0;
305
+
306
+ zFile = mprintf("%s/_FOSSIL_", zPath);
307
+ fileFound = file_size(zFile)>=1024;
308
+ fossil_free(zFile);
309
+ if( !fileFound ){
310
+ zFile = mprintf("%s/.fos", zPath);
311
+ fileFound = file_size(zFile)>=1024;
312
+ fossil_free(zFile);
313
+ }
314
+ return fileFound;
315
+}
316
+
296317
297318
/*
298319
** Load into table SFILE the name of every ordinary file in
299320
** the directory pPath. Omit the first nPrefix characters of
300321
** of pPath when inserting into the SFILE table.
301322
**
302323
** Subdirectories are scanned recursively.
303
-** Omit files named in VFILE.vid
324
+** Omit files named in VFILE.
325
+**
326
+** Files whose names begin with "." are omitted unless allFlag is true.
327
+**
328
+** Any files or directories that match the glob pattern pIgnore are
329
+** excluded from the scan. Name matching occurs after the first
330
+** nPrefix characters are elided from the filename.
304331
*/
305
-void vfile_scan(int vid, Blob *pPath, int nPrefix, int allFlag){
332
+void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){
306333
DIR *d;
307334
int origSize;
308335
const char *zDir;
309336
struct dirent *pEntry;
310
- static const char *zSql = "SELECT 1 FROM vfile "
311
- " WHERE pathname=%Q AND NOT deleted";
337
+ int skipAll = 0;
338
+ static Stmt ins;
339
+ static int depth = 0;
312340
313341
origSize = blob_size(pPath);
342
+ if( pIgnore ){
343
+ blob_appendf(pPath, "/");
344
+ if( glob_match(pIgnore, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
345
+ blob_resize(pPath, origSize);
346
+ }
347
+ if( skipAll ) return;
348
+
349
+ if( depth==0 ){
350
+ db_prepare(&ins,
351
+ "INSERT OR IGNORE INTO sfile(x) SELECT :file"
352
+ " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=:file)"
353
+ );
354
+ }
355
+ depth++;
356
+
314357
zDir = blob_str(pPath);
315358
d = opendir(zDir);
316359
if( d ){
317360
while( (pEntry=readdir(d))!=0 ){
318361
char *zPath;
@@ -321,19 +364,30 @@
321364
if( pEntry->d_name[1]==0 ) continue;
322365
if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
323366
}
324367
blob_appendf(pPath, "/%s", pEntry->d_name);
325368
zPath = blob_str(pPath);
326
- if( file_isdir(zPath)==1 ){
327
- vfile_scan(vid, pPath, nPrefix, allFlag);
328
- }else if( file_isfile(zPath) && !db_exists(zSql, &zPath[nPrefix+1]) ){
329
- db_multi_exec("INSERT INTO sfile VALUES(%Q)", &zPath[nPrefix+1]);
369
+ if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
370
+ /* do nothing */
371
+ }else if( file_isdir(zPath)==1 ){
372
+ if( !vfile_top_of_checkout(zPath) ){
373
+ vfile_scan(pPath, nPrefix, allFlag, pIgnore);
374
+ }
375
+ }else if( file_isfile(zPath) ){
376
+ db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
377
+ db_step(&ins);
378
+ db_reset(&ins);
330379
}
331380
blob_resize(pPath, origSize);
332381
}
333382
closedir(d);
334383
}
384
+
385
+ depth--;
386
+ if( depth==0 ){
387
+ db_finalize(&ins);
388
+ }
335389
}
336390
337391
/*
338392
** Compute an aggregate MD5 checksum over the disk image of every
339393
** file in vid. The file names are part of the checksum. The resulting
@@ -374,11 +428,11 @@
374428
const char *zName = db_column_text(&q, 1);
375429
int isSelected = db_column_int(&q, 3);
376430
377431
if( isSelected ){
378432
md5sum_step_text(zName, -1);
379
- in = fopen(zFullpath,"rb");
433
+ in = fossil_fopen(zFullpath,"rb");
380434
if( in==0 ){
381435
md5sum_step_text(" 0\n", -1);
382436
continue;
383437
}
384438
fseek(in, 0L, SEEK_END);
@@ -437,26 +491,27 @@
437491
int rid = db_column_int(&q, 2);
438492
439493
blob_zero(&disk);
440494
rc = blob_read_from_file(&disk, zFullpath);
441495
if( rc<0 ){
442
- printf("ERROR: cannot read file [%s]\n", zFullpath);
496
+ fossil_print("ERROR: cannot read file [%s]\n", zFullpath);
443497
blob_reset(&disk);
444498
continue;
445499
}
446500
blob_zero(&repo);
447501
content_get(rid, &repo);
448502
if( blob_size(&repo)!=blob_size(&disk) ){
449
- printf("ERROR: [%s] is %d bytes on disk but %d in the repository\n",
503
+ fossil_print("ERROR: [%s] is %d bytes on disk but %d in the repository\n",
450504
zName, blob_size(&disk), blob_size(&repo));
451505
blob_reset(&disk);
452506
blob_reset(&repo);
453507
continue;
454508
}
455509
if( blob_compare(&repo, &disk) ){
456
- printf("ERROR: [%s] is different on disk compared to the repository\n",
457
- zName);
510
+ fossil_print(
511
+ "ERROR: [%s] is different on disk compared to the repository\n",
512
+ zName);
458513
}
459514
blob_reset(&disk);
460515
blob_reset(&repo);
461516
}
462517
db_finalize(&q);
463518
--- src/vfile.c
+++ src/vfile.c
@@ -264,11 +264,11 @@
264 if( cReply=='n' || cReply=='N' ){
265 blob_reset(&content);
266 continue;
267 }
268 }
269 if( verbose ) printf("%s\n", &zName[nRepos]);
270 blob_write_to_file(&content, zName);
271 file_setexe(zName, isExe);
272 blob_reset(&content);
273 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
274 file_mtime(zName), id);
@@ -286,33 +286,76 @@
286 " WHERE vid=%d AND mrid>0", g.zLocalRoot, vid);
287 while( db_step(&q)==SQLITE_ROW ){
288 const char *zName;
289
290 zName = db_column_text(&q, 0);
291 unlink(zName);
292 }
293 db_finalize(&q);
294 db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid);
295 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
297 /*
298 ** Load into table SFILE the name of every ordinary file in
299 ** the directory pPath. Omit the first nPrefix characters of
300 ** of pPath when inserting into the SFILE table.
301 **
302 ** Subdirectories are scanned recursively.
303 ** Omit files named in VFILE.vid
 
 
 
 
 
 
304 */
305 void vfile_scan(int vid, Blob *pPath, int nPrefix, int allFlag){
306 DIR *d;
307 int origSize;
308 const char *zDir;
309 struct dirent *pEntry;
310 static const char *zSql = "SELECT 1 FROM vfile "
311 " WHERE pathname=%Q AND NOT deleted";
 
312
313 origSize = blob_size(pPath);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314 zDir = blob_str(pPath);
315 d = opendir(zDir);
316 if( d ){
317 while( (pEntry=readdir(d))!=0 ){
318 char *zPath;
@@ -321,19 +364,30 @@
321 if( pEntry->d_name[1]==0 ) continue;
322 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
323 }
324 blob_appendf(pPath, "/%s", pEntry->d_name);
325 zPath = blob_str(pPath);
326 if( file_isdir(zPath)==1 ){
327 vfile_scan(vid, pPath, nPrefix, allFlag);
328 }else if( file_isfile(zPath) && !db_exists(zSql, &zPath[nPrefix+1]) ){
329 db_multi_exec("INSERT INTO sfile VALUES(%Q)", &zPath[nPrefix+1]);
 
 
 
 
 
 
330 }
331 blob_resize(pPath, origSize);
332 }
333 closedir(d);
334 }
 
 
 
 
 
335 }
336
337 /*
338 ** Compute an aggregate MD5 checksum over the disk image of every
339 ** file in vid. The file names are part of the checksum. The resulting
@@ -374,11 +428,11 @@
374 const char *zName = db_column_text(&q, 1);
375 int isSelected = db_column_int(&q, 3);
376
377 if( isSelected ){
378 md5sum_step_text(zName, -1);
379 in = fopen(zFullpath,"rb");
380 if( in==0 ){
381 md5sum_step_text(" 0\n", -1);
382 continue;
383 }
384 fseek(in, 0L, SEEK_END);
@@ -437,26 +491,27 @@
437 int rid = db_column_int(&q, 2);
438
439 blob_zero(&disk);
440 rc = blob_read_from_file(&disk, zFullpath);
441 if( rc<0 ){
442 printf("ERROR: cannot read file [%s]\n", zFullpath);
443 blob_reset(&disk);
444 continue;
445 }
446 blob_zero(&repo);
447 content_get(rid, &repo);
448 if( blob_size(&repo)!=blob_size(&disk) ){
449 printf("ERROR: [%s] is %d bytes on disk but %d in the repository\n",
450 zName, blob_size(&disk), blob_size(&repo));
451 blob_reset(&disk);
452 blob_reset(&repo);
453 continue;
454 }
455 if( blob_compare(&repo, &disk) ){
456 printf("ERROR: [%s] is different on disk compared to the repository\n",
457 zName);
 
458 }
459 blob_reset(&disk);
460 blob_reset(&repo);
461 }
462 db_finalize(&q);
463
--- src/vfile.c
+++ src/vfile.c
@@ -264,11 +264,11 @@
264 if( cReply=='n' || cReply=='N' ){
265 blob_reset(&content);
266 continue;
267 }
268 }
269 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
270 blob_write_to_file(&content, zName);
271 file_setexe(zName, isExe);
272 blob_reset(&content);
273 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
274 file_mtime(zName), id);
@@ -286,33 +286,76 @@
286 " WHERE vid=%d AND mrid>0", g.zLocalRoot, vid);
287 while( db_step(&q)==SQLITE_ROW ){
288 const char *zName;
289
290 zName = db_column_text(&q, 0);
291 file_delete(zName);
292 }
293 db_finalize(&q);
294 db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid);
295 }
296
297 /*
298 ** Check to see if the directory named in zPath is the top of a checkout.
299 ** In other words, check to see if directory pPath contains a file named
300 ** "_FOSSIL_" or ".fos". Return true or false.
301 */
302 int vfile_top_of_checkout(const char *zPath){
303 char *zFile;
304 int fileFound = 0;
305
306 zFile = mprintf("%s/_FOSSIL_", zPath);
307 fileFound = file_size(zFile)>=1024;
308 fossil_free(zFile);
309 if( !fileFound ){
310 zFile = mprintf("%s/.fos", zPath);
311 fileFound = file_size(zFile)>=1024;
312 fossil_free(zFile);
313 }
314 return fileFound;
315 }
316
317
318 /*
319 ** Load into table SFILE the name of every ordinary file in
320 ** the directory pPath. Omit the first nPrefix characters of
321 ** of pPath when inserting into the SFILE table.
322 **
323 ** Subdirectories are scanned recursively.
324 ** Omit files named in VFILE.
325 **
326 ** Files whose names begin with "." are omitted unless allFlag is true.
327 **
328 ** Any files or directories that match the glob pattern pIgnore are
329 ** excluded from the scan. Name matching occurs after the first
330 ** nPrefix characters are elided from the filename.
331 */
332 void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){
333 DIR *d;
334 int origSize;
335 const char *zDir;
336 struct dirent *pEntry;
337 int skipAll = 0;
338 static Stmt ins;
339 static int depth = 0;
340
341 origSize = blob_size(pPath);
342 if( pIgnore ){
343 blob_appendf(pPath, "/");
344 if( glob_match(pIgnore, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
345 blob_resize(pPath, origSize);
346 }
347 if( skipAll ) return;
348
349 if( depth==0 ){
350 db_prepare(&ins,
351 "INSERT OR IGNORE INTO sfile(x) SELECT :file"
352 " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=:file)"
353 );
354 }
355 depth++;
356
357 zDir = blob_str(pPath);
358 d = opendir(zDir);
359 if( d ){
360 while( (pEntry=readdir(d))!=0 ){
361 char *zPath;
@@ -321,19 +364,30 @@
364 if( pEntry->d_name[1]==0 ) continue;
365 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
366 }
367 blob_appendf(pPath, "/%s", pEntry->d_name);
368 zPath = blob_str(pPath);
369 if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
370 /* do nothing */
371 }else if( file_isdir(zPath)==1 ){
372 if( !vfile_top_of_checkout(zPath) ){
373 vfile_scan(pPath, nPrefix, allFlag, pIgnore);
374 }
375 }else if( file_isfile(zPath) ){
376 db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
377 db_step(&ins);
378 db_reset(&ins);
379 }
380 blob_resize(pPath, origSize);
381 }
382 closedir(d);
383 }
384
385 depth--;
386 if( depth==0 ){
387 db_finalize(&ins);
388 }
389 }
390
391 /*
392 ** Compute an aggregate MD5 checksum over the disk image of every
393 ** file in vid. The file names are part of the checksum. The resulting
@@ -374,11 +428,11 @@
428 const char *zName = db_column_text(&q, 1);
429 int isSelected = db_column_int(&q, 3);
430
431 if( isSelected ){
432 md5sum_step_text(zName, -1);
433 in = fossil_fopen(zFullpath,"rb");
434 if( in==0 ){
435 md5sum_step_text(" 0\n", -1);
436 continue;
437 }
438 fseek(in, 0L, SEEK_END);
@@ -437,26 +491,27 @@
491 int rid = db_column_int(&q, 2);
492
493 blob_zero(&disk);
494 rc = blob_read_from_file(&disk, zFullpath);
495 if( rc<0 ){
496 fossil_print("ERROR: cannot read file [%s]\n", zFullpath);
497 blob_reset(&disk);
498 continue;
499 }
500 blob_zero(&repo);
501 content_get(rid, &repo);
502 if( blob_size(&repo)!=blob_size(&disk) ){
503 fossil_print("ERROR: [%s] is %d bytes on disk but %d in the repository\n",
504 zName, blob_size(&disk), blob_size(&repo));
505 blob_reset(&disk);
506 blob_reset(&repo);
507 continue;
508 }
509 if( blob_compare(&repo, &disk) ){
510 fossil_print(
511 "ERROR: [%s] is different on disk compared to the repository\n",
512 zName);
513 }
514 blob_reset(&disk);
515 blob_reset(&repo);
516 }
517 db_finalize(&q);
518
+5 -5
--- src/wiki.c
+++ src/wiki.c
@@ -916,20 +916,20 @@
916916
FILE * zF;
917917
short doClose = 0;
918918
if( (1 == strlen(zFile)) && ('-'==zFile[0]) ){
919919
zF = stdout;
920920
}else{
921
- zF = fopen( zFile, "w" );
921
+ zF = fossil_fopen( zFile, "w" );
922922
doClose = zF ? 1 : 0;
923923
}
924924
if( ! zF ){
925925
fossil_fatal("wiki export could not open output file for writing.");
926926
}
927927
fprintf(zF,"%.*s\n", i, zBody);
928928
if( doClose ) fclose(zF);
929929
}else{
930
- printf("%.*s\n", i, zBody);
930
+ fossil_print("%.*s\n", i, zBody);
931931
}
932932
manifest_destroy(pWiki);
933933
return;
934934
}else
935935
if( strncmp(g.argv[2],"commit",n)==0
@@ -945,14 +945,14 @@
945945
}else{
946946
blob_read_from_file(&content, g.argv[4]);
947947
}
948948
if( g.argv[2][1]=='r' ){
949949
wiki_cmd_commit(zPageName, 1, &content);
950
- printf("Created new wiki page %s.\n", zPageName);
950
+ fossil_print("Created new wiki page %s.\n", zPageName);
951951
}else{
952952
wiki_cmd_commit(zPageName, 0, &content);
953
- printf("Updated wiki page %s.\n", zPageName);
953
+ fossil_print("Updated wiki page %s.\n", zPageName);
954954
}
955955
blob_reset(&content);
956956
}else
957957
if( strncmp(g.argv[2],"delete",n)==0 ){
958958
if( g.argc!=5 ){
@@ -966,11 +966,11 @@
966966
"SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
967967
" ORDER BY lower(tagname) /*sort*/"
968968
);
969969
while( db_step(&q)==SQLITE_ROW ){
970970
const char *zName = db_column_text(&q, 0);
971
- printf( "%s\n",zName);
971
+ fossil_print( "%s\n",zName);
972972
}
973973
db_finalize(&q);
974974
}else
975975
{
976976
goto wiki_cmd_usage;
977977
--- src/wiki.c
+++ src/wiki.c
@@ -916,20 +916,20 @@
916 FILE * zF;
917 short doClose = 0;
918 if( (1 == strlen(zFile)) && ('-'==zFile[0]) ){
919 zF = stdout;
920 }else{
921 zF = fopen( zFile, "w" );
922 doClose = zF ? 1 : 0;
923 }
924 if( ! zF ){
925 fossil_fatal("wiki export could not open output file for writing.");
926 }
927 fprintf(zF,"%.*s\n", i, zBody);
928 if( doClose ) fclose(zF);
929 }else{
930 printf("%.*s\n", i, zBody);
931 }
932 manifest_destroy(pWiki);
933 return;
934 }else
935 if( strncmp(g.argv[2],"commit",n)==0
@@ -945,14 +945,14 @@
945 }else{
946 blob_read_from_file(&content, g.argv[4]);
947 }
948 if( g.argv[2][1]=='r' ){
949 wiki_cmd_commit(zPageName, 1, &content);
950 printf("Created new wiki page %s.\n", zPageName);
951 }else{
952 wiki_cmd_commit(zPageName, 0, &content);
953 printf("Updated wiki page %s.\n", zPageName);
954 }
955 blob_reset(&content);
956 }else
957 if( strncmp(g.argv[2],"delete",n)==0 ){
958 if( g.argc!=5 ){
@@ -966,11 +966,11 @@
966 "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
967 " ORDER BY lower(tagname) /*sort*/"
968 );
969 while( db_step(&q)==SQLITE_ROW ){
970 const char *zName = db_column_text(&q, 0);
971 printf( "%s\n",zName);
972 }
973 db_finalize(&q);
974 }else
975 {
976 goto wiki_cmd_usage;
977
--- src/wiki.c
+++ src/wiki.c
@@ -916,20 +916,20 @@
916 FILE * zF;
917 short doClose = 0;
918 if( (1 == strlen(zFile)) && ('-'==zFile[0]) ){
919 zF = stdout;
920 }else{
921 zF = fossil_fopen( zFile, "w" );
922 doClose = zF ? 1 : 0;
923 }
924 if( ! zF ){
925 fossil_fatal("wiki export could not open output file for writing.");
926 }
927 fprintf(zF,"%.*s\n", i, zBody);
928 if( doClose ) fclose(zF);
929 }else{
930 fossil_print("%.*s\n", i, zBody);
931 }
932 manifest_destroy(pWiki);
933 return;
934 }else
935 if( strncmp(g.argv[2],"commit",n)==0
@@ -945,14 +945,14 @@
945 }else{
946 blob_read_from_file(&content, g.argv[4]);
947 }
948 if( g.argv[2][1]=='r' ){
949 wiki_cmd_commit(zPageName, 1, &content);
950 fossil_print("Created new wiki page %s.\n", zPageName);
951 }else{
952 wiki_cmd_commit(zPageName, 0, &content);
953 fossil_print("Updated wiki page %s.\n", zPageName);
954 }
955 blob_reset(&content);
956 }else
957 if( strncmp(g.argv[2],"delete",n)==0 ){
958 if( g.argc!=5 ){
@@ -966,11 +966,11 @@
966 "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
967 " ORDER BY lower(tagname) /*sort*/"
968 );
969 while( db_step(&q)==SQLITE_ROW ){
970 const char *zName = db_column_text(&q, 0);
971 fossil_print( "%s\n",zName);
972 }
973 db_finalize(&q);
974 }else
975 {
976 goto wiki_cmd_usage;
977
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1734,6 +1734,7 @@
17341734
break;
17351735
}
17361736
}
17371737
z += n;
17381738
}
1739
+ free(renderer.aStack);
17391740
}
17401741
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1734,6 +1734,7 @@
1734 break;
1735 }
1736 }
1737 z += n;
1738 }
 
1739 }
1740
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1734,6 +1734,7 @@
1734 break;
1735 }
1736 }
1737 z += n;
1738 }
1739 free(renderer.aStack);
1740 }
1741
+8 -8
--- src/winhttp.c
+++ src/winhttp.c
@@ -92,11 +92,11 @@
9292
wanted = find_content_length(zHdr) + (&z[4]-zHdr) - amt;
9393
break;
9494
}
9595
}
9696
if( amt>=sizeof(zHdr) ) goto end_request;
97
- out = fopen(zRequestFName, "wb");
97
+ out = fossil_fopen(zRequestFName, "wb");
9898
if( out==0 ) goto end_request;
9999
fwrite(zHdr, 1, amt, out);
100100
while( wanted>0 ){
101101
got = recv(p->s, zHdr, sizeof(zHdr), 0);
102102
if( got==SOCKET_ERROR ) goto end_request;
@@ -112,11 +112,11 @@
112112
sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
113113
fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName,
114114
inet_ntoa(p->addr.sin_addr), p->zOptions
115115
);
116116
fossil_system(zCmd);
117
- in = fopen(zReplyFName, "rb");
117
+ in = fossil_fopen(zReplyFName, "rb");
118118
if( in ){
119119
while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
120120
send(p->s, zHdr, got, 0);
121121
}
122122
}
@@ -123,12 +123,12 @@
123123
124124
end_request:
125125
if( out ) fclose(out);
126126
if( in ) fclose(in);
127127
closesocket(p->s);
128
- unlink(zRequestFName);
129
- unlink(zReplyFName);
128
+ file_delete(zRequestFName);
129
+ file_delete(zReplyFName);
130130
free(p);
131131
}
132132
133133
/*
134134
** Start a listening socket and process incoming HTTP requests on
@@ -146,11 +146,11 @@
146146
SOCKADDR_IN addr;
147147
int idCnt = 0;
148148
int iPort = mnPort;
149149
Blob options;
150150
151
- if( zStopper ) unlink(zStopper);
151
+ if( zStopper ) file_delete(zStopper);
152152
blob_zero(&options);
153153
if( zNotFound ){
154154
blob_appendf(&options, " --notfound %s", zNotFound);
155155
}
156156
if( g.useLocalauth ){
@@ -190,17 +190,17 @@
190190
fossil_fatal("unable to open listening socket on any"
191191
" port in the range %d..%d", mnPort, mxPort);
192192
}
193193
}
194194
zTempPrefix = mprintf("fossil_server_P%d_", iPort);
195
- printf("Listening for HTTP requests on TCP port %d\n", iPort);
195
+ fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
196196
if( zBrowser ){
197197
zBrowser = mprintf(zBrowser, iPort);
198
- printf("Launch webbrowser: %s\n", zBrowser);
198
+ fossil_print("Launch webbrowser: %s\n", zBrowser);
199199
fossil_system(zBrowser);
200200
}
201
- printf("Type Ctrl-C to stop the HTTP server\n");
201
+ fossil_print("Type Ctrl-C to stop the HTTP server\n");
202202
for(;;){
203203
SOCKET client;
204204
SOCKADDR_IN client_addr;
205205
HttpRequest *p;
206206
int len = sizeof(client_addr);
207207
--- src/winhttp.c
+++ src/winhttp.c
@@ -92,11 +92,11 @@
92 wanted = find_content_length(zHdr) + (&z[4]-zHdr) - amt;
93 break;
94 }
95 }
96 if( amt>=sizeof(zHdr) ) goto end_request;
97 out = fopen(zRequestFName, "wb");
98 if( out==0 ) goto end_request;
99 fwrite(zHdr, 1, amt, out);
100 while( wanted>0 ){
101 got = recv(p->s, zHdr, sizeof(zHdr), 0);
102 if( got==SOCKET_ERROR ) goto end_request;
@@ -112,11 +112,11 @@
112 sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
113 fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName,
114 inet_ntoa(p->addr.sin_addr), p->zOptions
115 );
116 fossil_system(zCmd);
117 in = fopen(zReplyFName, "rb");
118 if( in ){
119 while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
120 send(p->s, zHdr, got, 0);
121 }
122 }
@@ -123,12 +123,12 @@
123
124 end_request:
125 if( out ) fclose(out);
126 if( in ) fclose(in);
127 closesocket(p->s);
128 unlink(zRequestFName);
129 unlink(zReplyFName);
130 free(p);
131 }
132
133 /*
134 ** Start a listening socket and process incoming HTTP requests on
@@ -146,11 +146,11 @@
146 SOCKADDR_IN addr;
147 int idCnt = 0;
148 int iPort = mnPort;
149 Blob options;
150
151 if( zStopper ) unlink(zStopper);
152 blob_zero(&options);
153 if( zNotFound ){
154 blob_appendf(&options, " --notfound %s", zNotFound);
155 }
156 if( g.useLocalauth ){
@@ -190,17 +190,17 @@
190 fossil_fatal("unable to open listening socket on any"
191 " port in the range %d..%d", mnPort, mxPort);
192 }
193 }
194 zTempPrefix = mprintf("fossil_server_P%d_", iPort);
195 printf("Listening for HTTP requests on TCP port %d\n", iPort);
196 if( zBrowser ){
197 zBrowser = mprintf(zBrowser, iPort);
198 printf("Launch webbrowser: %s\n", zBrowser);
199 fossil_system(zBrowser);
200 }
201 printf("Type Ctrl-C to stop the HTTP server\n");
202 for(;;){
203 SOCKET client;
204 SOCKADDR_IN client_addr;
205 HttpRequest *p;
206 int len = sizeof(client_addr);
207
--- src/winhttp.c
+++ src/winhttp.c
@@ -92,11 +92,11 @@
92 wanted = find_content_length(zHdr) + (&z[4]-zHdr) - amt;
93 break;
94 }
95 }
96 if( amt>=sizeof(zHdr) ) goto end_request;
97 out = fossil_fopen(zRequestFName, "wb");
98 if( out==0 ) goto end_request;
99 fwrite(zHdr, 1, amt, out);
100 while( wanted>0 ){
101 got = recv(p->s, zHdr, sizeof(zHdr), 0);
102 if( got==SOCKET_ERROR ) goto end_request;
@@ -112,11 +112,11 @@
112 sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
113 fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName,
114 inet_ntoa(p->addr.sin_addr), p->zOptions
115 );
116 fossil_system(zCmd);
117 in = fossil_fopen(zReplyFName, "rb");
118 if( in ){
119 while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
120 send(p->s, zHdr, got, 0);
121 }
122 }
@@ -123,12 +123,12 @@
123
124 end_request:
125 if( out ) fclose(out);
126 if( in ) fclose(in);
127 closesocket(p->s);
128 file_delete(zRequestFName);
129 file_delete(zReplyFName);
130 free(p);
131 }
132
133 /*
134 ** Start a listening socket and process incoming HTTP requests on
@@ -146,11 +146,11 @@
146 SOCKADDR_IN addr;
147 int idCnt = 0;
148 int iPort = mnPort;
149 Blob options;
150
151 if( zStopper ) file_delete(zStopper);
152 blob_zero(&options);
153 if( zNotFound ){
154 blob_appendf(&options, " --notfound %s", zNotFound);
155 }
156 if( g.useLocalauth ){
@@ -190,17 +190,17 @@
190 fossil_fatal("unable to open listening socket on any"
191 " port in the range %d..%d", mnPort, mxPort);
192 }
193 }
194 zTempPrefix = mprintf("fossil_server_P%d_", iPort);
195 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
196 if( zBrowser ){
197 zBrowser = mprintf(zBrowser, iPort);
198 fossil_print("Launch webbrowser: %s\n", zBrowser);
199 fossil_system(zBrowser);
200 }
201 fossil_print("Type Ctrl-C to stop the HTTP server\n");
202 for(;;){
203 SOCKET client;
204 SOCKADDR_IN client_addr;
205 HttpRequest *p;
206 int len = sizeof(client_addr);
207
+53 -75
--- src/xfer.c
+++ src/xfer.c
@@ -454,11 +454,11 @@
454454
" (SELECT uuid FROM delta, blob"
455455
" WHERE delta.rid=:rid AND delta.srcid=blob.rid)"
456456
" FROM blob"
457457
" WHERE rid=:rid"
458458
" AND size>=0"
459
- " AND uuid NOT IN shun"
459
+ " AND NOT EXISTS(SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)"
460460
);
461461
db_bind_int(&q1, ":rid", rid);
462462
rc = db_step(&q1);
463463
if( rc==SQLITE_ROW ){
464464
zUuid = db_column_text(&q1, 0);
@@ -552,10 +552,13 @@
552552
defossilize(zLogin);
553553
554554
if( strcmp(zLogin, "nobody")==0 || strcmp(zLogin,"anonymous")==0 ){
555555
return 0; /* Anybody is allowed to sync as "nobody" or "anonymous" */
556556
}
557
+ if( fossil_strcmp(P("REMOTE_USER"), zLogin)==0 ){
558
+ return 0; /* Accept Basic Authorization */
559
+ }
557560
db_prepare(&q,
558561
"SELECT pw, cap, uid FROM user"
559562
" WHERE login=%Q"
560563
" AND login NOT IN ('anonymous','nobody','developer','reader')"
561564
" AND length(pw)>0",
@@ -592,11 +595,11 @@
592595
blob_reset(&combined);
593596
}
594597
if( rc==0 ){
595598
const char *zCap;
596599
zCap = db_column_text(&q, 1);
597
- login_set_capabilities(zCap);
600
+ login_set_capabilities(zCap, 0);
598601
g.userUid = db_column_int(&q, 2);
599602
g.zLogin = mprintf("%b", pLogin);
600603
g.zNonce = mprintf("%b", pNonce);
601604
}
602605
}
@@ -738,13 +741,16 @@
738741
}
739742
db_finalize(&q);
740743
}
741744
742745
/*
743
-** Send a single config card for configuration item zName
746
+** Send a single old-style config card for configuration item zName.
747
+**
748
+** This routine and the functionality it implements is scheduled for
749
+** removal on 2012-05-01.
744750
*/
745
-static void send_config_card(Xfer *pXfer, const char *zName){
751
+static void send_legacy_config_card(Xfer *pXfer, const char *zName){
746752
if( zName[0]!='@' ){
747753
Blob val;
748754
blob_zero(&val);
749755
db_blob(&val, "SELECT value FROM config WHERE name=%Q", zName);
750756
if( blob_size(&val)>0 ){
@@ -760,11 +766,10 @@
760766
blob_appendf(pXfer->pOut, "config %s %d\n%s\n", zName,
761767
blob_size(&content), blob_str(&content));
762768
blob_reset(&content);
763769
}
764770
}
765
-
766771
767772
/*
768773
** Called when there is an attempt to transfer private content to and
769774
** from a server without authorization.
770775
*/
@@ -807,10 +812,11 @@
807812
if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
808813
fossil_redirect_home();
809814
}
810815
g.zLogin = "anonymous";
811816
login_set_anon_nobody_capabilities();
817
+ login_check_credentials();
812818
memset(&xfer, 0, sizeof(xfer));
813819
blobarray_zero(xfer.aToken, count(xfer.aToken));
814820
cgi_set_content_type(g.zContentType);
815821
if( db_schema_is_outofdate() ){
816822
@ error database\sschema\sis\sout-of-date\son\sthe\sserver.
@@ -1007,11 +1013,11 @@
10071013
*/
10081014
if( blob_eq(&xfer.aToken[0], "login")
10091015
&& xfer.nToken==4
10101016
){
10111017
if( disableLogin ){
1012
- g.okRead = g.okWrite = g.okPrivate = 1;
1018
+ g.okRead = g.okWrite = g.okPrivate = g.okAdmin = 1;
10131019
}else{
10141020
if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
10151021
|| check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
10161022
){
10171023
cgi_reset_content();
@@ -1029,12 +1035,19 @@
10291035
if( blob_eq(&xfer.aToken[0], "reqconfig")
10301036
&& xfer.nToken==2
10311037
){
10321038
if( g.okRead ){
10331039
char *zName = blob_str(&xfer.aToken[1]);
1034
- if( configure_is_exportable(zName) ){
1035
- send_config_card(&xfer, zName);
1040
+ if( zName[0]=='/' ){
1041
+ /* New style configuration transfer */
1042
+ int groupMask = configure_name_to_mask(&zName[1], 0);
1043
+ if( !g.okAdmin ) groupMask &= ~CONFIGSET_USER;
1044
+ if( !g.okRdAddr ) groupMask &= ~CONFIGSET_ADDR;
1045
+ configure_send_group(xfer.pOut, groupMask, 0);
1046
+ }else if( configure_is_exportable(zName) ){
1047
+ /* Old style configuration transfer */
1048
+ send_legacy_config_card(&xfer, zName);
10361049
}
10371050
}
10381051
}else
10391052
10401053
/* config NAME SIZE \n CONTENT
@@ -1052,38 +1065,15 @@
10521065
cgi_reset_content();
10531066
@ error not\sauthorized\sto\spush\sconfiguration
10541067
nErr++;
10551068
break;
10561069
}
1057
- if( zName[0]!='@' ){
1058
- if( strcmp(zName, "logo-image")==0 ){
1059
- Stmt ins;
1060
- db_prepare(&ins,
1061
- "REPLACE INTO config(name, value) VALUES(:name, :value)"
1062
- );
1063
- db_bind_text(&ins, ":name", zName);
1064
- db_bind_blob(&ins, ":value", &content);
1065
- db_step(&ins);
1066
- db_finalize(&ins);
1067
- }else{
1068
- db_multi_exec(
1069
- "REPLACE INTO config(name,value) VALUES(%Q,%Q)",
1070
- zName, blob_str(&content)
1071
- );
1072
- }
1073
- }else{
1074
- /* Notice that we are evaluating arbitrary SQL received from the
1075
- ** client. But this can only happen if the client has authenticated
1076
- ** as an administrator, so presumably we trust the client at this
1077
- ** point.
1078
- */
1079
- if( !recvConfig ){
1080
- configure_prepare_to_receive(0);
1081
- recvConfig = 1;
1082
- }
1083
- db_multi_exec("%s", blob_str(&content));
1084
- }
1070
+ if( !recvConfig && zName[0]=='@' ){
1071
+ configure_prepare_to_receive(0);
1072
+ recvConfig = 1;
1073
+ }
1074
+ configure_receive(zName, &content, CONFIGSET_ALL);
10851075
blob_reset(&content);
10861076
blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
10871077
}else
10881078
10891079
@@ -1208,19 +1198,19 @@
12081198
** gdb fossil
12091199
** r test-xfer out.txt
12101200
*/
12111201
void cmd_test_xfer(void){
12121202
int notUsed;
1203
+ db_find_and_open_repository(0,0);
12131204
if( g.argc!=2 && g.argc!=3 ){
12141205
usage("?MESSAGEFILE?");
12151206
}
1216
- db_must_be_within_tree();
12171207
blob_zero(&g.cgiIn);
12181208
blob_read_from_file(&g.cgiIn, g.argc==2 ? "-" : g.argv[2]);
12191209
disableLogin = 1;
12201210
page_xfer();
1221
- printf("%s\n", cgi_extract_content(&notUsed));
1211
+ fossil_print("%s\n", cgi_extract_content(&notUsed));
12221212
}
12231213
12241214
/*
12251215
** Format strings for progress reporting.
12261216
*/
@@ -1354,25 +1344,32 @@
13541344
while( zName ){
13551345
blob_appendf(&send, "reqconfig %s\n", zName);
13561346
zName = configure_next_name(configRcvMask);
13571347
nCardSent++;
13581348
}
1359
- if( configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT) ){
1360
- configure_prepare_to_receive(0);
1349
+ if( (configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT))!=0
1350
+ && (configRcvMask & CONFIGSET_OLDFORMAT)!=0
1351
+ ){
1352
+ int overwrite = (configRcvMask & CONFIGSET_OVERWRITE)!=0;
1353
+ configure_prepare_to_receive(overwrite);
13611354
}
13621355
origConfigRcvMask = configRcvMask;
13631356
configRcvMask = 0;
13641357
}
13651358
13661359
/* Send configuration parameters being pushed */
13671360
if( configSendMask ){
1368
- const char *zName;
1369
- zName = configure_first_name(configSendMask);
1370
- while( zName ){
1371
- send_config_card(&xfer, zName);
1372
- zName = configure_next_name(configSendMask);
1373
- nCardSent++;
1361
+ if( configSendMask & CONFIGSET_OLDFORMAT ){
1362
+ const char *zName;
1363
+ zName = configure_first_name(configSendMask);
1364
+ while( zName ){
1365
+ send_legacy_config_card(&xfer, zName);
1366
+ zName = configure_next_name(configSendMask);
1367
+ nCardSent++;
1368
+ }
1369
+ }else{
1370
+ nCardSent += configure_send_group(xfer.pOut, configSendMask, 0);
13741371
}
13751372
configSendMask = 0;
13761373
}
13771374
13781375
/* Append randomness to the end of the message. This makes all
@@ -1393,11 +1390,11 @@
13931390
xfer.nFileSent = 0;
13941391
xfer.nDeltaSent = 0;
13951392
xfer.nGimmeSent = 0;
13961393
xfer.nIGotSent = 0;
13971394
if( !g.cgiOutput && !g.fQuiet ){
1398
- printf("waiting for server...");
1395
+ fossil_print("waiting for server...");
13991396
}
14001397
fflush(stdout);
14011398
if( http_exchange(&send, &recv, cloneFlag==0 || nCycle>0) ){
14021399
nErr++;
14031400
break;
@@ -1441,18 +1438,19 @@
14411438
fossil_warning("*** time skew *** server is slow by %s",
14421439
db_timespan_name(-rDiff));
14431440
g.clockSkewSeen = 1;
14441441
}
14451442
}
1443
+ nCardRcvd++;
14461444
continue;
14471445
}
14481446
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
14491447
nCardRcvd++;
14501448
if( !g.cgiOutput && !g.fQuiet && recv.nUsed>0 ){
14511449
pctDone = (recv.iCursor*100)/recv.nUsed;
14521450
if( pctDone!=lastPctDone ){
1453
- printf("\rprocessed: %d%% ", pctDone);
1451
+ fossil_print("\rprocessed: %d%% ", pctDone);
14541452
lastPctDone = pctDone;
14551453
fflush(stdout);
14561454
}
14571455
}
14581456
@@ -1544,44 +1542,22 @@
15441542
}else
15451543
15461544
/* config NAME SIZE \n CONTENT
15471545
**
15481546
** Receive a configuration value from the server.
1547
+ **
1548
+ ** The received configuration setting is silently ignored if it was
1549
+ ** not requested by a prior "reqconfig" sent from client to server.
15491550
*/
15501551
if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
15511552
&& blob_is_int(&xfer.aToken[2], &size) ){
15521553
const char *zName = blob_str(&xfer.aToken[1]);
15531554
Blob content;
15541555
blob_zero(&content);
15551556
blob_extract(xfer.pIn, size, &content);
15561557
g.okAdmin = g.okRdAddr = 1;
1557
- if( configure_is_exportable(zName) & origConfigRcvMask ){
1558
- if( zName[0]!='@' ){
1559
- if( strcmp(zName, "logo-image")==0 ){
1560
- Stmt ins;
1561
- db_prepare(&ins,
1562
- "REPLACE INTO config(name, value) VALUES(:name, :value)"
1563
- );
1564
- db_bind_text(&ins, ":name", zName);
1565
- db_bind_blob(&ins, ":value", &content);
1566
- db_step(&ins);
1567
- db_finalize(&ins);
1568
- }else{
1569
- db_multi_exec(
1570
- "REPLACE INTO config(name,value) VALUES(%Q,%Q)",
1571
- zName, blob_str(&content)
1572
- );
1573
- }
1574
- }else{
1575
- /* Notice that we are evaluating arbitrary SQL received from the
1576
- ** server. But this can only happen if we have specifically
1577
- ** requested configuration information from the server, so
1578
- ** presumably the operator trusts the server.
1579
- */
1580
- db_multi_exec("%s", blob_str(&content));
1581
- }
1582
- }
1558
+ configure_receive(zName, &content, origConfigRcvMask);
15831559
nCardSent++;
15841560
blob_reset(&content);
15851561
blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
15861562
}else
15871563
@@ -1691,11 +1667,13 @@
16911667
break;
16921668
}
16931669
blobarray_reset(xfer.aToken, xfer.nToken);
16941670
blob_reset(&xfer.line);
16951671
}
1696
- if( origConfigRcvMask & (CONFIGSET_TKT|CONFIGSET_USER) ){
1672
+ if( (configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT))!=0
1673
+ && (configRcvMask & CONFIGSET_OLDFORMAT)!=0
1674
+ ){
16971675
configure_finalize_receive();
16981676
}
16991677
origConfigRcvMask = 0;
17001678
if( nCardRcvd>0 ){
17011679
fossil_print(zValueFormat, "Received:",
17021680
--- src/xfer.c
+++ src/xfer.c
@@ -454,11 +454,11 @@
454 " (SELECT uuid FROM delta, blob"
455 " WHERE delta.rid=:rid AND delta.srcid=blob.rid)"
456 " FROM blob"
457 " WHERE rid=:rid"
458 " AND size>=0"
459 " AND uuid NOT IN shun"
460 );
461 db_bind_int(&q1, ":rid", rid);
462 rc = db_step(&q1);
463 if( rc==SQLITE_ROW ){
464 zUuid = db_column_text(&q1, 0);
@@ -552,10 +552,13 @@
552 defossilize(zLogin);
553
554 if( strcmp(zLogin, "nobody")==0 || strcmp(zLogin,"anonymous")==0 ){
555 return 0; /* Anybody is allowed to sync as "nobody" or "anonymous" */
556 }
 
 
 
557 db_prepare(&q,
558 "SELECT pw, cap, uid FROM user"
559 " WHERE login=%Q"
560 " AND login NOT IN ('anonymous','nobody','developer','reader')"
561 " AND length(pw)>0",
@@ -592,11 +595,11 @@
592 blob_reset(&combined);
593 }
594 if( rc==0 ){
595 const char *zCap;
596 zCap = db_column_text(&q, 1);
597 login_set_capabilities(zCap);
598 g.userUid = db_column_int(&q, 2);
599 g.zLogin = mprintf("%b", pLogin);
600 g.zNonce = mprintf("%b", pNonce);
601 }
602 }
@@ -738,13 +741,16 @@
738 }
739 db_finalize(&q);
740 }
741
742 /*
743 ** Send a single config card for configuration item zName
 
 
 
744 */
745 static void send_config_card(Xfer *pXfer, const char *zName){
746 if( zName[0]!='@' ){
747 Blob val;
748 blob_zero(&val);
749 db_blob(&val, "SELECT value FROM config WHERE name=%Q", zName);
750 if( blob_size(&val)>0 ){
@@ -760,11 +766,10 @@
760 blob_appendf(pXfer->pOut, "config %s %d\n%s\n", zName,
761 blob_size(&content), blob_str(&content));
762 blob_reset(&content);
763 }
764 }
765
766
767 /*
768 ** Called when there is an attempt to transfer private content to and
769 ** from a server without authorization.
770 */
@@ -807,10 +812,11 @@
807 if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
808 fossil_redirect_home();
809 }
810 g.zLogin = "anonymous";
811 login_set_anon_nobody_capabilities();
 
812 memset(&xfer, 0, sizeof(xfer));
813 blobarray_zero(xfer.aToken, count(xfer.aToken));
814 cgi_set_content_type(g.zContentType);
815 if( db_schema_is_outofdate() ){
816 @ error database\sschema\sis\sout-of-date\son\sthe\sserver.
@@ -1007,11 +1013,11 @@
1007 */
1008 if( blob_eq(&xfer.aToken[0], "login")
1009 && xfer.nToken==4
1010 ){
1011 if( disableLogin ){
1012 g.okRead = g.okWrite = g.okPrivate = 1;
1013 }else{
1014 if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
1015 || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
1016 ){
1017 cgi_reset_content();
@@ -1029,12 +1035,19 @@
1029 if( blob_eq(&xfer.aToken[0], "reqconfig")
1030 && xfer.nToken==2
1031 ){
1032 if( g.okRead ){
1033 char *zName = blob_str(&xfer.aToken[1]);
1034 if( configure_is_exportable(zName) ){
1035 send_config_card(&xfer, zName);
 
 
 
 
 
 
 
1036 }
1037 }
1038 }else
1039
1040 /* config NAME SIZE \n CONTENT
@@ -1052,38 +1065,15 @@
1052 cgi_reset_content();
1053 @ error not\sauthorized\sto\spush\sconfiguration
1054 nErr++;
1055 break;
1056 }
1057 if( zName[0]!='@' ){
1058 if( strcmp(zName, "logo-image")==0 ){
1059 Stmt ins;
1060 db_prepare(&ins,
1061 "REPLACE INTO config(name, value) VALUES(:name, :value)"
1062 );
1063 db_bind_text(&ins, ":name", zName);
1064 db_bind_blob(&ins, ":value", &content);
1065 db_step(&ins);
1066 db_finalize(&ins);
1067 }else{
1068 db_multi_exec(
1069 "REPLACE INTO config(name,value) VALUES(%Q,%Q)",
1070 zName, blob_str(&content)
1071 );
1072 }
1073 }else{
1074 /* Notice that we are evaluating arbitrary SQL received from the
1075 ** client. But this can only happen if the client has authenticated
1076 ** as an administrator, so presumably we trust the client at this
1077 ** point.
1078 */
1079 if( !recvConfig ){
1080 configure_prepare_to_receive(0);
1081 recvConfig = 1;
1082 }
1083 db_multi_exec("%s", blob_str(&content));
1084 }
1085 blob_reset(&content);
1086 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1087 }else
1088
1089
@@ -1208,19 +1198,19 @@
1208 ** gdb fossil
1209 ** r test-xfer out.txt
1210 */
1211 void cmd_test_xfer(void){
1212 int notUsed;
 
1213 if( g.argc!=2 && g.argc!=3 ){
1214 usage("?MESSAGEFILE?");
1215 }
1216 db_must_be_within_tree();
1217 blob_zero(&g.cgiIn);
1218 blob_read_from_file(&g.cgiIn, g.argc==2 ? "-" : g.argv[2]);
1219 disableLogin = 1;
1220 page_xfer();
1221 printf("%s\n", cgi_extract_content(&notUsed));
1222 }
1223
1224 /*
1225 ** Format strings for progress reporting.
1226 */
@@ -1354,25 +1344,32 @@
1354 while( zName ){
1355 blob_appendf(&send, "reqconfig %s\n", zName);
1356 zName = configure_next_name(configRcvMask);
1357 nCardSent++;
1358 }
1359 if( configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT) ){
1360 configure_prepare_to_receive(0);
 
 
 
1361 }
1362 origConfigRcvMask = configRcvMask;
1363 configRcvMask = 0;
1364 }
1365
1366 /* Send configuration parameters being pushed */
1367 if( configSendMask ){
1368 const char *zName;
1369 zName = configure_first_name(configSendMask);
1370 while( zName ){
1371 send_config_card(&xfer, zName);
1372 zName = configure_next_name(configSendMask);
1373 nCardSent++;
 
 
 
 
1374 }
1375 configSendMask = 0;
1376 }
1377
1378 /* Append randomness to the end of the message. This makes all
@@ -1393,11 +1390,11 @@
1393 xfer.nFileSent = 0;
1394 xfer.nDeltaSent = 0;
1395 xfer.nGimmeSent = 0;
1396 xfer.nIGotSent = 0;
1397 if( !g.cgiOutput && !g.fQuiet ){
1398 printf("waiting for server...");
1399 }
1400 fflush(stdout);
1401 if( http_exchange(&send, &recv, cloneFlag==0 || nCycle>0) ){
1402 nErr++;
1403 break;
@@ -1441,18 +1438,19 @@
1441 fossil_warning("*** time skew *** server is slow by %s",
1442 db_timespan_name(-rDiff));
1443 g.clockSkewSeen = 1;
1444 }
1445 }
 
1446 continue;
1447 }
1448 xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
1449 nCardRcvd++;
1450 if( !g.cgiOutput && !g.fQuiet && recv.nUsed>0 ){
1451 pctDone = (recv.iCursor*100)/recv.nUsed;
1452 if( pctDone!=lastPctDone ){
1453 printf("\rprocessed: %d%% ", pctDone);
1454 lastPctDone = pctDone;
1455 fflush(stdout);
1456 }
1457 }
1458
@@ -1544,44 +1542,22 @@
1544 }else
1545
1546 /* config NAME SIZE \n CONTENT
1547 **
1548 ** Receive a configuration value from the server.
 
 
 
1549 */
1550 if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
1551 && blob_is_int(&xfer.aToken[2], &size) ){
1552 const char *zName = blob_str(&xfer.aToken[1]);
1553 Blob content;
1554 blob_zero(&content);
1555 blob_extract(xfer.pIn, size, &content);
1556 g.okAdmin = g.okRdAddr = 1;
1557 if( configure_is_exportable(zName) & origConfigRcvMask ){
1558 if( zName[0]!='@' ){
1559 if( strcmp(zName, "logo-image")==0 ){
1560 Stmt ins;
1561 db_prepare(&ins,
1562 "REPLACE INTO config(name, value) VALUES(:name, :value)"
1563 );
1564 db_bind_text(&ins, ":name", zName);
1565 db_bind_blob(&ins, ":value", &content);
1566 db_step(&ins);
1567 db_finalize(&ins);
1568 }else{
1569 db_multi_exec(
1570 "REPLACE INTO config(name,value) VALUES(%Q,%Q)",
1571 zName, blob_str(&content)
1572 );
1573 }
1574 }else{
1575 /* Notice that we are evaluating arbitrary SQL received from the
1576 ** server. But this can only happen if we have specifically
1577 ** requested configuration information from the server, so
1578 ** presumably the operator trusts the server.
1579 */
1580 db_multi_exec("%s", blob_str(&content));
1581 }
1582 }
1583 nCardSent++;
1584 blob_reset(&content);
1585 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1586 }else
1587
@@ -1691,11 +1667,13 @@
1691 break;
1692 }
1693 blobarray_reset(xfer.aToken, xfer.nToken);
1694 blob_reset(&xfer.line);
1695 }
1696 if( origConfigRcvMask & (CONFIGSET_TKT|CONFIGSET_USER) ){
 
 
1697 configure_finalize_receive();
1698 }
1699 origConfigRcvMask = 0;
1700 if( nCardRcvd>0 ){
1701 fossil_print(zValueFormat, "Received:",
1702
--- src/xfer.c
+++ src/xfer.c
@@ -454,11 +454,11 @@
454 " (SELECT uuid FROM delta, blob"
455 " WHERE delta.rid=:rid AND delta.srcid=blob.rid)"
456 " FROM blob"
457 " WHERE rid=:rid"
458 " AND size>=0"
459 " AND NOT EXISTS(SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)"
460 );
461 db_bind_int(&q1, ":rid", rid);
462 rc = db_step(&q1);
463 if( rc==SQLITE_ROW ){
464 zUuid = db_column_text(&q1, 0);
@@ -552,10 +552,13 @@
552 defossilize(zLogin);
553
554 if( strcmp(zLogin, "nobody")==0 || strcmp(zLogin,"anonymous")==0 ){
555 return 0; /* Anybody is allowed to sync as "nobody" or "anonymous" */
556 }
557 if( fossil_strcmp(P("REMOTE_USER"), zLogin)==0 ){
558 return 0; /* Accept Basic Authorization */
559 }
560 db_prepare(&q,
561 "SELECT pw, cap, uid FROM user"
562 " WHERE login=%Q"
563 " AND login NOT IN ('anonymous','nobody','developer','reader')"
564 " AND length(pw)>0",
@@ -592,11 +595,11 @@
595 blob_reset(&combined);
596 }
597 if( rc==0 ){
598 const char *zCap;
599 zCap = db_column_text(&q, 1);
600 login_set_capabilities(zCap, 0);
601 g.userUid = db_column_int(&q, 2);
602 g.zLogin = mprintf("%b", pLogin);
603 g.zNonce = mprintf("%b", pNonce);
604 }
605 }
@@ -738,13 +741,16 @@
741 }
742 db_finalize(&q);
743 }
744
745 /*
746 ** Send a single old-style config card for configuration item zName.
747 **
748 ** This routine and the functionality it implements is scheduled for
749 ** removal on 2012-05-01.
750 */
751 static void send_legacy_config_card(Xfer *pXfer, const char *zName){
752 if( zName[0]!='@' ){
753 Blob val;
754 blob_zero(&val);
755 db_blob(&val, "SELECT value FROM config WHERE name=%Q", zName);
756 if( blob_size(&val)>0 ){
@@ -760,11 +766,10 @@
766 blob_appendf(pXfer->pOut, "config %s %d\n%s\n", zName,
767 blob_size(&content), blob_str(&content));
768 blob_reset(&content);
769 }
770 }
 
771
772 /*
773 ** Called when there is an attempt to transfer private content to and
774 ** from a server without authorization.
775 */
@@ -807,10 +812,11 @@
812 if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
813 fossil_redirect_home();
814 }
815 g.zLogin = "anonymous";
816 login_set_anon_nobody_capabilities();
817 login_check_credentials();
818 memset(&xfer, 0, sizeof(xfer));
819 blobarray_zero(xfer.aToken, count(xfer.aToken));
820 cgi_set_content_type(g.zContentType);
821 if( db_schema_is_outofdate() ){
822 @ error database\sschema\sis\sout-of-date\son\sthe\sserver.
@@ -1007,11 +1013,11 @@
1013 */
1014 if( blob_eq(&xfer.aToken[0], "login")
1015 && xfer.nToken==4
1016 ){
1017 if( disableLogin ){
1018 g.okRead = g.okWrite = g.okPrivate = g.okAdmin = 1;
1019 }else{
1020 if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
1021 || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
1022 ){
1023 cgi_reset_content();
@@ -1029,12 +1035,19 @@
1035 if( blob_eq(&xfer.aToken[0], "reqconfig")
1036 && xfer.nToken==2
1037 ){
1038 if( g.okRead ){
1039 char *zName = blob_str(&xfer.aToken[1]);
1040 if( zName[0]=='/' ){
1041 /* New style configuration transfer */
1042 int groupMask = configure_name_to_mask(&zName[1], 0);
1043 if( !g.okAdmin ) groupMask &= ~CONFIGSET_USER;
1044 if( !g.okRdAddr ) groupMask &= ~CONFIGSET_ADDR;
1045 configure_send_group(xfer.pOut, groupMask, 0);
1046 }else if( configure_is_exportable(zName) ){
1047 /* Old style configuration transfer */
1048 send_legacy_config_card(&xfer, zName);
1049 }
1050 }
1051 }else
1052
1053 /* config NAME SIZE \n CONTENT
@@ -1052,38 +1065,15 @@
1065 cgi_reset_content();
1066 @ error not\sauthorized\sto\spush\sconfiguration
1067 nErr++;
1068 break;
1069 }
1070 if( !recvConfig && zName[0]=='@' ){
1071 configure_prepare_to_receive(0);
1072 recvConfig = 1;
1073 }
1074 configure_receive(zName, &content, CONFIGSET_ALL);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1075 blob_reset(&content);
1076 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1077 }else
1078
1079
@@ -1208,19 +1198,19 @@
1198 ** gdb fossil
1199 ** r test-xfer out.txt
1200 */
1201 void cmd_test_xfer(void){
1202 int notUsed;
1203 db_find_and_open_repository(0,0);
1204 if( g.argc!=2 && g.argc!=3 ){
1205 usage("?MESSAGEFILE?");
1206 }
 
1207 blob_zero(&g.cgiIn);
1208 blob_read_from_file(&g.cgiIn, g.argc==2 ? "-" : g.argv[2]);
1209 disableLogin = 1;
1210 page_xfer();
1211 fossil_print("%s\n", cgi_extract_content(&notUsed));
1212 }
1213
1214 /*
1215 ** Format strings for progress reporting.
1216 */
@@ -1354,25 +1344,32 @@
1344 while( zName ){
1345 blob_appendf(&send, "reqconfig %s\n", zName);
1346 zName = configure_next_name(configRcvMask);
1347 nCardSent++;
1348 }
1349 if( (configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT))!=0
1350 && (configRcvMask & CONFIGSET_OLDFORMAT)!=0
1351 ){
1352 int overwrite = (configRcvMask & CONFIGSET_OVERWRITE)!=0;
1353 configure_prepare_to_receive(overwrite);
1354 }
1355 origConfigRcvMask = configRcvMask;
1356 configRcvMask = 0;
1357 }
1358
1359 /* Send configuration parameters being pushed */
1360 if( configSendMask ){
1361 if( configSendMask & CONFIGSET_OLDFORMAT ){
1362 const char *zName;
1363 zName = configure_first_name(configSendMask);
1364 while( zName ){
1365 send_legacy_config_card(&xfer, zName);
1366 zName = configure_next_name(configSendMask);
1367 nCardSent++;
1368 }
1369 }else{
1370 nCardSent += configure_send_group(xfer.pOut, configSendMask, 0);
1371 }
1372 configSendMask = 0;
1373 }
1374
1375 /* Append randomness to the end of the message. This makes all
@@ -1393,11 +1390,11 @@
1390 xfer.nFileSent = 0;
1391 xfer.nDeltaSent = 0;
1392 xfer.nGimmeSent = 0;
1393 xfer.nIGotSent = 0;
1394 if( !g.cgiOutput && !g.fQuiet ){
1395 fossil_print("waiting for server...");
1396 }
1397 fflush(stdout);
1398 if( http_exchange(&send, &recv, cloneFlag==0 || nCycle>0) ){
1399 nErr++;
1400 break;
@@ -1441,18 +1438,19 @@
1438 fossil_warning("*** time skew *** server is slow by %s",
1439 db_timespan_name(-rDiff));
1440 g.clockSkewSeen = 1;
1441 }
1442 }
1443 nCardRcvd++;
1444 continue;
1445 }
1446 xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
1447 nCardRcvd++;
1448 if( !g.cgiOutput && !g.fQuiet && recv.nUsed>0 ){
1449 pctDone = (recv.iCursor*100)/recv.nUsed;
1450 if( pctDone!=lastPctDone ){
1451 fossil_print("\rprocessed: %d%% ", pctDone);
1452 lastPctDone = pctDone;
1453 fflush(stdout);
1454 }
1455 }
1456
@@ -1544,44 +1542,22 @@
1542 }else
1543
1544 /* config NAME SIZE \n CONTENT
1545 **
1546 ** Receive a configuration value from the server.
1547 **
1548 ** The received configuration setting is silently ignored if it was
1549 ** not requested by a prior "reqconfig" sent from client to server.
1550 */
1551 if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
1552 && blob_is_int(&xfer.aToken[2], &size) ){
1553 const char *zName = blob_str(&xfer.aToken[1]);
1554 Blob content;
1555 blob_zero(&content);
1556 blob_extract(xfer.pIn, size, &content);
1557 g.okAdmin = g.okRdAddr = 1;
1558 configure_receive(zName, &content, origConfigRcvMask);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1559 nCardSent++;
1560 blob_reset(&content);
1561 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1562 }else
1563
@@ -1691,11 +1667,13 @@
1667 break;
1668 }
1669 blobarray_reset(xfer.aToken, xfer.nToken);
1670 blob_reset(&xfer.line);
1671 }
1672 if( (configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT))!=0
1673 && (configRcvMask & CONFIGSET_OLDFORMAT)!=0
1674 ){
1675 configure_finalize_receive();
1676 }
1677 origConfigRcvMask = 0;
1678 if( nCardRcvd>0 ){
1679 fossil_print(zValueFormat, "Received:",
1680
+3 -3
--- test/file1.test
+++ test/file1.test
@@ -26,12 +26,12 @@
2626
incr i
2727
}
2828
}
2929
3030
simplify-name 100 . . .// . .. .. ..///// ..
31
-simplify-name 101 {} . / / ///////// / ././././ .
32
-simplify-name 102 x x /x /x ///x /x
33
-simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// /a/b
31
+simplify-name 101 {} {} / / ///////// / ././././ .
32
+simplify-name 102 x x /x /x ///x //x
33
+simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b
3434
simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
3535
simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
3636
simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
3737
simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y
3838
--- test/file1.test
+++ test/file1.test
@@ -26,12 +26,12 @@
26 incr i
27 }
28 }
29
30 simplify-name 100 . . .// . .. .. ..///// ..
31 simplify-name 101 {} . / / ///////// / ././././ .
32 simplify-name 102 x x /x /x ///x /x
33 simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// /a/b
34 simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
35 simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
36 simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
37 simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y
38
--- test/file1.test
+++ test/file1.test
@@ -26,12 +26,12 @@
26 incr i
27 }
28 }
29
30 simplify-name 100 . . .// . .. .. ..///// ..
31 simplify-name 101 {} {} / / ///////// / ././././ .
32 simplify-name 102 x x /x /x ///x //x
33 simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b
34 simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
35 simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
36 simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
37 simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y
38
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -2,30 +2,71 @@
22
33
This page contains examples a list of URLs of timelines with
44
interesting graphs. Click on all URLs, one by one, to verify
55
the correct operation of the graph drawing logic.
66
7
- * [/timeline?n=20&y=ci&b=2010-11-08]
8
- * [/timeline?n=40&y=ci&b=2010-11-08]
9
- * [/timeline?n=1000&y=ci&b=2010-11-08]
10
- * [/timeline?f=3ea66260b5555d2e]
11
- * [/timeline?d=e5fe4164f74a7576&p=e5fe4164f74a7576&n=3] -
12
- multiple merge descenders from the penultimate node.
13
- * [/timeline?y=ci&a=2010-12-20] - multiple branch risers.
14
- * [/timeline?y=ci&a=2010-12-20&n=18]
15
- * [/timeline?y=ci&a=2010-12-20&n=9]
16
- * [/timeline?r=experimental]
17
- * [/timeline?r=experimental&n=1000]
18
- * [/timeline?r=creole]
19
- * [/timeline?t=creole]
20
- * [/timeline?t=release]
21
- * [/timeline?r=release]
22
- * [/finfo?name=Makefile]
23
- * [/timeline?a=1970-01-01]
24
- * [/timeline?y=ci&n=1000000] - All checkins - a huge graph
25
- * [/timeline?f=8dfed953f7530442] - This malformed commit has a
26
- merge parent which is not a valid checkin.
7
+ * <a href="../../../timeline?n=20&y=ci&b=2010-11-08" target="testwindow">
8
+ 20-element timeline, check-ins only, before 2010-11-08</a>
9
+ * <a href="../../../timeline?n=20&y=ci&b=2010-11-08&ng" target="testwindow">
10
+ 20-element timeline, check-ins only, no graph, before 2010-11-08</a>
11
+ * <a href="../../../timeline?n=20&y=ci&b=2010-11-08&fc" target="testwindow">
12
+ 20-element timeline, check-ins only, file changes, before 2010-11-08</a>
13
+ * <a href="../../../timeline?n=40&y=ci&b=2010-11-08" target="testwindow">
14
+ 40-element timeline, check-ins only, before 2010-11-08</a>
15
+ * <a href="../../../timeline?n=1000&y=ci&b=2010-11-08" target="testwindow">
16
+ 1000-element timeline, check-ins only, before 2010-11-08</a>
17
+ * <a href="../../../timeline?n=10&c=2010-11-07+10:23:00" target="testwindow">
18
+ 10-elements circa 2010-11-07 10:23:00, with dividers</a>
19
+ * <a href="../../../timeline?n=10&c=2010-11-07+10:23:00&nd"
20
+ target="testwindow">
21
+ 10-elements circa 2010-11-07 10:23:00, without dividers</a>
22
+ * <a href="../../../timeline?f=3ea66260b5555" target="testwindow">
23
+ Parents and children of check-in 3ea66260b5555</a>
24
+ * <a href="../../../timeline?d=e5fe4164f74a7576&p=e5fe4164f74a7576&n=3"
25
+ target="testwindow">multiple merge descenders from the penultimate node.
26
+ </a>
27
+ * <a href="../../../timeline?y=ci&a=2010-12-20" target="testwindow">
28
+ multiple branch risers.</a>
29
+ * <a href="../../../timeline?y=ci&a=2010-12-20&n=18" target="testwindow">
30
+ multiple branch risers, n=18.</a>
31
+ * <a href="../../../timeline?y=ci&a=2010-12-20&n=9" target="testwindow">
32
+ multiple branch risers, n=9.</a>
33
+ * <a href="../../../timeline?r=experimental" target="testwindow">
34
+ Experimental branch using and related check-ins.</a>
35
+ * <a href="../../../timeline?r=experimental&mionly" target="testwindow">
36
+ Experimental branch using and merge-ins only.</a>
37
+ * <a href="../../../timeline?t=experimental" target="testwindow">
38
+ Experimental branch check-ins only.</a>
39
+ * <a href="../../../timeline?r=experimental&n=1000" target="testwindow">
40
+ Experimental branch using and related check-ins - 1000 elements.</a>
41
+ * <a href="../../../timeline?r=release" target="testwindow">
42
+ Check-ins tagged "release" and related check-ins</a>
43
+ * <a href="../../../timeline?r=release&mionly" target="testwindow">
44
+ Check-ins tagged "release" and merge-ins</a>
45
+ * <a href="../../../timeline?t=release" target="testwindow">
46
+ Only check-ins tagged "release"</a>
47
+ * <a href="../../../finfo?name=Makefile" target="testwindow">
48
+ History of source file "Makefile".</a>
49
+ * <a href="../../../timeline?a=1970-01-01" target="testwindow">
50
+ 20 elements after 1970-01-01.</a>
51
+ * <a href="../../../timeline?n=100000000&y=ci" target="testwindow">
52
+ All check-ins - a huge graph.</a>
53
+ * <a href="../../../timeline?f=8dfed953f7530442" target="testwindow">
54
+ This malformed commit has a
55
+ merge parent which is not a valid checkin.</a>
56
+ * <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9"
57
+ target="testwindow">
58
+ From e663bac6f7 to a298a0e2f9 by shortest path.</a>
59
+ * <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9&nomerge"
60
+ target="testwindow">
61
+ From e663bac6f7 to a298a0e2f9 without merge links.</a>
62
+ * <a href="../../../timeline?me=e663bac6f7&you=a298a0e2f9"
63
+ target="testwindow">
64
+ Common ancestor path of e663bac6f7 to a298a0e2f9.</a>
65
+ * <a href="../../../timeline?f=65dd90fb95a2af55">
66
+ Merge on the same branch does not result in a leaf.
67
+ </a>
2768
2869
External:
2970
30
- * [http://www.sqlite.org/src/timeline?c=2010-09-29&nd] - timewarp due to
31
- a mis-configured system clock.
71
+ * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
72
+ target="testwindow">Timewarp due to a mis-configured system clock.</a>
3273
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -2,30 +2,71 @@
2
3 This page contains examples a list of URLs of timelines with
4 interesting graphs. Click on all URLs, one by one, to verify
5 the correct operation of the graph drawing logic.
6
7 * [/timeline?n=20&y=ci&b=2010-11-08]
8 * [/timeline?n=40&y=ci&b=2010-11-08]
9 * [/timeline?n=1000&y=ci&b=2010-11-08]
10 * [/timeline?f=3ea66260b5555d2e]
11 * [/timeline?d=e5fe4164f74a7576&p=e5fe4164f74a7576&n=3] -
12 multiple merge descenders from the penultimate node.
13 * [/timeline?y=ci&a=2010-12-20] - multiple branch risers.
14 * [/timeline?y=ci&a=2010-12-20&n=18]
15 * [/timeline?y=ci&a=2010-12-20&n=9]
16 * [/timeline?r=experimental]
17 * [/timeline?r=experimental&n=1000]
18 * [/timeline?r=creole]
19 * [/timeline?t=creole]
20 * [/timeline?t=release]
21 * [/timeline?r=release]
22 * [/finfo?name=Makefile]
23 * [/timeline?a=1970-01-01]
24 * [/timeline?y=ci&n=1000000] - All checkins - a huge graph
25 * [/timeline?f=8dfed953f7530442] - This malformed commit has a
26 merge parent which is not a valid checkin.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
28 External:
29
30 * [http://www.sqlite.org/src/timeline?c=2010-09-29&nd] - timewarp due to
31 a mis-configured system clock.
32
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -2,30 +2,71 @@
2
3 This page contains examples a list of URLs of timelines with
4 interesting graphs. Click on all URLs, one by one, to verify
5 the correct operation of the graph drawing logic.
6
7 * <a href="../../../timeline?n=20&y=ci&b=2010-11-08" target="testwindow">
8 20-element timeline, check-ins only, before 2010-11-08</a>
9 * <a href="../../../timeline?n=20&y=ci&b=2010-11-08&ng" target="testwindow">
10 20-element timeline, check-ins only, no graph, before 2010-11-08</a>
11 * <a href="../../../timeline?n=20&y=ci&b=2010-11-08&fc" target="testwindow">
12 20-element timeline, check-ins only, file changes, before 2010-11-08</a>
13 * <a href="../../../timeline?n=40&y=ci&b=2010-11-08" target="testwindow">
14 40-element timeline, check-ins only, before 2010-11-08</a>
15 * <a href="../../../timeline?n=1000&y=ci&b=2010-11-08" target="testwindow">
16 1000-element timeline, check-ins only, before 2010-11-08</a>
17 * <a href="../../../timeline?n=10&c=2010-11-07+10:23:00" target="testwindow">
18 10-elements circa 2010-11-07 10:23:00, with dividers</a>
19 * <a href="../../../timeline?n=10&c=2010-11-07+10:23:00&nd"
20 target="testwindow">
21 10-elements circa 2010-11-07 10:23:00, without dividers</a>
22 * <a href="../../../timeline?f=3ea66260b5555" target="testwindow">
23 Parents and children of check-in 3ea66260b5555</a>
24 * <a href="../../../timeline?d=e5fe4164f74a7576&p=e5fe4164f74a7576&n=3"
25 target="testwindow">multiple merge descenders from the penultimate node.
26 </a>
27 * <a href="../../../timeline?y=ci&a=2010-12-20" target="testwindow">
28 multiple branch risers.</a>
29 * <a href="../../../timeline?y=ci&a=2010-12-20&n=18" target="testwindow">
30 multiple branch risers, n=18.</a>
31 * <a href="../../../timeline?y=ci&a=2010-12-20&n=9" target="testwindow">
32 multiple branch risers, n=9.</a>
33 * <a href="../../../timeline?r=experimental" target="testwindow">
34 Experimental branch using and related check-ins.</a>
35 * <a href="../../../timeline?r=experimental&mionly" target="testwindow">
36 Experimental branch using and merge-ins only.</a>
37 * <a href="../../../timeline?t=experimental" target="testwindow">
38 Experimental branch check-ins only.</a>
39 * <a href="../../../timeline?r=experimental&n=1000" target="testwindow">
40 Experimental branch using and related check-ins - 1000 elements.</a>
41 * <a href="../../../timeline?r=release" target="testwindow">
42 Check-ins tagged "release" and related check-ins</a>
43 * <a href="../../../timeline?r=release&mionly" target="testwindow">
44 Check-ins tagged "release" and merge-ins</a>
45 * <a href="../../../timeline?t=release" target="testwindow">
46 Only check-ins tagged "release"</a>
47 * <a href="../../../finfo?name=Makefile" target="testwindow">
48 History of source file "Makefile".</a>
49 * <a href="../../../timeline?a=1970-01-01" target="testwindow">
50 20 elements after 1970-01-01.</a>
51 * <a href="../../../timeline?n=100000000&y=ci" target="testwindow">
52 All check-ins - a huge graph.</a>
53 * <a href="../../../timeline?f=8dfed953f7530442" target="testwindow">
54 This malformed commit has a
55 merge parent which is not a valid checkin.</a>
56 * <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9"
57 target="testwindow">
58 From e663bac6f7 to a298a0e2f9 by shortest path.</a>
59 * <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9&nomerge"
60 target="testwindow">
61 From e663bac6f7 to a298a0e2f9 without merge links.</a>
62 * <a href="../../../timeline?me=e663bac6f7&you=a298a0e2f9"
63 target="testwindow">
64 Common ancestor path of e663bac6f7 to a298a0e2f9.</a>
65 * <a href="../../../timeline?f=65dd90fb95a2af55">
66 Merge on the same branch does not result in a leaf.
67 </a>
68
69 External:
70
71 * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
72 target="testwindow">Timewarp due to a mis-configured system clock.</a>
73
+44 -18
--- test/merge1.test
+++ test/merge1.test
@@ -71,26 +71,30 @@
7171
333 - This is a test of the merging algohm - 3333
7272
444 - If all goes well, we will be pleased - 4444
7373
555 - we think it well and other stuff too - 5555
7474
}
7575
write_file_indented t23 {
76
- <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
76
+ <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
7777
111 - This is line ONE of the demo program - 1111
78
- ======= original content above; conflict below =============
78
+ ======= COMMON ANCESTOR content follows ============================
79
+ 111 - This is line one of the demo program - 1111
80
+ ======= MERGED IN content follows ==================================
7981
111 - This is line one OF the demo program - 1111
80
- >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
82
+ >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
8183
222 - The second line program line in code - 2222
8284
333 - This is a test of the merging algohm - 3333
8385
444 - If all goes well, we will be pleased - 4444
8486
555 - we think it well and other stuff too - 5555
8587
}
8688
write_file_indented t32 {
87
- <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
89
+ <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
8890
111 - This is line one OF the demo program - 1111
89
- ======= original content above; conflict below =============
91
+ ======= COMMON ANCESTOR content follows ============================
92
+ 111 - This is line one of the demo program - 1111
93
+ ======= MERGED IN content follows ==================================
9094
111 - This is line ONE of the demo program - 1111
91
- >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
95
+ >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
9296
222 - The second line program line in code - 2222
9397
333 - This is a test of the merging algohm - 3333
9498
444 - If all goes well, we will be pleased - 4444
9599
555 - we think it well and other stuff too - 5555
96100
}
@@ -152,26 +156,30 @@
152156
333 - This is a test of the merging algohm - 3333
153157
444 - If all goes well, we will be pleased - 4444
154158
555 - we think it well and other stuff too - 5555
155159
}
156160
write_file_indented t32 {
157
- <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
158
- ======= original content above; conflict below =============
161
+ <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
162
+ ======= COMMON ANCESTOR content follows ============================
163
+ 111 - This is line one of the demo program - 1111
164
+ ======= MERGED IN content follows ==================================
159165
000 - Zero lines added to the beginning of - 0000
160166
111 - This is line one of the demo program - 1111
161
- >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
167
+ >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
162168
222 - The second line program line in code - 2222
163169
333 - This is a test of the merging algohm - 3333
164170
444 - If all goes well, we will be pleased - 4444
165171
555 - we think it well and other stuff too - 5555
166172
}
167173
write_file_indented t23 {
168
- <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
174
+ <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
169175
000 - Zero lines added to the beginning of - 0000
170176
111 - This is line one of the demo program - 1111
171
- ======= original content above; conflict below =============
172
- >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
177
+ ======= COMMON ANCESTOR content follows ============================
178
+ 111 - This is line one of the demo program - 1111
179
+ ======= MERGED IN content follows ==================================
180
+ >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
173181
222 - The second line program line in code - 2222
174182
333 - This is a test of the merging algohm - 3333
175183
444 - If all goes well, we will be pleased - 4444
176184
555 - we think it well and other stuff too - 5555
177185
}
@@ -287,29 +295,38 @@
287295
STUV
288296
XYZ.
289297
}
290298
write_file_indented t23 {
291299
abcd
292
- <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
300
+ <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
293301
efgh 2
294302
ijkl 2
295303
mnop 2
296304
qrst
297305
uvwx
298306
yzAB 2
299307
CDEF 2
300308
GHIJ 2
301
- ======= original content above; conflict below =============
309
+ ======= COMMON ANCESTOR content follows ============================
310
+ efgh
311
+ ijkl
312
+ mnop
313
+ qrst
314
+ uvwx
315
+ yzAB
316
+ CDEF
317
+ GHIJ
318
+ ======= MERGED IN content follows ==================================
302319
efgh
303320
ijkl
304321
mnop 3
305322
qrst 3
306323
uvwx 3
307324
yzAB 3
308325
CDEF
309326
GHIJ
310
- >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
327
+ >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
311328
KLMN
312329
OPQR
313330
STUV
314331
XYZ.
315332
}
@@ -346,31 +363,40 @@
346363
STUV
347364
XYZ.
348365
}
349366
write_file_indented t23 {
350367
abcd
351
- <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
368
+ <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
352369
efgh 2
353370
ijkl 2
354371
mnop
355372
qrst
356373
uvwx
357374
yzAB 2
358375
CDEF 2
359376
GHIJ 2
360
- ======= original content above; conflict below =============
377
+ ======= COMMON ANCESTOR content follows ============================
378
+ efgh
379
+ ijkl
380
+ mnop
381
+ qrst
382
+ uvwx
383
+ yzAB
384
+ CDEF
385
+ GHIJ
386
+ ======= MERGED IN content follows ==================================
361387
efgh
362388
ijkl
363389
mnop 3
364390
qrst 3
365391
uvwx 3
366392
yzAB 3
367393
CDEF
368394
GHIJ
369
- >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
395
+ >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
370396
KLMN
371397
OPQR
372398
STUV
373399
XYZ.
374400
}
375401
fossil test-3 t1 t2 t3 a23
376402
test merge1-7.2 {[same_file t23 a23]}
377403
--- test/merge1.test
+++ test/merge1.test
@@ -71,26 +71,30 @@
71 333 - This is a test of the merging algohm - 3333
72 444 - If all goes well, we will be pleased - 4444
73 555 - we think it well and other stuff too - 5555
74 }
75 write_file_indented t23 {
76 <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
77 111 - This is line ONE of the demo program - 1111
78 ======= original content above; conflict below =============
 
 
79 111 - This is line one OF the demo program - 1111
80 >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
81 222 - The second line program line in code - 2222
82 333 - This is a test of the merging algohm - 3333
83 444 - If all goes well, we will be pleased - 4444
84 555 - we think it well and other stuff too - 5555
85 }
86 write_file_indented t32 {
87 <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
88 111 - This is line one OF the demo program - 1111
89 ======= original content above; conflict below =============
 
 
90 111 - This is line ONE of the demo program - 1111
91 >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
92 222 - The second line program line in code - 2222
93 333 - This is a test of the merging algohm - 3333
94 444 - If all goes well, we will be pleased - 4444
95 555 - we think it well and other stuff too - 5555
96 }
@@ -152,26 +156,30 @@
152 333 - This is a test of the merging algohm - 3333
153 444 - If all goes well, we will be pleased - 4444
154 555 - we think it well and other stuff too - 5555
155 }
156 write_file_indented t32 {
157 <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
158 ======= original content above; conflict below =============
 
 
159 000 - Zero lines added to the beginning of - 0000
160 111 - This is line one of the demo program - 1111
161 >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
162 222 - The second line program line in code - 2222
163 333 - This is a test of the merging algohm - 3333
164 444 - If all goes well, we will be pleased - 4444
165 555 - we think it well and other stuff too - 5555
166 }
167 write_file_indented t23 {
168 <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
169 000 - Zero lines added to the beginning of - 0000
170 111 - This is line one of the demo program - 1111
171 ======= original content above; conflict below =============
172 >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
 
 
173 222 - The second line program line in code - 2222
174 333 - This is a test of the merging algohm - 3333
175 444 - If all goes well, we will be pleased - 4444
176 555 - we think it well and other stuff too - 5555
177 }
@@ -287,29 +295,38 @@
287 STUV
288 XYZ.
289 }
290 write_file_indented t23 {
291 abcd
292 <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
293 efgh 2
294 ijkl 2
295 mnop 2
296 qrst
297 uvwx
298 yzAB 2
299 CDEF 2
300 GHIJ 2
301 ======= original content above; conflict below =============
 
 
 
 
 
 
 
 
 
302 efgh
303 ijkl
304 mnop 3
305 qrst 3
306 uvwx 3
307 yzAB 3
308 CDEF
309 GHIJ
310 >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
311 KLMN
312 OPQR
313 STUV
314 XYZ.
315 }
@@ -346,31 +363,40 @@
346 STUV
347 XYZ.
348 }
349 write_file_indented t23 {
350 abcd
351 <<<<<<< BEGIN MERGE CONFLICT: original content first <<<<<<<
352 efgh 2
353 ijkl 2
354 mnop
355 qrst
356 uvwx
357 yzAB 2
358 CDEF 2
359 GHIJ 2
360 ======= original content above; conflict below =============
 
 
 
 
 
 
 
 
 
361 efgh
362 ijkl
363 mnop 3
364 qrst 3
365 uvwx 3
366 yzAB 3
367 CDEF
368 GHIJ
369 >>>>>>> END MERGE CONFLICT: conflict last >>>>>>>>>>>>>>>>>>
370 KLMN
371 OPQR
372 STUV
373 XYZ.
374 }
375 fossil test-3 t1 t2 t3 a23
376 test merge1-7.2 {[same_file t23 a23]}
377
--- test/merge1.test
+++ test/merge1.test
@@ -71,26 +71,30 @@
71 333 - This is a test of the merging algohm - 3333
72 444 - If all goes well, we will be pleased - 4444
73 555 - we think it well and other stuff too - 5555
74 }
75 write_file_indented t23 {
76 <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
77 111 - This is line ONE of the demo program - 1111
78 ======= COMMON ANCESTOR content follows ============================
79 111 - This is line one of the demo program - 1111
80 ======= MERGED IN content follows ==================================
81 111 - This is line one OF the demo program - 1111
82 >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
83 222 - The second line program line in code - 2222
84 333 - This is a test of the merging algohm - 3333
85 444 - If all goes well, we will be pleased - 4444
86 555 - we think it well and other stuff too - 5555
87 }
88 write_file_indented t32 {
89 <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
90 111 - This is line one OF the demo program - 1111
91 ======= COMMON ANCESTOR content follows ============================
92 111 - This is line one of the demo program - 1111
93 ======= MERGED IN content follows ==================================
94 111 - This is line ONE of the demo program - 1111
95 >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
96 222 - The second line program line in code - 2222
97 333 - This is a test of the merging algohm - 3333
98 444 - If all goes well, we will be pleased - 4444
99 555 - we think it well and other stuff too - 5555
100 }
@@ -152,26 +156,30 @@
156 333 - This is a test of the merging algohm - 3333
157 444 - If all goes well, we will be pleased - 4444
158 555 - we think it well and other stuff too - 5555
159 }
160 write_file_indented t32 {
161 <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
162 ======= COMMON ANCESTOR content follows ============================
163 111 - This is line one of the demo program - 1111
164 ======= MERGED IN content follows ==================================
165 000 - Zero lines added to the beginning of - 0000
166 111 - This is line one of the demo program - 1111
167 >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
168 222 - The second line program line in code - 2222
169 333 - This is a test of the merging algohm - 3333
170 444 - If all goes well, we will be pleased - 4444
171 555 - we think it well and other stuff too - 5555
172 }
173 write_file_indented t23 {
174 <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
175 000 - Zero lines added to the beginning of - 0000
176 111 - This is line one of the demo program - 1111
177 ======= COMMON ANCESTOR content follows ============================
178 111 - This is line one of the demo program - 1111
179 ======= MERGED IN content follows ==================================
180 >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
181 222 - The second line program line in code - 2222
182 333 - This is a test of the merging algohm - 3333
183 444 - If all goes well, we will be pleased - 4444
184 555 - we think it well and other stuff too - 5555
185 }
@@ -287,29 +295,38 @@
295 STUV
296 XYZ.
297 }
298 write_file_indented t23 {
299 abcd
300 <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
301 efgh 2
302 ijkl 2
303 mnop 2
304 qrst
305 uvwx
306 yzAB 2
307 CDEF 2
308 GHIJ 2
309 ======= COMMON ANCESTOR content follows ============================
310 efgh
311 ijkl
312 mnop
313 qrst
314 uvwx
315 yzAB
316 CDEF
317 GHIJ
318 ======= MERGED IN content follows ==================================
319 efgh
320 ijkl
321 mnop 3
322 qrst 3
323 uvwx 3
324 yzAB 3
325 CDEF
326 GHIJ
327 >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
328 KLMN
329 OPQR
330 STUV
331 XYZ.
332 }
@@ -346,31 +363,40 @@
363 STUV
364 XYZ.
365 }
366 write_file_indented t23 {
367 abcd
368 <<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<
369 efgh 2
370 ijkl 2
371 mnop
372 qrst
373 uvwx
374 yzAB 2
375 CDEF 2
376 GHIJ 2
377 ======= COMMON ANCESTOR content follows ============================
378 efgh
379 ijkl
380 mnop
381 qrst
382 uvwx
383 yzAB
384 CDEF
385 GHIJ
386 ======= MERGED IN content follows ==================================
387 efgh
388 ijkl
389 mnop 3
390 qrst 3
391 uvwx 3
392 yzAB 3
393 CDEF
394 GHIJ
395 >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
396 KLMN
397 OPQR
398 STUV
399 XYZ.
400 }
401 fossil test-3 t1 t2 t3 a23
402 test merge1-7.2 {[same_file t23 a23]}
403
+30 -28
--- test/merge3.test
+++ test/merge3.test
@@ -22,13 +22,15 @@
2222
write_file t1 [join [string trim $basis] \n]\n
2323
write_file t2 [join [string trim $v1] \n]\n
2424
write_file t3 [join [string trim $v2] \n]\n
2525
fossil test-3-way-merge t1 t2 t3 t4
2626
set x [read_file t4]
27
- regsub -all {<<<<<<< BEGIN MERGE CONFLICT:.*<} $x {>} x
28
- regsub -all {======= original content.*======} $x {=} x
29
- regsub -all {>>>>>>> END MERGE CONFLICT:.*>>>} $x {<} x
27
+ regsub -all {<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <+} $x \
28
+ {MINE:} x
29
+ regsub -all {======= COMMON ANCESTOR content follows =+} $x {COM:} x
30
+ regsub -all {======= MERGED IN content follows =+} $x {YOURS:} x
31
+ regsub -all {>>>>>>> END MERGE CONFLICT >+} $x {END} x
3032
set x [split [string trim $x] \n]
3133
set result [string trim $result]
3234
if {$x!=$result} {
3335
protOut " Expected \[$result\]"
3436
protOut " Got \[$x\]"
@@ -62,56 +64,56 @@
6264
} {
6365
1 2 3b 4b 5b 6 7 8 9
6466
} {
6567
1 2 3 4 5c 6 7 8 9
6668
} {
67
- 1 2 > 3b 4b 5b = 3 4 5c < 6 7 8 9
69
+ 1 2 MINE: 3b 4b 5b COM: 3 4 5 YOURS: 3 4 5c END 6 7 8 9
6870
}
6971
merge-test 4 {
7072
1 2 3 4 5 6 7 8 9
7173
} {
7274
1 2 3b 4b 5b 6b 7 8 9
7375
} {
7476
1 2 3 4 5c 6 7 8 9
7577
} {
76
- 1 2 > 3b 4b 5b 6b = 3 4 5c 6 < 7 8 9
78
+ 1 2 MINE: 3b 4b 5b 6b COM: 3 4 5 6 YOURS: 3 4 5c 6 END 7 8 9
7779
}
7880
merge-test 5 {
7981
1 2 3 4 5 6 7 8 9
8082
} {
8183
1 2 3b 4b 5b 6b 7 8 9
8284
} {
8385
1 2 3 4 5c 6c 7c 8 9
8486
} {
85
- 1 2 > 3b 4b 5b 6b 7 = 3 4 5c 6c 7c < 8 9
87
+ 1 2 MINE: 3b 4b 5b 6b 7 COM: 3 4 5 6 7 YOURS: 3 4 5c 6c 7c END 8 9
8688
}
8789
merge-test 6 {
8890
1 2 3 4 5 6 7 8 9
8991
} {
9092
1 2 3b 4b 5b 6b 7 8b 9
9193
} {
9294
1 2 3 4 5c 6c 7c 8 9
9395
} {
94
- 1 2 > 3b 4b 5b 6b 7 = 3 4 5c 6c 7c < 8b 9
96
+ 1 2 MINE: 3b 4b 5b 6b 7 COM: 3 4 5 6 7 YOURS: 3 4 5c 6c 7c END 8b 9
9597
}
9698
merge-test 7 {
9799
1 2 3 4 5 6 7 8 9
98100
} {
99101
1 2 3b 4b 5b 6b 7 8b 9
100102
} {
101103
1 2 3 4 5c 6c 7c 8c 9
102104
} {
103
- 1 2 > 3b 4b 5b 6b 7 8b = 3 4 5c 6c 7c 8c < 9
105
+ 1 2 MINE: 3b 4b 5b 6b 7 8b COM: 3 4 5 6 7 8 YOURS: 3 4 5c 6c 7c 8c END 9
104106
}
105107
merge-test 8 {
106108
1 2 3 4 5 6 7 8 9
107109
} {
108110
1 2 3b 4b 5b 6b 7 8b 9b
109111
} {
110112
1 2 3 4 5c 6c 7c 8c 9
111113
} {
112
- 1 2 > 3b 4b 5b 6b 7 8b 9b = 3 4 5c 6c 7c 8c 9 <
114
+ 1 2 MINE: 3b 4b 5b 6b 7 8b 9b COM: 3 4 5 6 7 8 9 YOURS: 3 4 5c 6c 7c 8c 9 END
113115
}
114116
merge-test 9 {
115117
1 2 3 4 5 6 7 8 9
116118
} {
117119
1 2 3b 4b 5 6 7 8b 9b
@@ -135,11 +137,11 @@
135137
} {
136138
1 2 3b 4b 5 6 7 8b 9b
137139
} {
138140
1 2 3b 4c 5 6c 7c 8 9
139141
} {
140
- 1 2 > 3b 4b = 3b 4c < 5 6c 7c 8b 9b
142
+ 1 2 MINE: 3b 4b COM: 3 4 YOURS: 3b 4c END 5 6c 7c 8b 9b
141143
}
142144
merge-test 12 {
143145
1 2 3 4 5 6 7 8 9
144146
} {
145147
1 2 3b4b 5 6 7 8b 9b
@@ -190,20 +192,20 @@
190192
} {
191193
1 6 7 8 9
192194
} {
193195
1 2 3 4 9
194196
} {
195
- 1 > 6 7 8 = 2 3 4 < 9
197
+ 1 MINE: 6 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 4 END 9
196198
}
197199
merge-test 25 {
198200
1 2 3 4 5 6 7 8 9
199201
} {
200202
1 7 8 9
201203
} {
202204
1 2 3 9
203205
} {
204
- 1 > 7 8 = 2 3 < 9
206
+ 1 MINE: 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 END 9
205207
}
206208
207209
merge-test 30 {
208210
1 2 3 4 5 6 7 8 9
209211
} {
@@ -245,20 +247,20 @@
245247
} {
246248
1 2 3 4 9
247249
} {
248250
1 6 7 8 9
249251
} {
250
- 1 > 2 3 4 = 6 7 8 < 9
252
+ 1 MINE: 2 3 4 COM: 2 3 4 5 6 7 8 YOURS: 6 7 8 END 9
251253
}
252254
merge-test 35 {
253255
1 2 3 4 5 6 7 8 9
254256
} {
255257
1 2 3 9
256258
} {
257259
1 7 8 9
258260
} {
259
- 1 > 2 3 = 7 8 < 9
261
+ 1 MINE: 2 3 COM: 2 3 4 5 6 7 8 YOURS: 7 8 END 9
260262
}
261263
262264
merge-test 40 {
263265
2 3 4 5 6 7 8
264266
} {
@@ -300,20 +302,20 @@
300302
} {
301303
6 7 8
302304
} {
303305
2 3 4
304306
} {
305
- > 6 7 8 = 2 3 4 <
307
+ MINE: 6 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 4 END
306308
}
307309
merge-test 45 {
308310
2 3 4 5 6 7 8
309311
} {
310312
7 8
311313
} {
312314
2 3
313315
} {
314
- > 7 8 = 2 3 <
316
+ MINE: 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 END
315317
}
316318
317319
merge-test 50 {
318320
2 3 4 5 6 7 8
319321
} {
@@ -354,20 +356,20 @@
354356
} {
355357
2 3 4
356358
} {
357359
6 7 8
358360
} {
359
- > 2 3 4 = 6 7 8 <
361
+ MINE: 2 3 4 COM: 2 3 4 5 6 7 8 YOURS: 6 7 8 END
360362
}
361363
merge-test 55 {
362364
2 3 4 5 6 7 8
363365
} {
364366
2 3
365367
} {
366368
7 8
367369
} {
368
- > 2 3 = 7 8 <
370
+ MINE: 2 3 COM: 2 3 4 5 6 7 8 YOURS: 7 8 END
369371
}
370372
371373
merge-test 60 {
372374
1 2 3 4 5 6 7 8 9
373375
} {
@@ -409,20 +411,20 @@
409411
} {
410412
1 2b 3b 4b 5b 6 7 8 9
411413
} {
412414
1 2 3 4 9
413415
} {
414
- 1 > 2b 3b 4b 5b 6 7 8 = 2 3 4 < 9
416
+ 1 MINE: 2b 3b 4b 5b 6 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 4 END 9
415417
}
416418
merge-test 65 {
417419
1 2 3 4 5 6 7 8 9
418420
} {
419421
1 2b 3b 4b 5b 6b 7 8 9
420422
} {
421423
1 2 3 9
422424
} {
423
- 1 > 2b 3b 4b 5b 6b 7 8 = 2 3 < 9
425
+ 1 MINE: 2b 3b 4b 5b 6b 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 END 9
424426
}
425427
426428
merge-test 70 {
427429
1 2 3 4 5 6 7 8 9
428430
} {
@@ -464,20 +466,20 @@
464466
} {
465467
1 2 3 4 9
466468
} {
467469
1 2b 3b 4b 5b 6 7 8 9
468470
} {
469
- 1 > 2 3 4 = 2b 3b 4b 5b 6 7 8 < 9
471
+ 1 MINE: 2 3 4 COM: 2 3 4 5 6 7 8 YOURS: 2b 3b 4b 5b 6 7 8 END 9
470472
}
471473
merge-test 75 {
472474
1 2 3 4 5 6 7 8 9
473475
} {
474476
1 2 3 9
475477
} {
476478
1 2b 3b 4b 5b 6b 7 8 9
477479
} {
478
- 1 > 2 3 = 2b 3b 4b 5b 6b 7 8 < 9
480
+ 1 MINE: 2 3 COM: 2 3 4 5 6 7 8 YOURS: 2b 3b 4b 5b 6b 7 8 END 9
479481
}
480482
481483
merge-test 80 {
482484
2 3 4 5 6 7 8
483485
} {
@@ -519,20 +521,20 @@
519521
} {
520522
2b 3b 4b 5b 6 7 8
521523
} {
522524
2 3 4
523525
} {
524
- > 2b 3b 4b 5b 6 7 8 = 2 3 4 <
526
+ MINE: 2b 3b 4b 5b 6 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 4 END
525527
}
526528
merge-test 85 {
527529
2 3 4 5 6 7 8
528530
} {
529531
2b 3b 4b 5b 6b 7 8
530532
} {
531533
2 3
532534
} {
533
- > 2b 3b 4b 5b 6b 7 8 = 2 3 <
535
+ MINE: 2b 3b 4b 5b 6b 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 END
534536
}
535537
536538
merge-test 90 {
537539
2 3 4 5 6 7 8
538540
} {
@@ -574,20 +576,20 @@
574576
} {
575577
2 3 4
576578
} {
577579
2b 3b 4b 5b 6 7 8
578580
} {
579
- > 2 3 4 = 2b 3b 4b 5b 6 7 8 <
581
+ MINE: 2 3 4 COM: 2 3 4 5 6 7 8 YOURS: 2b 3b 4b 5b 6 7 8 END
580582
}
581583
merge-test 95 {
582584
2 3 4 5 6 7 8
583585
} {
584586
2 3
585587
} {
586588
2b 3b 4b 5b 6b 7 8
587589
} {
588
- > 2 3 = 2b 3b 4b 5b 6b 7 8 <
590
+ MINE: 2 3 COM: 2 3 4 5 6 7 8 YOURS: 2b 3b 4b 5b 6b 7 8 END
589591
}
590592
591593
merge-test 100 {
592594
1 2 3 4 5 6 7 8 9
593595
} {
@@ -620,16 +622,16 @@
620622
} {
621623
1 2 3 4 5 7 8 9b
622624
} {
623625
1 2 3 4 5 7 8 9b a b c d e
624626
} {
625
- 1 2 3 4 5 7 8 > 9b = 9b a b c d e <
627
+ 1 2 3 4 5 7 8 MINE: 9b COM: 9 YOURS: 9b a b c d e END
626628
}
627629
merge-test 104 {
628630
1 2 3 4 5 6 7 8 9
629631
} {
630632
1 2 3 4 5 7 8 9b a b c d e
631633
} {
632634
1 2 3 4 5 7 8 9b
633635
} {
634
- 1 2 3 4 5 7 8 > 9b a b c d e = 9b <
636
+ 1 2 3 4 5 7 8 MINE: 9b a b c d e COM: 9 YOURS: 9b END
635637
}
636638
--- test/merge3.test
+++ test/merge3.test
@@ -22,13 +22,15 @@
22 write_file t1 [join [string trim $basis] \n]\n
23 write_file t2 [join [string trim $v1] \n]\n
24 write_file t3 [join [string trim $v2] \n]\n
25 fossil test-3-way-merge t1 t2 t3 t4
26 set x [read_file t4]
27 regsub -all {<<<<<<< BEGIN MERGE CONFLICT:.*<} $x {>} x
28 regsub -all {======= original content.*======} $x {=} x
29 regsub -all {>>>>>>> END MERGE CONFLICT:.*>>>} $x {<} x
 
 
30 set x [split [string trim $x] \n]
31 set result [string trim $result]
32 if {$x!=$result} {
33 protOut " Expected \[$result\]"
34 protOut " Got \[$x\]"
@@ -62,56 +64,56 @@
62 } {
63 1 2 3b 4b 5b 6 7 8 9
64 } {
65 1 2 3 4 5c 6 7 8 9
66 } {
67 1 2 > 3b 4b 5b = 3 4 5c < 6 7 8 9
68 }
69 merge-test 4 {
70 1 2 3 4 5 6 7 8 9
71 } {
72 1 2 3b 4b 5b 6b 7 8 9
73 } {
74 1 2 3 4 5c 6 7 8 9
75 } {
76 1 2 > 3b 4b 5b 6b = 3 4 5c 6 < 7 8 9
77 }
78 merge-test 5 {
79 1 2 3 4 5 6 7 8 9
80 } {
81 1 2 3b 4b 5b 6b 7 8 9
82 } {
83 1 2 3 4 5c 6c 7c 8 9
84 } {
85 1 2 > 3b 4b 5b 6b 7 = 3 4 5c 6c 7c < 8 9
86 }
87 merge-test 6 {
88 1 2 3 4 5 6 7 8 9
89 } {
90 1 2 3b 4b 5b 6b 7 8b 9
91 } {
92 1 2 3 4 5c 6c 7c 8 9
93 } {
94 1 2 > 3b 4b 5b 6b 7 = 3 4 5c 6c 7c < 8b 9
95 }
96 merge-test 7 {
97 1 2 3 4 5 6 7 8 9
98 } {
99 1 2 3b 4b 5b 6b 7 8b 9
100 } {
101 1 2 3 4 5c 6c 7c 8c 9
102 } {
103 1 2 > 3b 4b 5b 6b 7 8b = 3 4 5c 6c 7c 8c < 9
104 }
105 merge-test 8 {
106 1 2 3 4 5 6 7 8 9
107 } {
108 1 2 3b 4b 5b 6b 7 8b 9b
109 } {
110 1 2 3 4 5c 6c 7c 8c 9
111 } {
112 1 2 > 3b 4b 5b 6b 7 8b 9b = 3 4 5c 6c 7c 8c 9 <
113 }
114 merge-test 9 {
115 1 2 3 4 5 6 7 8 9
116 } {
117 1 2 3b 4b 5 6 7 8b 9b
@@ -135,11 +137,11 @@
135 } {
136 1 2 3b 4b 5 6 7 8b 9b
137 } {
138 1 2 3b 4c 5 6c 7c 8 9
139 } {
140 1 2 > 3b 4b = 3b 4c < 5 6c 7c 8b 9b
141 }
142 merge-test 12 {
143 1 2 3 4 5 6 7 8 9
144 } {
145 1 2 3b4b 5 6 7 8b 9b
@@ -190,20 +192,20 @@
190 } {
191 1 6 7 8 9
192 } {
193 1 2 3 4 9
194 } {
195 1 > 6 7 8 = 2 3 4 < 9
196 }
197 merge-test 25 {
198 1 2 3 4 5 6 7 8 9
199 } {
200 1 7 8 9
201 } {
202 1 2 3 9
203 } {
204 1 > 7 8 = 2 3 < 9
205 }
206
207 merge-test 30 {
208 1 2 3 4 5 6 7 8 9
209 } {
@@ -245,20 +247,20 @@
245 } {
246 1 2 3 4 9
247 } {
248 1 6 7 8 9
249 } {
250 1 > 2 3 4 = 6 7 8 < 9
251 }
252 merge-test 35 {
253 1 2 3 4 5 6 7 8 9
254 } {
255 1 2 3 9
256 } {
257 1 7 8 9
258 } {
259 1 > 2 3 = 7 8 < 9
260 }
261
262 merge-test 40 {
263 2 3 4 5 6 7 8
264 } {
@@ -300,20 +302,20 @@
300 } {
301 6 7 8
302 } {
303 2 3 4
304 } {
305 > 6 7 8 = 2 3 4 <
306 }
307 merge-test 45 {
308 2 3 4 5 6 7 8
309 } {
310 7 8
311 } {
312 2 3
313 } {
314 > 7 8 = 2 3 <
315 }
316
317 merge-test 50 {
318 2 3 4 5 6 7 8
319 } {
@@ -354,20 +356,20 @@
354 } {
355 2 3 4
356 } {
357 6 7 8
358 } {
359 > 2 3 4 = 6 7 8 <
360 }
361 merge-test 55 {
362 2 3 4 5 6 7 8
363 } {
364 2 3
365 } {
366 7 8
367 } {
368 > 2 3 = 7 8 <
369 }
370
371 merge-test 60 {
372 1 2 3 4 5 6 7 8 9
373 } {
@@ -409,20 +411,20 @@
409 } {
410 1 2b 3b 4b 5b 6 7 8 9
411 } {
412 1 2 3 4 9
413 } {
414 1 > 2b 3b 4b 5b 6 7 8 = 2 3 4 < 9
415 }
416 merge-test 65 {
417 1 2 3 4 5 6 7 8 9
418 } {
419 1 2b 3b 4b 5b 6b 7 8 9
420 } {
421 1 2 3 9
422 } {
423 1 > 2b 3b 4b 5b 6b 7 8 = 2 3 < 9
424 }
425
426 merge-test 70 {
427 1 2 3 4 5 6 7 8 9
428 } {
@@ -464,20 +466,20 @@
464 } {
465 1 2 3 4 9
466 } {
467 1 2b 3b 4b 5b 6 7 8 9
468 } {
469 1 > 2 3 4 = 2b 3b 4b 5b 6 7 8 < 9
470 }
471 merge-test 75 {
472 1 2 3 4 5 6 7 8 9
473 } {
474 1 2 3 9
475 } {
476 1 2b 3b 4b 5b 6b 7 8 9
477 } {
478 1 > 2 3 = 2b 3b 4b 5b 6b 7 8 < 9
479 }
480
481 merge-test 80 {
482 2 3 4 5 6 7 8
483 } {
@@ -519,20 +521,20 @@
519 } {
520 2b 3b 4b 5b 6 7 8
521 } {
522 2 3 4
523 } {
524 > 2b 3b 4b 5b 6 7 8 = 2 3 4 <
525 }
526 merge-test 85 {
527 2 3 4 5 6 7 8
528 } {
529 2b 3b 4b 5b 6b 7 8
530 } {
531 2 3
532 } {
533 > 2b 3b 4b 5b 6b 7 8 = 2 3 <
534 }
535
536 merge-test 90 {
537 2 3 4 5 6 7 8
538 } {
@@ -574,20 +576,20 @@
574 } {
575 2 3 4
576 } {
577 2b 3b 4b 5b 6 7 8
578 } {
579 > 2 3 4 = 2b 3b 4b 5b 6 7 8 <
580 }
581 merge-test 95 {
582 2 3 4 5 6 7 8
583 } {
584 2 3
585 } {
586 2b 3b 4b 5b 6b 7 8
587 } {
588 > 2 3 = 2b 3b 4b 5b 6b 7 8 <
589 }
590
591 merge-test 100 {
592 1 2 3 4 5 6 7 8 9
593 } {
@@ -620,16 +622,16 @@
620 } {
621 1 2 3 4 5 7 8 9b
622 } {
623 1 2 3 4 5 7 8 9b a b c d e
624 } {
625 1 2 3 4 5 7 8 > 9b = 9b a b c d e <
626 }
627 merge-test 104 {
628 1 2 3 4 5 6 7 8 9
629 } {
630 1 2 3 4 5 7 8 9b a b c d e
631 } {
632 1 2 3 4 5 7 8 9b
633 } {
634 1 2 3 4 5 7 8 > 9b a b c d e = 9b <
635 }
636
--- test/merge3.test
+++ test/merge3.test
@@ -22,13 +22,15 @@
22 write_file t1 [join [string trim $basis] \n]\n
23 write_file t2 [join [string trim $v1] \n]\n
24 write_file t3 [join [string trim $v2] \n]\n
25 fossil test-3-way-merge t1 t2 t3 t4
26 set x [read_file t4]
27 regsub -all {<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <+} $x \
28 {MINE:} x
29 regsub -all {======= COMMON ANCESTOR content follows =+} $x {COM:} x
30 regsub -all {======= MERGED IN content follows =+} $x {YOURS:} x
31 regsub -all {>>>>>>> END MERGE CONFLICT >+} $x {END} x
32 set x [split [string trim $x] \n]
33 set result [string trim $result]
34 if {$x!=$result} {
35 protOut " Expected \[$result\]"
36 protOut " Got \[$x\]"
@@ -62,56 +64,56 @@
64 } {
65 1 2 3b 4b 5b 6 7 8 9
66 } {
67 1 2 3 4 5c 6 7 8 9
68 } {
69 1 2 MINE: 3b 4b 5b COM: 3 4 5 YOURS: 3 4 5c END 6 7 8 9
70 }
71 merge-test 4 {
72 1 2 3 4 5 6 7 8 9
73 } {
74 1 2 3b 4b 5b 6b 7 8 9
75 } {
76 1 2 3 4 5c 6 7 8 9
77 } {
78 1 2 MINE: 3b 4b 5b 6b COM: 3 4 5 6 YOURS: 3 4 5c 6 END 7 8 9
79 }
80 merge-test 5 {
81 1 2 3 4 5 6 7 8 9
82 } {
83 1 2 3b 4b 5b 6b 7 8 9
84 } {
85 1 2 3 4 5c 6c 7c 8 9
86 } {
87 1 2 MINE: 3b 4b 5b 6b 7 COM: 3 4 5 6 7 YOURS: 3 4 5c 6c 7c END 8 9
88 }
89 merge-test 6 {
90 1 2 3 4 5 6 7 8 9
91 } {
92 1 2 3b 4b 5b 6b 7 8b 9
93 } {
94 1 2 3 4 5c 6c 7c 8 9
95 } {
96 1 2 MINE: 3b 4b 5b 6b 7 COM: 3 4 5 6 7 YOURS: 3 4 5c 6c 7c END 8b 9
97 }
98 merge-test 7 {
99 1 2 3 4 5 6 7 8 9
100 } {
101 1 2 3b 4b 5b 6b 7 8b 9
102 } {
103 1 2 3 4 5c 6c 7c 8c 9
104 } {
105 1 2 MINE: 3b 4b 5b 6b 7 8b COM: 3 4 5 6 7 8 YOURS: 3 4 5c 6c 7c 8c END 9
106 }
107 merge-test 8 {
108 1 2 3 4 5 6 7 8 9
109 } {
110 1 2 3b 4b 5b 6b 7 8b 9b
111 } {
112 1 2 3 4 5c 6c 7c 8c 9
113 } {
114 1 2 MINE: 3b 4b 5b 6b 7 8b 9b COM: 3 4 5 6 7 8 9 YOURS: 3 4 5c 6c 7c 8c 9 END
115 }
116 merge-test 9 {
117 1 2 3 4 5 6 7 8 9
118 } {
119 1 2 3b 4b 5 6 7 8b 9b
@@ -135,11 +137,11 @@
137 } {
138 1 2 3b 4b 5 6 7 8b 9b
139 } {
140 1 2 3b 4c 5 6c 7c 8 9
141 } {
142 1 2 MINE: 3b 4b COM: 3 4 YOURS: 3b 4c END 5 6c 7c 8b 9b
143 }
144 merge-test 12 {
145 1 2 3 4 5 6 7 8 9
146 } {
147 1 2 3b4b 5 6 7 8b 9b
@@ -190,20 +192,20 @@
192 } {
193 1 6 7 8 9
194 } {
195 1 2 3 4 9
196 } {
197 1 MINE: 6 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 4 END 9
198 }
199 merge-test 25 {
200 1 2 3 4 5 6 7 8 9
201 } {
202 1 7 8 9
203 } {
204 1 2 3 9
205 } {
206 1 MINE: 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 END 9
207 }
208
209 merge-test 30 {
210 1 2 3 4 5 6 7 8 9
211 } {
@@ -245,20 +247,20 @@
247 } {
248 1 2 3 4 9
249 } {
250 1 6 7 8 9
251 } {
252 1 MINE: 2 3 4 COM: 2 3 4 5 6 7 8 YOURS: 6 7 8 END 9
253 }
254 merge-test 35 {
255 1 2 3 4 5 6 7 8 9
256 } {
257 1 2 3 9
258 } {
259 1 7 8 9
260 } {
261 1 MINE: 2 3 COM: 2 3 4 5 6 7 8 YOURS: 7 8 END 9
262 }
263
264 merge-test 40 {
265 2 3 4 5 6 7 8
266 } {
@@ -300,20 +302,20 @@
302 } {
303 6 7 8
304 } {
305 2 3 4
306 } {
307 MINE: 6 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 4 END
308 }
309 merge-test 45 {
310 2 3 4 5 6 7 8
311 } {
312 7 8
313 } {
314 2 3
315 } {
316 MINE: 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 END
317 }
318
319 merge-test 50 {
320 2 3 4 5 6 7 8
321 } {
@@ -354,20 +356,20 @@
356 } {
357 2 3 4
358 } {
359 6 7 8
360 } {
361 MINE: 2 3 4 COM: 2 3 4 5 6 7 8 YOURS: 6 7 8 END
362 }
363 merge-test 55 {
364 2 3 4 5 6 7 8
365 } {
366 2 3
367 } {
368 7 8
369 } {
370 MINE: 2 3 COM: 2 3 4 5 6 7 8 YOURS: 7 8 END
371 }
372
373 merge-test 60 {
374 1 2 3 4 5 6 7 8 9
375 } {
@@ -409,20 +411,20 @@
411 } {
412 1 2b 3b 4b 5b 6 7 8 9
413 } {
414 1 2 3 4 9
415 } {
416 1 MINE: 2b 3b 4b 5b 6 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 4 END 9
417 }
418 merge-test 65 {
419 1 2 3 4 5 6 7 8 9
420 } {
421 1 2b 3b 4b 5b 6b 7 8 9
422 } {
423 1 2 3 9
424 } {
425 1 MINE: 2b 3b 4b 5b 6b 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 END 9
426 }
427
428 merge-test 70 {
429 1 2 3 4 5 6 7 8 9
430 } {
@@ -464,20 +466,20 @@
466 } {
467 1 2 3 4 9
468 } {
469 1 2b 3b 4b 5b 6 7 8 9
470 } {
471 1 MINE: 2 3 4 COM: 2 3 4 5 6 7 8 YOURS: 2b 3b 4b 5b 6 7 8 END 9
472 }
473 merge-test 75 {
474 1 2 3 4 5 6 7 8 9
475 } {
476 1 2 3 9
477 } {
478 1 2b 3b 4b 5b 6b 7 8 9
479 } {
480 1 MINE: 2 3 COM: 2 3 4 5 6 7 8 YOURS: 2b 3b 4b 5b 6b 7 8 END 9
481 }
482
483 merge-test 80 {
484 2 3 4 5 6 7 8
485 } {
@@ -519,20 +521,20 @@
521 } {
522 2b 3b 4b 5b 6 7 8
523 } {
524 2 3 4
525 } {
526 MINE: 2b 3b 4b 5b 6 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 4 END
527 }
528 merge-test 85 {
529 2 3 4 5 6 7 8
530 } {
531 2b 3b 4b 5b 6b 7 8
532 } {
533 2 3
534 } {
535 MINE: 2b 3b 4b 5b 6b 7 8 COM: 2 3 4 5 6 7 8 YOURS: 2 3 END
536 }
537
538 merge-test 90 {
539 2 3 4 5 6 7 8
540 } {
@@ -574,20 +576,20 @@
576 } {
577 2 3 4
578 } {
579 2b 3b 4b 5b 6 7 8
580 } {
581 MINE: 2 3 4 COM: 2 3 4 5 6 7 8 YOURS: 2b 3b 4b 5b 6 7 8 END
582 }
583 merge-test 95 {
584 2 3 4 5 6 7 8
585 } {
586 2 3
587 } {
588 2b 3b 4b 5b 6b 7 8
589 } {
590 MINE: 2 3 COM: 2 3 4 5 6 7 8 YOURS: 2b 3b 4b 5b 6b 7 8 END
591 }
592
593 merge-test 100 {
594 1 2 3 4 5 6 7 8 9
595 } {
@@ -620,16 +622,16 @@
622 } {
623 1 2 3 4 5 7 8 9b
624 } {
625 1 2 3 4 5 7 8 9b a b c d e
626 } {
627 1 2 3 4 5 7 8 MINE: 9b COM: 9 YOURS: 9b a b c d e END
628 }
629 merge-test 104 {
630 1 2 3 4 5 6 7 8 9
631 } {
632 1 2 3 4 5 7 8 9b a b c d e
633 } {
634 1 2 3 4 5 7 8 9b
635 } {
636 1 2 3 4 5 7 8 MINE: 9b a b c d e COM: 9 YOURS: 9b END
637 }
638
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -61,11 +61,11 @@
6161
6262
# define standard C-compiler and flags, used to compile
6363
# the fossil binary. Some special definitions follow for
6464
# special files follow
6565
CC=$(PellesCDir)\bin\pocc.exe
66
-DEFINES=-DFOSSIL_I18N=0 -D_pgmptr=g.argv[0]
66
+DEFINES=-D_pgmptr=g.argv[0]
6767
CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
6868
INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
6969
7070
# define commands for building the windows resource files
7171
RESOURCE=fossil.res
7272
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -61,11 +61,11 @@
61
62 # define standard C-compiler and flags, used to compile
63 # the fossil binary. Some special definitions follow for
64 # special files follow
65 CC=$(PellesCDir)\bin\pocc.exe
66 DEFINES=-DFOSSIL_I18N=0 -D_pgmptr=g.argv[0]
67 CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
68 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
69
70 # define commands for building the windows resource files
71 RESOURCE=fossil.res
72
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -61,11 +61,11 @@
61
62 # define standard C-compiler and flags, used to compile
63 # the fossil binary. Some special definitions follow for
64 # special files follow
65 CC=$(PellesCDir)\bin\pocc.exe
66 DEFINES=-D_pgmptr=g.argv[0]
67 CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES)
68 INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR)
69
70 # define commands for building the windows resource files
71 RESOURCE=fossil.res
72
+11 -7
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -15,22 +15,20 @@
1515
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(DMDIR)\extra\include
1616
1717
#SSL = -DFOSSIL_ENABLE_SSL=1
1818
SSL =
1919
20
-I18N = -DFOSSIL_I18N=0
21
-
2220
CFLAGS = -o
2321
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
24
-TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
22
+TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2523
LIBS = $(DMDIR)\extra\lib\ zlib wsock32
2624
2725
SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
2826
29
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c 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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
27
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c 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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
3028
31
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\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)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\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)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
29
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\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)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3230
3331
3432
RC=$(DMDIR)\bin\rcc
3533
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
3634
@@ -44,11 +42,11 @@
4442
4543
$(OBJDIR)\fossil.res: $B\win\fossil.rc
4644
$(RC) $(RCFLAGS) -o$@ $**
4745
4846
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
49
- +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip shell sqlite3 th th_lang > $@
47
+ +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip shell sqlite3 th th_lang > $@
5048
+echo fossil >> $@
5149
+echo fossil >> $@
5250
+echo $(LIBS) >> $@
5351
+echo. >> $@
5452
+echo fossil >> $@
@@ -262,10 +260,16 @@
262260
$(OBJDIR)\finfo$O : finfo_.c finfo.h
263261
$(TCC) -o$@ -c finfo_.c
264262
265263
finfo_.c : $(SRCDIR)\finfo.c
266264
+translate$E $** > $@
265
+
266
+$(OBJDIR)\glob$O : glob_.c glob.h
267
+ $(TCC) -o$@ -c glob_.c
268
+
269
+glob_.c : $(SRCDIR)\glob.c
270
+ +translate$E $** > $@
267271
268272
$(OBJDIR)\graph$O : graph_.c graph.h
269273
$(TCC) -o$@ -c graph_.c
270274
271275
graph_.c : $(SRCDIR)\graph.c
@@ -576,7 +580,7 @@
576580
577581
zip_.c : $(SRCDIR)\zip.c
578582
+translate$E $** > $@
579583
580584
headers: makeheaders$E page_index.h VERSION.h
581
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h 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 leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h 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 update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
585
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h 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 update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
582586
@copy /Y nul: headers
583587
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -15,22 +15,20 @@
15 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(DMDIR)\extra\include
16
17 #SSL = -DFOSSIL_ENABLE_SSL=1
18 SSL =
19
20 I18N = -DFOSSIL_I18N=0
21
22 CFLAGS = -o
23 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
24 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
25 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
26
27 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
28
29 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c 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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
30
31 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\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)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\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)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
32
33
34 RC=$(DMDIR)\bin\rcc
35 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
36
@@ -44,11 +42,11 @@
44
45 $(OBJDIR)\fossil.res: $B\win\fossil.rc
46 $(RC) $(RCFLAGS) -o$@ $**
47
48 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
49 +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip shell sqlite3 th th_lang > $@
50 +echo fossil >> $@
51 +echo fossil >> $@
52 +echo $(LIBS) >> $@
53 +echo. >> $@
54 +echo fossil >> $@
@@ -262,10 +260,16 @@
262 $(OBJDIR)\finfo$O : finfo_.c finfo.h
263 $(TCC) -o$@ -c finfo_.c
264
265 finfo_.c : $(SRCDIR)\finfo.c
266 +translate$E $** > $@
 
 
 
 
 
 
267
268 $(OBJDIR)\graph$O : graph_.c graph.h
269 $(TCC) -o$@ -c graph_.c
270
271 graph_.c : $(SRCDIR)\graph.c
@@ -576,7 +580,7 @@
576
577 zip_.c : $(SRCDIR)\zip.c
578 +translate$E $** > $@
579
580 headers: makeheaders$E page_index.h VERSION.h
581 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h 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 leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h 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 update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
582 @copy /Y nul: headers
583
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -15,22 +15,20 @@
15 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(DMDIR)\extra\include
16
17 #SSL = -DFOSSIL_ENABLE_SSL=1
18 SSL =
19
 
 
20 CFLAGS = -o
21 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
22 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
23 LIBS = $(DMDIR)\extra\lib\ zlib wsock32
24
25 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
26
27 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c 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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
28
29 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\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)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
30
31
32 RC=$(DMDIR)\bin\rcc
33 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
34
@@ -44,11 +42,11 @@
42
43 $(OBJDIR)\fossil.res: $B\win\fossil.rc
44 $(RC) $(RCFLAGS) -o$@ $**
45
46 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
47 +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip shell sqlite3 th th_lang > $@
48 +echo fossil >> $@
49 +echo fossil >> $@
50 +echo $(LIBS) >> $@
51 +echo. >> $@
52 +echo fossil >> $@
@@ -262,10 +260,16 @@
260 $(OBJDIR)\finfo$O : finfo_.c finfo.h
261 $(TCC) -o$@ -c finfo_.c
262
263 finfo_.c : $(SRCDIR)\finfo.c
264 +translate$E $** > $@
265
266 $(OBJDIR)\glob$O : glob_.c glob.h
267 $(TCC) -o$@ -c glob_.c
268
269 glob_.c : $(SRCDIR)\glob.c
270 +translate$E $** > $@
271
272 $(OBJDIR)\graph$O : graph_.c graph.h
273 $(TCC) -o$@ -c graph_.c
274
275 graph_.c : $(SRCDIR)\graph.c
@@ -576,7 +580,7 @@
580
581 zip_.c : $(SRCDIR)\zip.c
582 +translate$E $** > $@
583
584 headers: makeheaders$E page_index.h VERSION.h
585 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h 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 update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
586 @copy /Y nul: headers
587
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -33,11 +33,11 @@
3333
# will run on the target platform. This is usually the same
3434
# as BCC, unless you are cross-compiling. This C compiler builds
3535
# the finished binary for fossil. The BCC compiler above is used
3636
# for building intermediate code-generator tools.
3737
#
38
-TCC = gcc -Os -Wall -DFOSSIL_I18N=0 -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include
38
+TCC = gcc -Os -Wall -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include
3939
4040
# With HTTPS support
4141
ifdef FOSSIL_ENABLE_SSL
4242
TCC += -static -DFOSSIL_ENABLE_SSL=1
4343
endif
@@ -101,10 +101,11 @@
101101
$(SRCDIR)/encode.c \
102102
$(SRCDIR)/event.c \
103103
$(SRCDIR)/export.c \
104104
$(SRCDIR)/file.c \
105105
$(SRCDIR)/finfo.c \
106
+ $(SRCDIR)/glob.c \
106107
$(SRCDIR)/graph.c \
107108
$(SRCDIR)/gzip.c \
108109
$(SRCDIR)/http.c \
109110
$(SRCDIR)/http_socket.c \
110111
$(SRCDIR)/http_ssl.c \
@@ -184,10 +185,11 @@
184185
$(OBJDIR)/encode_.c \
185186
$(OBJDIR)/event_.c \
186187
$(OBJDIR)/export_.c \
187188
$(OBJDIR)/file_.c \
188189
$(OBJDIR)/finfo_.c \
190
+ $(OBJDIR)/glob_.c \
189191
$(OBJDIR)/graph_.c \
190192
$(OBJDIR)/gzip_.c \
191193
$(OBJDIR)/http_.c \
192194
$(OBJDIR)/http_socket_.c \
193195
$(OBJDIR)/http_ssl_.c \
@@ -267,10 +269,11 @@
267269
$(OBJDIR)/encode.o \
268270
$(OBJDIR)/event.o \
269271
$(OBJDIR)/export.o \
270272
$(OBJDIR)/file.o \
271273
$(OBJDIR)/finfo.o \
274
+ $(OBJDIR)/glob.o \
272275
$(OBJDIR)/graph.o \
273276
$(OBJDIR)/gzip.o \
274277
$(OBJDIR)/http.o \
275278
$(OBJDIR)/http_socket.o \
276279
$(OBJDIR)/http_ssl.o \
@@ -385,11 +388,11 @@
385388
386389
387390
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
388391
$(MKINDEX) $(TRANS_SRC) >$@
389392
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
390
- $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
393
+ $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
391394
echo Done >$(OBJDIR)/headers
392395
393396
$(OBJDIR)/headers: Makefile
394397
Makefile:
395398
$(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -593,10 +596,17 @@
593596
594597
$(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
595598
$(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
596599
597600
finfo.h: $(OBJDIR)/headers
601
+$(OBJDIR)/glob_.c: $(SRCDIR)/glob.c $(OBJDIR)/translate
602
+ $(TRANSLATE) $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c
603
+
604
+$(OBJDIR)/glob.o: $(OBJDIR)/glob_.c $(OBJDIR)/glob.h $(SRCDIR)/config.h
605
+ $(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c
606
+
607
+glob.h: $(OBJDIR)/headers
598608
$(OBJDIR)/graph_.c: $(SRCDIR)/graph.c $(OBJDIR)/translate
599609
$(TRANSLATE) $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c
600610
601611
$(OBJDIR)/graph.o: $(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
602612
$(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c
603613
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -33,11 +33,11 @@
33 # will run on the target platform. This is usually the same
34 # as BCC, unless you are cross-compiling. This C compiler builds
35 # the finished binary for fossil. The BCC compiler above is used
36 # for building intermediate code-generator tools.
37 #
38 TCC = gcc -Os -Wall -DFOSSIL_I18N=0 -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include
39
40 # With HTTPS support
41 ifdef FOSSIL_ENABLE_SSL
42 TCC += -static -DFOSSIL_ENABLE_SSL=1
43 endif
@@ -101,10 +101,11 @@
101 $(SRCDIR)/encode.c \
102 $(SRCDIR)/event.c \
103 $(SRCDIR)/export.c \
104 $(SRCDIR)/file.c \
105 $(SRCDIR)/finfo.c \
 
106 $(SRCDIR)/graph.c \
107 $(SRCDIR)/gzip.c \
108 $(SRCDIR)/http.c \
109 $(SRCDIR)/http_socket.c \
110 $(SRCDIR)/http_ssl.c \
@@ -184,10 +185,11 @@
184 $(OBJDIR)/encode_.c \
185 $(OBJDIR)/event_.c \
186 $(OBJDIR)/export_.c \
187 $(OBJDIR)/file_.c \
188 $(OBJDIR)/finfo_.c \
 
189 $(OBJDIR)/graph_.c \
190 $(OBJDIR)/gzip_.c \
191 $(OBJDIR)/http_.c \
192 $(OBJDIR)/http_socket_.c \
193 $(OBJDIR)/http_ssl_.c \
@@ -267,10 +269,11 @@
267 $(OBJDIR)/encode.o \
268 $(OBJDIR)/event.o \
269 $(OBJDIR)/export.o \
270 $(OBJDIR)/file.o \
271 $(OBJDIR)/finfo.o \
 
272 $(OBJDIR)/graph.o \
273 $(OBJDIR)/gzip.o \
274 $(OBJDIR)/http.o \
275 $(OBJDIR)/http_socket.o \
276 $(OBJDIR)/http_ssl.o \
@@ -385,11 +388,11 @@
385
386
387 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
388 $(MKINDEX) $(TRANS_SRC) >$@
389 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
390 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
391 echo Done >$(OBJDIR)/headers
392
393 $(OBJDIR)/headers: Makefile
394 Makefile:
395 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -593,10 +596,17 @@
593
594 $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
595 $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
596
597 finfo.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
598 $(OBJDIR)/graph_.c: $(SRCDIR)/graph.c $(OBJDIR)/translate
599 $(TRANSLATE) $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c
600
601 $(OBJDIR)/graph.o: $(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
602 $(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c
603
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -33,11 +33,11 @@
33 # will run on the target platform. This is usually the same
34 # as BCC, unless you are cross-compiling. This C compiler builds
35 # the finished binary for fossil. The BCC compiler above is used
36 # for building intermediate code-generator tools.
37 #
38 TCC = gcc -Os -Wall -L$(ZLIBDIR)/lib -I$(ZLIBDIR)/include
39
40 # With HTTPS support
41 ifdef FOSSIL_ENABLE_SSL
42 TCC += -static -DFOSSIL_ENABLE_SSL=1
43 endif
@@ -101,10 +101,11 @@
101 $(SRCDIR)/encode.c \
102 $(SRCDIR)/event.c \
103 $(SRCDIR)/export.c \
104 $(SRCDIR)/file.c \
105 $(SRCDIR)/finfo.c \
106 $(SRCDIR)/glob.c \
107 $(SRCDIR)/graph.c \
108 $(SRCDIR)/gzip.c \
109 $(SRCDIR)/http.c \
110 $(SRCDIR)/http_socket.c \
111 $(SRCDIR)/http_ssl.c \
@@ -184,10 +185,11 @@
185 $(OBJDIR)/encode_.c \
186 $(OBJDIR)/event_.c \
187 $(OBJDIR)/export_.c \
188 $(OBJDIR)/file_.c \
189 $(OBJDIR)/finfo_.c \
190 $(OBJDIR)/glob_.c \
191 $(OBJDIR)/graph_.c \
192 $(OBJDIR)/gzip_.c \
193 $(OBJDIR)/http_.c \
194 $(OBJDIR)/http_socket_.c \
195 $(OBJDIR)/http_ssl_.c \
@@ -267,10 +269,11 @@
269 $(OBJDIR)/encode.o \
270 $(OBJDIR)/event.o \
271 $(OBJDIR)/export.o \
272 $(OBJDIR)/file.o \
273 $(OBJDIR)/finfo.o \
274 $(OBJDIR)/glob.o \
275 $(OBJDIR)/graph.o \
276 $(OBJDIR)/gzip.o \
277 $(OBJDIR)/http.o \
278 $(OBJDIR)/http_socket.o \
279 $(OBJDIR)/http_ssl.o \
@@ -385,11 +388,11 @@
388
389
390 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
391 $(MKINDEX) $(TRANS_SRC) >$@
392 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
393 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
394 echo Done >$(OBJDIR)/headers
395
396 $(OBJDIR)/headers: Makefile
397 Makefile:
398 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
@@ -593,10 +596,17 @@
596
597 $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h
598 $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c
599
600 finfo.h: $(OBJDIR)/headers
601 $(OBJDIR)/glob_.c: $(SRCDIR)/glob.c $(OBJDIR)/translate
602 $(TRANSLATE) $(SRCDIR)/glob.c >$(OBJDIR)/glob_.c
603
604 $(OBJDIR)/glob.o: $(OBJDIR)/glob_.c $(OBJDIR)/glob.h $(SRCDIR)/config.h
605 $(XTCC) -o $(OBJDIR)/glob.o -c $(OBJDIR)/glob_.c
606
607 glob.h: $(OBJDIR)/headers
608 $(OBJDIR)/graph_.c: $(SRCDIR)/graph.c $(OBJDIR)/translate
609 $(TRANSLATE) $(SRCDIR)/graph.c >$(OBJDIR)/graph_.c
610
611 $(OBJDIR)/graph.o: $(OBJDIR)/graph_.c $(OBJDIR)/graph.h $(SRCDIR)/config.h
612 $(XTCC) -o $(OBJDIR)/graph.o -c $(OBJDIR)/graph_.c
613
+11 -7
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -28,23 +28,21 @@
2828
ZLIBDIR = $(MSCDIR)\extra\lib
2929
ZLIB = zlib.lib
3030
3131
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
3232
33
-I18N = -DFOSSIL_I18N=0
34
-
3533
CFLAGS = -nologo -MT -O2
3634
BCC = $(CC) $(CFLAGS)
37
-TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(I18N) $(SSL) $(INCL)
35
+TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
3836
LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
3937
LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
4038
4139
SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT2 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
4240
43
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c 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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
41
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c 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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
4442
45
-OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
43
+OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
4644
4745
4846
APPNAME = $(OX)\fossil$(E)
4947
5048
all: $(OX) $(APPNAME)
@@ -52,11 +50,11 @@
5250
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
5351
cd $(OX)
5452
link -LINK -OUT:$@ $(LIBDIR) @linkopts
5553
5654
$(OX)\linkopts: $B\win\Makefile.msc
57
- echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
55
+ echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
5856
echo $(LIBS) >> $@
5957
6058
6159
6260
@@ -273,10 +271,16 @@
273271
$(OX)\finfo$O : finfo_.c finfo.h
274272
$(TCC) /Fo$@ -c finfo_.c
275273
276274
finfo_.c : $(SRCDIR)\finfo.c
277275
translate$E $** > $@
276
+
277
+$(OX)\glob$O : glob_.c glob.h
278
+ $(TCC) /Fo$@ -c glob_.c
279
+
280
+glob_.c : $(SRCDIR)\glob.c
281
+ translate$E $** > $@
278282
279283
$(OX)\graph$O : graph_.c graph.h
280284
$(TCC) /Fo$@ -c graph_.c
281285
282286
graph_.c : $(SRCDIR)\graph.c
@@ -587,7 +591,7 @@
587591
588592
zip_.c : $(SRCDIR)\zip.c
589593
translate$E $** > $@
590594
591595
headers: makeheaders$E page_index.h VERSION.h
592
- makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h 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 leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h 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 update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
596
+ makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h 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 update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
593597
@copy /Y nul: headers
594598
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -28,23 +28,21 @@
28 ZLIBDIR = $(MSCDIR)\extra\lib
29 ZLIB = zlib.lib
30
31 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
32
33 I18N = -DFOSSIL_I18N=0
34
35 CFLAGS = -nologo -MT -O2
36 BCC = $(CC) $(CFLAGS)
37 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(I18N) $(SSL) $(INCL)
38 LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
39 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
40
41 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT2 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
42
43 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c 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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
44
45 OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
46
47
48 APPNAME = $(OX)\fossil$(E)
49
50 all: $(OX) $(APPNAME)
@@ -52,11 +50,11 @@
52 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
53 cd $(OX)
54 link -LINK -OUT:$@ $(LIBDIR) @linkopts
55
56 $(OX)\linkopts: $B\win\Makefile.msc
57 echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
58 echo $(LIBS) >> $@
59
60
61
62
@@ -273,10 +271,16 @@
273 $(OX)\finfo$O : finfo_.c finfo.h
274 $(TCC) /Fo$@ -c finfo_.c
275
276 finfo_.c : $(SRCDIR)\finfo.c
277 translate$E $** > $@
 
 
 
 
 
 
278
279 $(OX)\graph$O : graph_.c graph.h
280 $(TCC) /Fo$@ -c graph_.c
281
282 graph_.c : $(SRCDIR)\graph.c
@@ -587,7 +591,7 @@
587
588 zip_.c : $(SRCDIR)\zip.c
589 translate$E $** > $@
590
591 headers: makeheaders$E page_index.h VERSION.h
592 makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h 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 leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h 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 update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
593 @copy /Y nul: headers
594
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -28,23 +28,21 @@
28 ZLIBDIR = $(MSCDIR)\extra\lib
29 ZLIB = zlib.lib
30
31 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
32
 
 
33 CFLAGS = -nologo -MT -O2
34 BCC = $(CC) $(CFLAGS)
35 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
36 LIBS = $(ZLIB) ws2_32.lib $(SSLLIB)
37 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
38
39 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT2 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
40
41 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c 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 update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c
42
43 OBJ = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\glob$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O
44
45
46 APPNAME = $(OX)\fossil$(E)
47
48 all: $(OX) $(APPNAME)
@@ -52,11 +50,11 @@
50 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
51 cd $(OX)
52 link -LINK -OUT:$@ $(LIBDIR) @linkopts
53
54 $(OX)\linkopts: $B\win\Makefile.msc
55 echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
56 echo $(LIBS) >> $@
57
58
59
60
@@ -273,10 +271,16 @@
271 $(OX)\finfo$O : finfo_.c finfo.h
272 $(TCC) /Fo$@ -c finfo_.c
273
274 finfo_.c : $(SRCDIR)\finfo.c
275 translate$E $** > $@
276
277 $(OX)\glob$O : glob_.c glob.h
278 $(TCC) /Fo$@ -c glob_.c
279
280 glob_.c : $(SRCDIR)\glob.c
281 translate$E $** > $@
282
283 $(OX)\graph$O : graph_.c graph.h
284 $(TCC) /Fo$@ -c graph_.c
285
286 graph_.c : $(SRCDIR)\graph.c
@@ -587,7 +591,7 @@
591
592 zip_.c : $(SRCDIR)\zip.c
593 translate$E $** > $@
594
595 headers: makeheaders$E page_index.h VERSION.h
596 makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h 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 update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
597 @copy /Y nul: headers
598
--- www/fossil_logo_small.gif
+++ www/fossil_logo_small.gif
cannot compute difference between binary files
11
--- www/fossil_logo_small.gif
+++ www/fossil_logo_small.gif
0 annot compute difference between binary files
1
--- www/fossil_logo_small.gif
+++ www/fossil_logo_small.gif
0 annot compute difference between binary files
1
+52 -26
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -1,11 +1,13 @@
11
#!/usr/bin/tclsh
22
#
3
-# Run this script to build the "download.html" page on standard output.
3
+# Run this script to build the "download.html" page. Also generate
4
+# the fossil_download_checksums.html page.
45
#
56
#
6
-puts \
7
+set out [open download.html w]
8
+puts $out \
79
{<html>
810
<head>
911
<title>Fossil: Downloads</title>
1012
<link rel="stylesheet" href="/fossil/style.css" type="text/css"
1113
media="screen">
@@ -22,14 +24,17 @@
2224
<p>
2325
2426
<center><font size=4>
2527
<b>To install Fossil &rarr;</b> download the stand-alone executable
2628
and put it on your $PATH.
27
-</font><p>
29
+</font><p><small>
2830
RPMs available
2931
<a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/">
30
-here</a>
32
+here.</a>
33
+Cryptographic checksums for download files are
34
+<a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>.
35
+</small></p>
3136
</center>
3237
3338
<table cellpadding="10">
3439
}
3540
@@ -49,13 +54,13 @@
4954
append dt "[string range $datetime 6 7] "
5055
append dt "[string range $datetime 8 9]:[string range $datetime 10 11]:"
5156
append dt "[string range $datetime 12 13]"
5257
set link [string map {{ } +} $dt]
5358
set hr http://www.fossil-scm.org/fossil/timeline?c=$link&y=ci
54
- puts "<tr><td colspan=6 align=left><hr>"
55
- puts "<center><b><a href=\"$hr\">$dt</a></b></center>"
56
- puts "</td></tr>"
59
+ puts $out "<tr><td colspan=6 align=left><hr>"
60
+ puts $out "<center><b><a href=\"$hr\">$dt</a></b></center>"
61
+ puts $out "</td></tr>"
5762
5863
foreach {prefix suffix img desc} {
5964
fossil-linux-x86 zip linux.gif {Linux x86}
6065
fossil-linux-amd64 zip linux64.gif {Linux x86_64}
6166
fossil-macosx-x86 zip mac.gif {Mac 10.5 x86}
@@ -72,27 +77,48 @@
7277
set units MiB
7378
} elseif {$size>1024} {
7479
set size [format %.2f [expr {$size/(1024.0)}]]
7580
set units KiB
7681
}
77
- puts "<td align=center valign=bottom><a href=\"$filename\">"
78
- puts "<img src=\"build-icons/$img\" border=0><br>$desc</a><br>"
79
- puts "$size $units</td>"
80
- } else {
81
- puts "<td>&nbsp;</td>"
82
- }
83
- }
84
- puts "</tr>"
85
- if {[file exists download/releasenotes-$datetime.html]} {
86
- puts "<tr><td colspan=6 align=left>"
87
- set rn [open download/releasenotes-$datetime.html]
88
- puts "[read $rn]"
89
- close $rn
90
- puts "</td></tr>"
91
- }
92
-}
93
-puts "<tr><td colspan=5><hr></td></tr>"
94
-
95
-puts {</table>
82
+ puts $out "<td align=center valign=bottom><a href=\"$filename\">"
83
+ puts $out "<img src=\"build-icons/$img\" border=0><br>$desc</a><br>"
84
+ puts $out "$size $units</td>"
85
+ } else {
86
+ puts $out "<td>&nbsp;</td>"
87
+ }
88
+ }
89
+ puts $out "</tr>"
90
+ if {[file exists download/releasenotes-$datetime.html]} {
91
+ puts $out "<tr><td colspan=6 align=left>"
92
+ set rn [open download/releasenotes-$datetime.html]
93
+ puts $out "[read $rn]"
94
+ close $rn
95
+ puts $out "</td></tr>"
96
+ }
97
+}
98
+puts $out "<tr><td colspan=5><hr></td></tr>"
99
+
100
+puts $out {</table>
96101
</body>
97102
</html>
98103
}
104
+
105
+close $out
106
+
107
+# Generate the checksum page
108
+#
109
+set out [open fossil_download_checksums.html w]
110
+puts $out {<html>
111
+<title>Fossil Download Checksums</title>
112
+<body>
113
+<h1 align="center">Checksums For Fossil Downloads</h1>
114
+<p>The following table shows the SHA1 checksums for the precompiled
115
+binaries available on the
116
+<a href="http://www.fossil-scm.org/download.html">Fossil website</a>.</p>
117
+<pre>}
118
+
119
+foreach file [lsort [glob -nocomplain download/fossil-*.zip]] {
120
+ set sha1sum [lindex [exec sha1sum $file] 0]
121
+ puts $out "$sha1sum [file tail $file]"
122
+}
123
+puts $out {</pre></body></html}
124
+close $out
99125
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -1,11 +1,13 @@
1 #!/usr/bin/tclsh
2 #
3 # Run this script to build the "download.html" page on standard output.
 
4 #
5 #
6 puts \
 
7 {<html>
8 <head>
9 <title>Fossil: Downloads</title>
10 <link rel="stylesheet" href="/fossil/style.css" type="text/css"
11 media="screen">
@@ -22,14 +24,17 @@
22 <p>
23
24 <center><font size=4>
25 <b>To install Fossil &rarr;</b> download the stand-alone executable
26 and put it on your $PATH.
27 </font><p>
28 RPMs available
29 <a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/">
30 here</a>
 
 
 
31 </center>
32
33 <table cellpadding="10">
34 }
35
@@ -49,13 +54,13 @@
49 append dt "[string range $datetime 6 7] "
50 append dt "[string range $datetime 8 9]:[string range $datetime 10 11]:"
51 append dt "[string range $datetime 12 13]"
52 set link [string map {{ } +} $dt]
53 set hr http://www.fossil-scm.org/fossil/timeline?c=$link&y=ci
54 puts "<tr><td colspan=6 align=left><hr>"
55 puts "<center><b><a href=\"$hr\">$dt</a></b></center>"
56 puts "</td></tr>"
57
58 foreach {prefix suffix img desc} {
59 fossil-linux-x86 zip linux.gif {Linux x86}
60 fossil-linux-amd64 zip linux64.gif {Linux x86_64}
61 fossil-macosx-x86 zip mac.gif {Mac 10.5 x86}
@@ -72,27 +77,48 @@
72 set units MiB
73 } elseif {$size>1024} {
74 set size [format %.2f [expr {$size/(1024.0)}]]
75 set units KiB
76 }
77 puts "<td align=center valign=bottom><a href=\"$filename\">"
78 puts "<img src=\"build-icons/$img\" border=0><br>$desc</a><br>"
79 puts "$size $units</td>"
80 } else {
81 puts "<td>&nbsp;</td>"
82 }
83 }
84 puts "</tr>"
85 if {[file exists download/releasenotes-$datetime.html]} {
86 puts "<tr><td colspan=6 align=left>"
87 set rn [open download/releasenotes-$datetime.html]
88 puts "[read $rn]"
89 close $rn
90 puts "</td></tr>"
91 }
92 }
93 puts "<tr><td colspan=5><hr></td></tr>"
94
95 puts {</table>
96 </body>
97 </html>
98 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -1,11 +1,13 @@
1 #!/usr/bin/tclsh
2 #
3 # Run this script to build the "download.html" page. Also generate
4 # the fossil_download_checksums.html page.
5 #
6 #
7 set out [open download.html w]
8 puts $out \
9 {<html>
10 <head>
11 <title>Fossil: Downloads</title>
12 <link rel="stylesheet" href="/fossil/style.css" type="text/css"
13 media="screen">
@@ -22,14 +24,17 @@
24 <p>
25
26 <center><font size=4>
27 <b>To install Fossil &rarr;</b> download the stand-alone executable
28 and put it on your $PATH.
29 </font><p><small>
30 RPMs available
31 <a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/">
32 here.</a>
33 Cryptographic checksums for download files are
34 <a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>.
35 </small></p>
36 </center>
37
38 <table cellpadding="10">
39 }
40
@@ -49,13 +54,13 @@
54 append dt "[string range $datetime 6 7] "
55 append dt "[string range $datetime 8 9]:[string range $datetime 10 11]:"
56 append dt "[string range $datetime 12 13]"
57 set link [string map {{ } +} $dt]
58 set hr http://www.fossil-scm.org/fossil/timeline?c=$link&y=ci
59 puts $out "<tr><td colspan=6 align=left><hr>"
60 puts $out "<center><b><a href=\"$hr\">$dt</a></b></center>"
61 puts $out "</td></tr>"
62
63 foreach {prefix suffix img desc} {
64 fossil-linux-x86 zip linux.gif {Linux x86}
65 fossil-linux-amd64 zip linux64.gif {Linux x86_64}
66 fossil-macosx-x86 zip mac.gif {Mac 10.5 x86}
@@ -72,27 +77,48 @@
77 set units MiB
78 } elseif {$size>1024} {
79 set size [format %.2f [expr {$size/(1024.0)}]]
80 set units KiB
81 }
82 puts $out "<td align=center valign=bottom><a href=\"$filename\">"
83 puts $out "<img src=\"build-icons/$img\" border=0><br>$desc</a><br>"
84 puts $out "$size $units</td>"
85 } else {
86 puts $out "<td>&nbsp;</td>"
87 }
88 }
89 puts $out "</tr>"
90 if {[file exists download/releasenotes-$datetime.html]} {
91 puts $out "<tr><td colspan=6 align=left>"
92 set rn [open download/releasenotes-$datetime.html]
93 puts $out "[read $rn]"
94 close $rn
95 puts $out "</td></tr>"
96 }
97 }
98 puts $out "<tr><td colspan=5><hr></td></tr>"
99
100 puts $out {</table>
101 </body>
102 </html>
103 }
104
105 close $out
106
107 # Generate the checksum page
108 #
109 set out [open fossil_download_checksums.html w]
110 puts $out {<html>
111 <title>Fossil Download Checksums</title>
112 <body>
113 <h1 align="center">Checksums For Fossil Downloads</h1>
114 <p>The following table shows the SHA1 checksums for the precompiled
115 binaries available on the
116 <a href="http://www.fossil-scm.org/download.html">Fossil website</a>.</p>
117 <pre>}
118
119 foreach file [lsort [glob -nocomplain download/fossil-*.zip]] {
120 set sha1sum [lindex [exec sha1sum $file] 0]
121 puts $out "$sha1sum [file tail $file]"
122 }
123 puts $out {</pre></body></html}
124 close $out
125
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -58,8 +58,8 @@
5858
<blockquote><pre>
5959
/home/hwaci/bin/fossil sync -R /home/hwaci/fossil/fossil.fossil
6060
</pre></blockquote>
6161
6262
Server (2) is a
63
-<a href="http://www.linode.com/">Linode 512</a> located in Atlanta, GA
63
+<a href="http://www.linode.com/">Linode 512</a> located in Newark, NJ
6464
and set up just like the canonical server (1) with the addition of a
6565
cron job for synchronization as in server (3).
6666
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -58,8 +58,8 @@
58 <blockquote><pre>
59 /home/hwaci/bin/fossil sync -R /home/hwaci/fossil/fossil.fossil
60 </pre></blockquote>
61
62 Server (2) is a
63 <a href="http://www.linode.com/">Linode 512</a> located in Atlanta, GA
64 and set up just like the canonical server (1) with the addition of a
65 cron job for synchronization as in server (3).
66
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -58,8 +58,8 @@
58 <blockquote><pre>
59 /home/hwaci/bin/fossil sync -R /home/hwaci/fossil/fossil.fossil
60 </pre></blockquote>
61
62 Server (2) is a
63 <a href="http://www.linode.com/">Linode 512</a> located in Newark, NJ
64 and set up just like the canonical server (1) with the addition of a
65 cron job for synchronization as in server (3).
66
+8 -3
--- www/server.wiki
+++ www/server.wiki
@@ -15,11 +15,13 @@
1515
<p>
1616
Both of these commands start a Fossil server on port 8080 on the local machine,
1717
which can be accessed with the URL: <tt>http://localhost:8080/</tt> using any
1818
handy web browser. The difference between the two commands is that "ui", in
1919
addition to starting the Fossil server, also starts a web browser and points it
20
-to the URL mentioned above.
20
+to the URL mentioned above. On the other hand, the "ui" command binds to
21
+the loopback IP address only (127.0.0.1) so that the "ui" command cannot be
22
+used to serve content to a different machine.
2123
</p>
2224
<p>
2325
NOTES:
2426
<ol>
2527
<li>The option "--port NNN" will start the server on port "NNN" instead of 8080.
@@ -70,19 +72,22 @@
7072
</p>
7173
</blockquote>
7274
7375
<h3>Serving multiple repositories with one script</h3><blockquote>
7476
<p>
75
-This scenario is almost identical to the previous one. However, here we will assume you have multiple repositories, in one directory (call it 'fossils'). So as before, create a script (again, 'repo'):
77
+This scenario is almost identical to the previous one. However, here we will assume you have multiple repositories, in one directory.
78
+(Call the directory 'fossils'). All repositories served, in this case, must
79
+use the ".fossil" filename suffix.
80
+As before, create a script (again, 'repo'):
7681
<blockquote><tt>
7782
#!/path-to/fossil<br>
7883
directory: /path-to-repo/fossils<br>
7984
notfound: http://url-to-go-to-if-repo-not-found/
8085
</tt></blockquote>
8186
</p>
8287
<p>
83
-Once deployed, a URL like: <tt>http://mydomain.org/cgi-bin/repo/XYZ</tt> will serve up the repository "fossils/XYX" (if it exists). This makes serving multiple projects on one server pretty painless.
88
+Once deployed, a URL like: <tt>http://mydomain.org/cgi-bin/repo/XYZ</tt> will serve up the repository "fossils/XYX.fossil" (if it exists). This makes serving multiple projects on one server pretty painless.
8489
</p>
8590
</blockquote>
8691
8792
<h2>Securing a repository with SSL</h2><blockquote>
8893
<p>
8994
--- www/server.wiki
+++ www/server.wiki
@@ -15,11 +15,13 @@
15 <p>
16 Both of these commands start a Fossil server on port 8080 on the local machine,
17 which can be accessed with the URL: <tt>http://localhost:8080/</tt> using any
18 handy web browser. The difference between the two commands is that "ui", in
19 addition to starting the Fossil server, also starts a web browser and points it
20 to the URL mentioned above.
 
 
21 </p>
22 <p>
23 NOTES:
24 <ol>
25 <li>The option "--port NNN" will start the server on port "NNN" instead of 8080.
@@ -70,19 +72,22 @@
70 </p>
71 </blockquote>
72
73 <h3>Serving multiple repositories with one script</h3><blockquote>
74 <p>
75 This scenario is almost identical to the previous one. However, here we will assume you have multiple repositories, in one directory (call it 'fossils'). So as before, create a script (again, 'repo'):
 
 
 
76 <blockquote><tt>
77 #!/path-to/fossil<br>
78 directory: /path-to-repo/fossils<br>
79 notfound: http://url-to-go-to-if-repo-not-found/
80 </tt></blockquote>
81 </p>
82 <p>
83 Once deployed, a URL like: <tt>http://mydomain.org/cgi-bin/repo/XYZ</tt> will serve up the repository "fossils/XYX" (if it exists). This makes serving multiple projects on one server pretty painless.
84 </p>
85 </blockquote>
86
87 <h2>Securing a repository with SSL</h2><blockquote>
88 <p>
89
--- www/server.wiki
+++ www/server.wiki
@@ -15,11 +15,13 @@
15 <p>
16 Both of these commands start a Fossil server on port 8080 on the local machine,
17 which can be accessed with the URL: <tt>http://localhost:8080/</tt> using any
18 handy web browser. The difference between the two commands is that "ui", in
19 addition to starting the Fossil server, also starts a web browser and points it
20 to the URL mentioned above. On the other hand, the "ui" command binds to
21 the loopback IP address only (127.0.0.1) so that the "ui" command cannot be
22 used to serve content to a different machine.
23 </p>
24 <p>
25 NOTES:
26 <ol>
27 <li>The option "--port NNN" will start the server on port "NNN" instead of 8080.
@@ -70,19 +72,22 @@
72 </p>
73 </blockquote>
74
75 <h3>Serving multiple repositories with one script</h3><blockquote>
76 <p>
77 This scenario is almost identical to the previous one. However, here we will assume you have multiple repositories, in one directory.
78 (Call the directory 'fossils'). All repositories served, in this case, must
79 use the ".fossil" filename suffix.
80 As before, create a script (again, 'repo'):
81 <blockquote><tt>
82 #!/path-to/fossil<br>
83 directory: /path-to-repo/fossils<br>
84 notfound: http://url-to-go-to-if-repo-not-found/
85 </tt></blockquote>
86 </p>
87 <p>
88 Once deployed, a URL like: <tt>http://mydomain.org/cgi-bin/repo/XYZ</tt> will serve up the repository "fossils/XYX.fossil" (if it exists). This makes serving multiple projects on one server pretty painless.
89 </p>
90 </blockquote>
91
92 <h2>Securing a repository with SSL</h2><blockquote>
93 <p>
94

Keyboard Shortcuts

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