Fossil SCM

Updating from trunk.

viriketo 2012-10-16 12:19 annotate_links merge
Commit 3cdf9480dd9f1889ad791fe731c5c073c5926d74
+7 -12
--- src/add.c
+++ src/add.c
@@ -21,16 +21,10 @@
2121
#include "config.h"
2222
#include "add.h"
2323
#include <assert.h>
2424
#include <dirent.h>
2525
26
-/*
27
-** Set to true if files whose names begin with "." should be
28
-** included when processing a recursive "add" command.
29
-*/
30
-static int includeDotFiles = 0;
31
-
3226
/*
3327
** This routine returns the names of files in a working checkout that
3428
** are created by Fossil itself, and hence should not be added, deleted,
3529
** or merge, and should be omitted from "clean" and "extra" lists.
3630
**
@@ -39,11 +33,11 @@
3933
*/
4034
const char *fossil_reserved_name(int N){
4135
/* Possible names of the local per-checkout database file and
4236
** its associated journals
4337
*/
44
- static const char *azName[] = {
38
+ static const char *const azName[] = {
4539
"_FOSSIL_",
4640
"_FOSSIL_-journal",
4741
"_FOSSIL_-wal",
4842
"_FOSSIL_-shm",
4943
".fslckout",
@@ -61,11 +55,11 @@
6155
};
6256
6357
/* Names of auxiliary files generated by SQLite when the "manifest"
6458
** properity is enabled
6559
*/
66
- static const char *azManifest[] = {
60
+ static const char *const azManifest[] = {
6761
"manifest",
6862
"manifest.uuid",
6963
};
7064
7165
/* Cached setting "manifest" */
@@ -216,13 +210,14 @@
216210
int vid; /* Currently checked out version */
217211
int nRoot; /* Full path characters in g.zLocalRoot */
218212
const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
219213
Glob *pIgnore; /* Ignore everything matching this glob pattern */
220214
int caseSensitive; /* True if filenames are case sensitive */
215
+ unsigned scanFlags = 0; /* Flags passed to vfile_scan() */
221216
222217
zIgnoreFlag = find_option("ignore",0,1);
223
- includeDotFiles = find_option("dotfiles",0,0)!=0;
218
+ if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
224219
capture_case_sensitive_option();
225220
db_must_be_within_tree();
226221
caseSensitive = filenames_are_case_sensitive();
227222
if( zIgnoreFlag==0 ){
228223
zIgnoreFlag = db_get("ignore-glob", 0);
@@ -250,11 +245,11 @@
250245
251246
file_canonical_name(g.argv[i], &fullName, 0);
252247
zName = blob_str(&fullName);
253248
isDir = file_wd_isdir(zName);
254249
if( isDir==1 ){
255
- vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
250
+ vfile_scan(&fullName, nRoot-1, scanFlags, pIgnore);
256251
}else if( isDir==0 ){
257252
fossil_warning("not found: %s", zName);
258253
}else if( file_access(zName, R_OK) ){
259254
fossil_fatal("cannot open %s", zName);
260255
}else{
@@ -433,11 +428,11 @@
433428
** See also: add, rm
434429
*/
435430
void addremove_cmd(void){
436431
Blob path;
437432
const char *zIgnoreFlag = find_option("ignore",0,1);
438
- int allFlag = find_option("dotfiles",0,0)!=0;
433
+ unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
439434
int isTest = find_option("test",0,0)!=0;
440435
int caseSensitive;
441436
int n;
442437
Stmt q;
443438
int vid;
@@ -466,11 +461,11 @@
466461
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
467462
n = strlen(g.zLocalRoot);
468463
blob_init(&path, g.zLocalRoot, n-1);
469464
/* now we read the complete file structure into a temp table */
470465
pIgnore = glob_create(zIgnoreFlag);
471
- vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
466
+ vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
472467
glob_free(pIgnore);
473468
nAdd = add_files_in_sfile(vid, caseSensitive);
474469
475470
/* step 2: search for missing files */
476471
db_prepare(&q,
477472
--- src/add.c
+++ src/add.c
@@ -21,16 +21,10 @@
21 #include "config.h"
22 #include "add.h"
23 #include <assert.h>
24 #include <dirent.h>
25
26 /*
27 ** Set to true if files whose names begin with "." should be
28 ** included when processing a recursive "add" command.
29 */
30 static int includeDotFiles = 0;
31
32 /*
33 ** This routine returns the names of files in a working checkout that
34 ** are created by Fossil itself, and hence should not be added, deleted,
35 ** or merge, and should be omitted from "clean" and "extra" lists.
36 **
@@ -39,11 +33,11 @@
39 */
40 const char *fossil_reserved_name(int N){
41 /* Possible names of the local per-checkout database file and
42 ** its associated journals
43 */
44 static const char *azName[] = {
45 "_FOSSIL_",
46 "_FOSSIL_-journal",
47 "_FOSSIL_-wal",
48 "_FOSSIL_-shm",
49 ".fslckout",
@@ -61,11 +55,11 @@
61 };
62
63 /* Names of auxiliary files generated by SQLite when the "manifest"
64 ** properity is enabled
65 */
66 static const char *azManifest[] = {
67 "manifest",
68 "manifest.uuid",
69 };
70
71 /* Cached setting "manifest" */
@@ -216,13 +210,14 @@
216 int vid; /* Currently checked out version */
217 int nRoot; /* Full path characters in g.zLocalRoot */
218 const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
219 Glob *pIgnore; /* Ignore everything matching this glob pattern */
220 int caseSensitive; /* True if filenames are case sensitive */
 
221
222 zIgnoreFlag = find_option("ignore",0,1);
223 includeDotFiles = find_option("dotfiles",0,0)!=0;
224 capture_case_sensitive_option();
225 db_must_be_within_tree();
226 caseSensitive = filenames_are_case_sensitive();
227 if( zIgnoreFlag==0 ){
228 zIgnoreFlag = db_get("ignore-glob", 0);
@@ -250,11 +245,11 @@
250
251 file_canonical_name(g.argv[i], &fullName, 0);
252 zName = blob_str(&fullName);
253 isDir = file_wd_isdir(zName);
254 if( isDir==1 ){
255 vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
256 }else if( isDir==0 ){
257 fossil_warning("not found: %s", zName);
258 }else if( file_access(zName, R_OK) ){
259 fossil_fatal("cannot open %s", zName);
260 }else{
@@ -433,11 +428,11 @@
433 ** See also: add, rm
434 */
435 void addremove_cmd(void){
436 Blob path;
437 const char *zIgnoreFlag = find_option("ignore",0,1);
438 int allFlag = find_option("dotfiles",0,0)!=0;
439 int isTest = find_option("test",0,0)!=0;
440 int caseSensitive;
441 int n;
442 Stmt q;
443 int vid;
@@ -466,11 +461,11 @@
466 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
467 n = strlen(g.zLocalRoot);
468 blob_init(&path, g.zLocalRoot, n-1);
469 /* now we read the complete file structure into a temp table */
470 pIgnore = glob_create(zIgnoreFlag);
471 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
472 glob_free(pIgnore);
473 nAdd = add_files_in_sfile(vid, caseSensitive);
474
475 /* step 2: search for missing files */
476 db_prepare(&q,
477
--- src/add.c
+++ src/add.c
@@ -21,16 +21,10 @@
21 #include "config.h"
22 #include "add.h"
23 #include <assert.h>
24 #include <dirent.h>
25
 
 
 
 
 
 
26 /*
27 ** This routine returns the names of files in a working checkout that
28 ** are created by Fossil itself, and hence should not be added, deleted,
29 ** or merge, and should be omitted from "clean" and "extra" lists.
30 **
@@ -39,11 +33,11 @@
33 */
34 const char *fossil_reserved_name(int N){
35 /* Possible names of the local per-checkout database file and
36 ** its associated journals
37 */
38 static const char *const azName[] = {
39 "_FOSSIL_",
40 "_FOSSIL_-journal",
41 "_FOSSIL_-wal",
42 "_FOSSIL_-shm",
43 ".fslckout",
@@ -61,11 +55,11 @@
55 };
56
57 /* Names of auxiliary files generated by SQLite when the "manifest"
58 ** properity is enabled
59 */
60 static const char *const azManifest[] = {
61 "manifest",
62 "manifest.uuid",
63 };
64
65 /* Cached setting "manifest" */
@@ -216,13 +210,14 @@
210 int vid; /* Currently checked out version */
211 int nRoot; /* Full path characters in g.zLocalRoot */
212 const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
213 Glob *pIgnore; /* Ignore everything matching this glob pattern */
214 int caseSensitive; /* True if filenames are case sensitive */
215 unsigned scanFlags = 0; /* Flags passed to vfile_scan() */
216
217 zIgnoreFlag = find_option("ignore",0,1);
218 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
219 capture_case_sensitive_option();
220 db_must_be_within_tree();
221 caseSensitive = filenames_are_case_sensitive();
222 if( zIgnoreFlag==0 ){
223 zIgnoreFlag = db_get("ignore-glob", 0);
@@ -250,11 +245,11 @@
245
246 file_canonical_name(g.argv[i], &fullName, 0);
247 zName = blob_str(&fullName);
248 isDir = file_wd_isdir(zName);
249 if( isDir==1 ){
250 vfile_scan(&fullName, nRoot-1, scanFlags, pIgnore);
251 }else if( isDir==0 ){
252 fossil_warning("not found: %s", zName);
253 }else if( file_access(zName, R_OK) ){
254 fossil_fatal("cannot open %s", zName);
255 }else{
@@ -433,11 +428,11 @@
428 ** See also: add, rm
429 */
430 void addremove_cmd(void){
431 Blob path;
432 const char *zIgnoreFlag = find_option("ignore",0,1);
433 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
434 int isTest = find_option("test",0,0)!=0;
435 int caseSensitive;
436 int n;
437 Stmt q;
438 int vid;
@@ -466,11 +461,11 @@
461 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
462 n = strlen(g.zLocalRoot);
463 blob_init(&path, g.zLocalRoot, n-1);
464 /* now we read the complete file structure into a temp table */
465 pIgnore = glob_create(zIgnoreFlag);
466 vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
467 glob_free(pIgnore);
468 nAdd = add_files_in_sfile(vid, caseSensitive);
469
470 /* step 2: search for missing files */
471 db_prepare(&q,
472
+152
--- src/browse.c
+++ src/browse.c
@@ -165,10 +165,12 @@
165165
if( zD ){
166166
style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
167167
style_submenu_element("All", "All", "%R/dir?name=%t", zD);
168168
}else{
169169
style_submenu_element("All", "All", "%R/dir");
170
+ style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%S",
171
+ zUuid);
170172
}
171173
}else{
172174
int hasTrunk;
173175
@ <h2>The union of all files from all check-ins
174176
@ %s(blob_str(&dirname))</h2>
@@ -293,5 +295,155 @@
293295
db_finalize(&q);
294296
manifest_destroy(pM);
295297
@ </ul></td></tr></table>
296298
style_footer();
297299
}
300
+
301
+/*
302
+** Look at all file containing in the version "vid". Construct a
303
+** temporary table named "fileage" that contains the file-id for each
304
+** files, the pathname, the check-in where the file was added, and the
305
+** mtime on that checkin.
306
+*/
307
+int compute_fileage(int vid){
308
+ Manifest *pManifest;
309
+ ManifestFile *pFile;
310
+ int nFile = 0;
311
+ double vmtime;
312
+ Stmt ins;
313
+ Stmt q1, q2, q3;
314
+ Stmt upd;
315
+ db_multi_exec(
316
+ /*"DROP TABLE IF EXISTS temp.fileage;"*/
317
+ "CREATE TEMP TABLE fileage("
318
+ " fid INTEGER,"
319
+ " mid INTEGER,"
320
+ " mtime DATETIME,"
321
+ " pathname TEXT"
322
+ ");"
323
+ "CREATE INDEX fileage_fid ON fileage(fid);"
324
+ );
325
+ pManifest = manifest_get(vid, CFTYPE_MANIFEST);
326
+ if( pManifest==0 ) return 1;
327
+ manifest_file_rewind(pManifest);
328
+ db_prepare(&ins,
329
+ "INSERT INTO temp.fileage(fid, pathname)"
330
+ " SELECT rid, :path FROM blob WHERE uuid=:uuid"
331
+ );
332
+ while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
333
+ db_bind_text(&ins, ":uuid", pFile->zUuid);
334
+ db_bind_text(&ins, ":path", pFile->zName);
335
+ db_step(&ins);
336
+ db_reset(&ins);
337
+ nFile++;
338
+ }
339
+ db_finalize(&ins);
340
+ manifest_destroy(pManifest);
341
+ db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid");
342
+ db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime"
343
+ " WHERE fid=:fid AND mid IS NULL");
344
+ db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim");
345
+ db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid");
346
+ while( nFile>0 && vid>0 ){
347
+ db_bind_int(&q3, ":vid", vid);
348
+ if( db_step(&q3)==SQLITE_ROW ){
349
+ vmtime = db_column_double(&q3, 0);
350
+ }else{
351
+ break;
352
+ }
353
+ db_reset(&q3);
354
+ db_bind_int(&q1, ":mid", vid);
355
+ db_bind_int(&upd, ":mid", vid);
356
+ db_bind_double(&upd, ":vmtime", vmtime);
357
+ while( db_step(&q1)==SQLITE_ROW ){
358
+ db_bind_int(&upd, ":fid", db_column_int(&q1, 0));
359
+ db_step(&upd);
360
+ nFile -= db_changes();
361
+ db_reset(&upd);
362
+ }
363
+ db_reset(&q1);
364
+ db_bind_int(&q2, ":vid", vid);
365
+ if( db_step(&q2)!=SQLITE_ROW ) break;
366
+ vid = db_column_int(&q2, 0);
367
+ db_reset(&q2);
368
+ }
369
+ db_finalize(&q1);
370
+ db_finalize(&upd);
371
+ db_finalize(&q2);
372
+ db_finalize(&q3);
373
+ return 0;
374
+}
375
+
376
+/*
377
+** WEBPAGE: fileage
378
+**
379
+** Parameters:
380
+** name=VERSION
381
+*/
382
+void fileage_page(void){
383
+ int rid;
384
+ const char *zName;
385
+ char *zBaseTime;
386
+ Stmt q;
387
+ double baseTime;
388
+ int lastMid = -1;
389
+
390
+ login_check_credentials();
391
+ if( !g.perm.Read ){ login_needed(); return; }
392
+ zName = P("name");
393
+ if( zName==0 ) zName = "tip";
394
+ rid = symbolic_name_to_rid(zName, "ci");
395
+ if( rid==0 ){
396
+ fossil_fatal("not a valid check-in: %s", zName);
397
+ }
398
+ style_header("File Ages", zName);
399
+ compute_fileage(rid);
400
+ baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
401
+ zBaseTime = db_text("","SELECT datetime(%.20g,'localtime')", baseTime);
402
+ @ <h2>File Ages For Check-in
403
+ @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
404
+ @
405
+ @ <p>The times given are relative
406
+ @ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the
407
+ @ check-in time for
408
+ @ %z(href("%R/info?name=%T",zName))%h(zName)</a></p>
409
+ @
410
+ @ <table border=0 cellspacing=0 cellpadding=0>
411
+ db_prepare(&q,
412
+ "SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname"
413
+ " FROM fileage"
414
+ " ORDER BY mtime DESC, mid, pathname"
415
+ );
416
+ while( db_step(&q)==SQLITE_ROW ){
417
+ double age = baseTime - db_column_double(&q, 0);
418
+ int mid = db_column_int(&q, 2);
419
+ const char *zFUuid = db_column_text(&q, 1);
420
+ char zAge[200];
421
+ if( lastMid!=mid ){
422
+ @ <tr><td colspan=3><hr></tr>
423
+ lastMid = mid;
424
+ if( age*86400.0<120 ){
425
+ sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0));
426
+ }else if( age*1440.0<90 ){
427
+ sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0);
428
+ }else if( age*24.0<36 ){
429
+ sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0);
430
+ }else if( age<365.0 ){
431
+ sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age);
432
+ }else{
433
+ sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0);
434
+ }
435
+ }else{
436
+ zAge[0] = 0;
437
+ }
438
+ @ <tr>
439
+ @ <td>%s(zAge)
440
+ @ <td width="25">
441
+ @ <td>%z(href("%R/artifact/%S?ln", zFUuid))%h(db_column_text(&q, 3))</a>
442
+ @ </tr>
443
+ @
444
+ }
445
+ @ <tr><td colspan=3><hr></tr>
446
+ @ </table>
447
+ db_finalize(&q);
448
+ style_footer();
449
+}
298450
--- src/browse.c
+++ src/browse.c
@@ -165,10 +165,12 @@
165 if( zD ){
166 style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
167 style_submenu_element("All", "All", "%R/dir?name=%t", zD);
168 }else{
169 style_submenu_element("All", "All", "%R/dir");
 
 
170 }
171 }else{
172 int hasTrunk;
173 @ <h2>The union of all files from all check-ins
174 @ %s(blob_str(&dirname))</h2>
@@ -293,5 +295,155 @@
293 db_finalize(&q);
294 manifest_destroy(pM);
295 @ </ul></td></tr></table>
296 style_footer();
297 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
--- src/browse.c
+++ src/browse.c
@@ -165,10 +165,12 @@
165 if( zD ){
166 style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
167 style_submenu_element("All", "All", "%R/dir?name=%t", zD);
168 }else{
169 style_submenu_element("All", "All", "%R/dir");
170 style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%S",
171 zUuid);
172 }
173 }else{
174 int hasTrunk;
175 @ <h2>The union of all files from all check-ins
176 @ %s(blob_str(&dirname))</h2>
@@ -293,5 +295,155 @@
295 db_finalize(&q);
296 manifest_destroy(pM);
297 @ </ul></td></tr></table>
298 style_footer();
299 }
300
301 /*
302 ** Look at all file containing in the version "vid". Construct a
303 ** temporary table named "fileage" that contains the file-id for each
304 ** files, the pathname, the check-in where the file was added, and the
305 ** mtime on that checkin.
306 */
307 int compute_fileage(int vid){
308 Manifest *pManifest;
309 ManifestFile *pFile;
310 int nFile = 0;
311 double vmtime;
312 Stmt ins;
313 Stmt q1, q2, q3;
314 Stmt upd;
315 db_multi_exec(
316 /*"DROP TABLE IF EXISTS temp.fileage;"*/
317 "CREATE TEMP TABLE fileage("
318 " fid INTEGER,"
319 " mid INTEGER,"
320 " mtime DATETIME,"
321 " pathname TEXT"
322 ");"
323 "CREATE INDEX fileage_fid ON fileage(fid);"
324 );
325 pManifest = manifest_get(vid, CFTYPE_MANIFEST);
326 if( pManifest==0 ) return 1;
327 manifest_file_rewind(pManifest);
328 db_prepare(&ins,
329 "INSERT INTO temp.fileage(fid, pathname)"
330 " SELECT rid, :path FROM blob WHERE uuid=:uuid"
331 );
332 while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
333 db_bind_text(&ins, ":uuid", pFile->zUuid);
334 db_bind_text(&ins, ":path", pFile->zName);
335 db_step(&ins);
336 db_reset(&ins);
337 nFile++;
338 }
339 db_finalize(&ins);
340 manifest_destroy(pManifest);
341 db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid");
342 db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime"
343 " WHERE fid=:fid AND mid IS NULL");
344 db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim");
345 db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid");
346 while( nFile>0 && vid>0 ){
347 db_bind_int(&q3, ":vid", vid);
348 if( db_step(&q3)==SQLITE_ROW ){
349 vmtime = db_column_double(&q3, 0);
350 }else{
351 break;
352 }
353 db_reset(&q3);
354 db_bind_int(&q1, ":mid", vid);
355 db_bind_int(&upd, ":mid", vid);
356 db_bind_double(&upd, ":vmtime", vmtime);
357 while( db_step(&q1)==SQLITE_ROW ){
358 db_bind_int(&upd, ":fid", db_column_int(&q1, 0));
359 db_step(&upd);
360 nFile -= db_changes();
361 db_reset(&upd);
362 }
363 db_reset(&q1);
364 db_bind_int(&q2, ":vid", vid);
365 if( db_step(&q2)!=SQLITE_ROW ) break;
366 vid = db_column_int(&q2, 0);
367 db_reset(&q2);
368 }
369 db_finalize(&q1);
370 db_finalize(&upd);
371 db_finalize(&q2);
372 db_finalize(&q3);
373 return 0;
374 }
375
376 /*
377 ** WEBPAGE: fileage
378 **
379 ** Parameters:
380 ** name=VERSION
381 */
382 void fileage_page(void){
383 int rid;
384 const char *zName;
385 char *zBaseTime;
386 Stmt q;
387 double baseTime;
388 int lastMid = -1;
389
390 login_check_credentials();
391 if( !g.perm.Read ){ login_needed(); return; }
392 zName = P("name");
393 if( zName==0 ) zName = "tip";
394 rid = symbolic_name_to_rid(zName, "ci");
395 if( rid==0 ){
396 fossil_fatal("not a valid check-in: %s", zName);
397 }
398 style_header("File Ages", zName);
399 compute_fileage(rid);
400 baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
401 zBaseTime = db_text("","SELECT datetime(%.20g,'localtime')", baseTime);
402 @ <h2>File Ages For Check-in
403 @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
404 @
405 @ <p>The times given are relative
406 @ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the
407 @ check-in time for
408 @ %z(href("%R/info?name=%T",zName))%h(zName)</a></p>
409 @
410 @ <table border=0 cellspacing=0 cellpadding=0>
411 db_prepare(&q,
412 "SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname"
413 " FROM fileage"
414 " ORDER BY mtime DESC, mid, pathname"
415 );
416 while( db_step(&q)==SQLITE_ROW ){
417 double age = baseTime - db_column_double(&q, 0);
418 int mid = db_column_int(&q, 2);
419 const char *zFUuid = db_column_text(&q, 1);
420 char zAge[200];
421 if( lastMid!=mid ){
422 @ <tr><td colspan=3><hr></tr>
423 lastMid = mid;
424 if( age*86400.0<120 ){
425 sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0));
426 }else if( age*1440.0<90 ){
427 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0);
428 }else if( age*24.0<36 ){
429 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0);
430 }else if( age<365.0 ){
431 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age);
432 }else{
433 sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0);
434 }
435 }else{
436 zAge[0] = 0;
437 }
438 @ <tr>
439 @ <td>%s(zAge)
440 @ <td width="25">
441 @ <td>%z(href("%R/artifact/%S?ln", zFUuid))%h(db_column_text(&q, 3))</a>
442 @ </tr>
443 @
444 }
445 @ <tr><td colspan=3><hr></tr>
446 @ </table>
447 db_finalize(&q);
448 style_footer();
449 }
450
+2 -2
--- src/captcha.c
+++ src/captcha.c
@@ -98,11 +98,11 @@
9898
}
9999
#endif /* CAPTCHA==1 */
100100
101101
102102
#if CAPTCHA==2
103
-static const char *azFont2[] = {
103
+static const char *const azFont2[] = {
104104
/* 0 */
105105
" __ ",
106106
" / \\ ",
107107
"| () |",
108108
" \\__/ ",
@@ -223,11 +223,11 @@
223223
return z;
224224
}
225225
#endif /* CAPTCHA==2 */
226226
227227
#if CAPTCHA==3
228
-static const char *azFont3[] = {
228
+static const char *const azFont3[] = {
229229
/* 0 */
230230
" ___ ",
231231
" / _ \\ ",
232232
"| | | |",
233233
"| | | |",
234234
--- src/captcha.c
+++ src/captcha.c
@@ -98,11 +98,11 @@
98 }
99 #endif /* CAPTCHA==1 */
100
101
102 #if CAPTCHA==2
103 static const char *azFont2[] = {
104 /* 0 */
105 " __ ",
106 " / \\ ",
107 "| () |",
108 " \\__/ ",
@@ -223,11 +223,11 @@
223 return z;
224 }
225 #endif /* CAPTCHA==2 */
226
227 #if CAPTCHA==3
228 static const char *azFont3[] = {
229 /* 0 */
230 " ___ ",
231 " / _ \\ ",
232 "| | | |",
233 "| | | |",
234
--- src/captcha.c
+++ src/captcha.c
@@ -98,11 +98,11 @@
98 }
99 #endif /* CAPTCHA==1 */
100
101
102 #if CAPTCHA==2
103 static const char *const azFont2[] = {
104 /* 0 */
105 " __ ",
106 " / \\ ",
107 "| () |",
108 " \\__/ ",
@@ -223,11 +223,11 @@
223 return z;
224 }
225 #endif /* CAPTCHA==2 */
226
227 #if CAPTCHA==3
228 static const char *const azFont3[] = {
229 /* 0 */
230 " ___ ",
231 " / _ \\ ",
232 "| | | |",
233 "| | | |",
234
+2 -2
--- src/cgi.c
+++ src/cgi.c
@@ -1354,13 +1354,13 @@
13541354
13551355
13561356
/*
13571357
** Name of days and months.
13581358
*/
1359
-static const char *azDays[] =
1359
+static const char *const azDays[] =
13601360
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0};
1361
-static const char *azMonths[] =
1361
+static const char *const azMonths[] =
13621362
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
13631363
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
13641364
13651365
13661366
/*
13671367
--- src/cgi.c
+++ src/cgi.c
@@ -1354,13 +1354,13 @@
1354
1355
1356 /*
1357 ** Name of days and months.
1358 */
1359 static const char *azDays[] =
1360 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0};
1361 static const char *azMonths[] =
1362 {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
1363 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
1364
1365
1366 /*
1367
--- src/cgi.c
+++ src/cgi.c
@@ -1354,13 +1354,13 @@
1354
1355
1356 /*
1357 ** Name of days and months.
1358 */
1359 static const char *const azDays[] =
1360 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0};
1361 static const char *const azMonths[] =
1362 {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
1363 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
1364
1365
1366 /*
1367
+46 -19
--- src/checkin.c
+++ src/checkin.c
@@ -163,11 +163,11 @@
163163
int cwdRelative = 0;
164164
db_must_be_within_tree();
165165
cwdRelative = determine_cwd_relative_option();
166166
blob_zero(&report);
167167
vid = db_lget_int("checkout", 0);
168
- vfile_check_signature(vid, 0, useSha1sum);
168
+ vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
169169
status_report(&report, "", 0, cwdRelative);
170170
if( verbose && blob_size(&report)==0 ){
171171
blob_append(&report, " (none)\n", -1);
172172
}
173173
if( showHdr && blob_size(&report)>0 ){
@@ -208,46 +208,74 @@
208208
show_common_info(vid, "checkout:", 1, 1);
209209
}
210210
db_record_repository_filename(0);
211211
changes_cmd();
212212
}
213
+
214
+/*
215
+** Implementation of the checkin_mtime SQL function
216
+*/
217
+
213218
214219
/*
215220
** COMMAND: ls
216221
**
217
-** Usage: %fossil ls ?OPTIONS?
222
+** Usage: %fossil ls ?OPTIONS? ?VERSION?
218223
**
219224
** Show the names of all files in the current checkout. The -l provides
220225
** extra information about each file.
221226
**
222227
** Options:
223
-** -l Provide extra information about each file.
228
+** -l Provide extra information about each file.
229
+** --age Show when each file was committed
224230
**
225231
** See also: changes, extra, status
226232
*/
227233
void ls_cmd(void){
228234
int vid;
229235
Stmt q;
230236
int isBrief;
237
+ int showAge;
238
+ char *zOrderBy = "pathname";
231239
232240
isBrief = find_option("l","l", 0)==0;
241
+ showAge = find_option("age",0,0)!=0;
233242
db_must_be_within_tree();
234243
vid = db_lget_int("checkout", 0);
235
- vfile_check_signature(vid, 0, 0);
236
- db_prepare(&q,
237
- "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
238
- " FROM vfile"
239
- " ORDER BY 1"
240
- );
244
+ if( find_option("t","t",0)!=0 ){
245
+ if( showAge ){
246
+ zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
247
+ }else{
248
+ zOrderBy = "mtime DESC";
249
+ }
250
+ }
251
+ verify_all_options();
252
+ vfile_check_signature(vid, 0);
253
+ if( showAge ){
254
+ db_prepare(&q,
255
+ "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
256
+ " datetime(checkin_mtime(%d,rid),'unixepoch','localtime')"
257
+ " FROM vfile"
258
+ " ORDER BY %s", vid, zOrderBy
259
+ );
260
+ }else{
261
+ db_prepare(&q,
262
+ "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
263
+ " FROM vfile"
264
+ " ORDER BY %s", zOrderBy
265
+ );
266
+ }
241267
while( db_step(&q)==SQLITE_ROW ){
242268
const char *zPathname = db_column_text(&q,0);
243269
int isDeleted = db_column_int(&q, 1);
244270
int isNew = db_column_int(&q,2)==0;
245271
int chnged = db_column_int(&q,3);
246272
int renamed = db_column_int(&q,4);
247273
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
248
- if( isBrief ){
274
+ if( showAge ){
275
+ fossil_print("%s %s\n", db_column_text(&q, 5), zPathname);
276
+ }else if( isBrief ){
249277
fossil_print("%s\n", zPathname);
250278
}else if( isNew ){
251279
fossil_print("ADDED %s\n", zPathname);
252280
}else if( isDeleted ){
253281
fossil_print("DELETED %s\n", zPathname);
@@ -299,16 +327,17 @@
299327
Blob path;
300328
Blob repo;
301329
Stmt q;
302330
int n;
303331
const char *zIgnoreFlag = find_option("ignore",0,1);
304
- int allFlag = find_option("dotfiles",0,0)!=0;
332
+ unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
305333
int cwdRelative = 0;
306334
Glob *pIgnore;
307335
Blob rewrittenPathname;
308336
const char *zPathname, *zDisplayName;
309337
338
+ if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
310339
db_must_be_within_tree();
311340
cwdRelative = determine_cwd_relative_option();
312341
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
313342
filename_collation());
314343
n = strlen(g.zLocalRoot);
@@ -315,11 +344,11 @@
315344
blob_init(&path, g.zLocalRoot, n-1);
316345
if( zIgnoreFlag==0 ){
317346
zIgnoreFlag = db_get("ignore-glob", 0);
318347
}
319348
pIgnore = glob_create(zIgnoreFlag);
320
- vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
349
+ vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
321350
glob_free(pIgnore);
322351
db_prepare(&q,
323352
"SELECT x FROM sfile"
324353
" WHERE x NOT IN (%s)"
325354
" ORDER BY 1",
@@ -370,34 +399,36 @@
370399
** Options:
371400
** --dotfiles include files beginning with a dot (".")
372401
** --force Remove files without prompting
373402
** --ignore <CSG> ignore files matching patterns from the
374403
** comma separated list of glob patterns.
404
+** --temp Remove only Fossil-generated temporary files
375405
**
376406
** See also: addremove, extra, status
377407
*/
378408
void clean_cmd(void){
379409
int allFlag;
380
- int dotfilesFlag;
410
+ unsigned scanFlags = 0;
381411
const char *zIgnoreFlag;
382412
Blob path, repo;
383413
Stmt q;
384414
int n;
385415
Glob *pIgnore;
386416
387417
allFlag = find_option("force","f",0)!=0;
388
- dotfilesFlag = find_option("dotfiles",0,0)!=0;
418
+ if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
419
+ if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
389420
zIgnoreFlag = find_option("ignore",0,1);
390421
db_must_be_within_tree();
391422
if( zIgnoreFlag==0 ){
392423
zIgnoreFlag = db_get("ignore-glob", 0);
393424
}
394425
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
395426
n = strlen(g.zLocalRoot);
396427
blob_init(&path, g.zLocalRoot, n-1);
397428
pIgnore = glob_create(zIgnoreFlag);
398
- vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
429
+ vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
399430
glob_free(pIgnore);
400431
db_prepare(&q,
401432
"SELECT %Q || x FROM sfile"
402433
" WHERE x NOT IN (%s)"
403434
" ORDER BY 1",
@@ -806,14 +837,10 @@
806837
}
807838
if( zColor && zColor[0] ){
808839
/* One-time background color */
809840
blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
810841
}
811
- if( g.markPrivate ){
812
- /* If this manifest is private, mark it as such */
813
- blob_appendf(pOut, "T +private *\n");
814
- }
815842
if( azTag ){
816843
for(i=0; azTag[i]; i++){
817844
/* Add a symbolic tag to this check-in. The tag names have already
818845
** been sorted and converted using the %F format */
819846
blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
820847
--- src/checkin.c
+++ src/checkin.c
@@ -163,11 +163,11 @@
163 int cwdRelative = 0;
164 db_must_be_within_tree();
165 cwdRelative = determine_cwd_relative_option();
166 blob_zero(&report);
167 vid = db_lget_int("checkout", 0);
168 vfile_check_signature(vid, 0, useSha1sum);
169 status_report(&report, "", 0, cwdRelative);
170 if( verbose && blob_size(&report)==0 ){
171 blob_append(&report, " (none)\n", -1);
172 }
173 if( showHdr && blob_size(&report)>0 ){
@@ -208,46 +208,74 @@
208 show_common_info(vid, "checkout:", 1, 1);
209 }
210 db_record_repository_filename(0);
211 changes_cmd();
212 }
 
 
 
 
 
213
214 /*
215 ** COMMAND: ls
216 **
217 ** Usage: %fossil ls ?OPTIONS?
218 **
219 ** Show the names of all files in the current checkout. The -l provides
220 ** extra information about each file.
221 **
222 ** Options:
223 ** -l Provide extra information about each file.
 
224 **
225 ** See also: changes, extra, status
226 */
227 void ls_cmd(void){
228 int vid;
229 Stmt q;
230 int isBrief;
 
 
231
232 isBrief = find_option("l","l", 0)==0;
 
233 db_must_be_within_tree();
234 vid = db_lget_int("checkout", 0);
235 vfile_check_signature(vid, 0, 0);
236 db_prepare(&q,
237 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
238 " FROM vfile"
239 " ORDER BY 1"
240 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241 while( db_step(&q)==SQLITE_ROW ){
242 const char *zPathname = db_column_text(&q,0);
243 int isDeleted = db_column_int(&q, 1);
244 int isNew = db_column_int(&q,2)==0;
245 int chnged = db_column_int(&q,3);
246 int renamed = db_column_int(&q,4);
247 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
248 if( isBrief ){
 
 
249 fossil_print("%s\n", zPathname);
250 }else if( isNew ){
251 fossil_print("ADDED %s\n", zPathname);
252 }else if( isDeleted ){
253 fossil_print("DELETED %s\n", zPathname);
@@ -299,16 +327,17 @@
299 Blob path;
300 Blob repo;
301 Stmt q;
302 int n;
303 const char *zIgnoreFlag = find_option("ignore",0,1);
304 int allFlag = find_option("dotfiles",0,0)!=0;
305 int cwdRelative = 0;
306 Glob *pIgnore;
307 Blob rewrittenPathname;
308 const char *zPathname, *zDisplayName;
309
 
310 db_must_be_within_tree();
311 cwdRelative = determine_cwd_relative_option();
312 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
313 filename_collation());
314 n = strlen(g.zLocalRoot);
@@ -315,11 +344,11 @@
315 blob_init(&path, g.zLocalRoot, n-1);
316 if( zIgnoreFlag==0 ){
317 zIgnoreFlag = db_get("ignore-glob", 0);
318 }
319 pIgnore = glob_create(zIgnoreFlag);
320 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
321 glob_free(pIgnore);
322 db_prepare(&q,
323 "SELECT x FROM sfile"
324 " WHERE x NOT IN (%s)"
325 " ORDER BY 1",
@@ -370,34 +399,36 @@
370 ** Options:
371 ** --dotfiles include files beginning with a dot (".")
372 ** --force Remove files without prompting
373 ** --ignore <CSG> ignore files matching patterns from the
374 ** comma separated list of glob patterns.
 
375 **
376 ** See also: addremove, extra, status
377 */
378 void clean_cmd(void){
379 int allFlag;
380 int dotfilesFlag;
381 const char *zIgnoreFlag;
382 Blob path, repo;
383 Stmt q;
384 int n;
385 Glob *pIgnore;
386
387 allFlag = find_option("force","f",0)!=0;
388 dotfilesFlag = find_option("dotfiles",0,0)!=0;
 
389 zIgnoreFlag = find_option("ignore",0,1);
390 db_must_be_within_tree();
391 if( zIgnoreFlag==0 ){
392 zIgnoreFlag = db_get("ignore-glob", 0);
393 }
394 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
395 n = strlen(g.zLocalRoot);
396 blob_init(&path, g.zLocalRoot, n-1);
397 pIgnore = glob_create(zIgnoreFlag);
398 vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
399 glob_free(pIgnore);
400 db_prepare(&q,
401 "SELECT %Q || x FROM sfile"
402 " WHERE x NOT IN (%s)"
403 " ORDER BY 1",
@@ -806,14 +837,10 @@
806 }
807 if( zColor && zColor[0] ){
808 /* One-time background color */
809 blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
810 }
811 if( g.markPrivate ){
812 /* If this manifest is private, mark it as such */
813 blob_appendf(pOut, "T +private *\n");
814 }
815 if( azTag ){
816 for(i=0; azTag[i]; i++){
817 /* Add a symbolic tag to this check-in. The tag names have already
818 ** been sorted and converted using the %F format */
819 blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
820
--- src/checkin.c
+++ src/checkin.c
@@ -163,11 +163,11 @@
163 int cwdRelative = 0;
164 db_must_be_within_tree();
165 cwdRelative = determine_cwd_relative_option();
166 blob_zero(&report);
167 vid = db_lget_int("checkout", 0);
168 vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
169 status_report(&report, "", 0, cwdRelative);
170 if( verbose && blob_size(&report)==0 ){
171 blob_append(&report, " (none)\n", -1);
172 }
173 if( showHdr && blob_size(&report)>0 ){
@@ -208,46 +208,74 @@
208 show_common_info(vid, "checkout:", 1, 1);
209 }
210 db_record_repository_filename(0);
211 changes_cmd();
212 }
213
214 /*
215 ** Implementation of the checkin_mtime SQL function
216 */
217
218
219 /*
220 ** COMMAND: ls
221 **
222 ** Usage: %fossil ls ?OPTIONS? ?VERSION?
223 **
224 ** Show the names of all files in the current checkout. The -l provides
225 ** extra information about each file.
226 **
227 ** Options:
228 ** -l Provide extra information about each file.
229 ** --age Show when each file was committed
230 **
231 ** See also: changes, extra, status
232 */
233 void ls_cmd(void){
234 int vid;
235 Stmt q;
236 int isBrief;
237 int showAge;
238 char *zOrderBy = "pathname";
239
240 isBrief = find_option("l","l", 0)==0;
241 showAge = find_option("age",0,0)!=0;
242 db_must_be_within_tree();
243 vid = db_lget_int("checkout", 0);
244 if( find_option("t","t",0)!=0 ){
245 if( showAge ){
246 zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
247 }else{
248 zOrderBy = "mtime DESC";
249 }
250 }
251 verify_all_options();
252 vfile_check_signature(vid, 0);
253 if( showAge ){
254 db_prepare(&q,
255 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
256 " datetime(checkin_mtime(%d,rid),'unixepoch','localtime')"
257 " FROM vfile"
258 " ORDER BY %s", vid, zOrderBy
259 );
260 }else{
261 db_prepare(&q,
262 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
263 " FROM vfile"
264 " ORDER BY %s", zOrderBy
265 );
266 }
267 while( db_step(&q)==SQLITE_ROW ){
268 const char *zPathname = db_column_text(&q,0);
269 int isDeleted = db_column_int(&q, 1);
270 int isNew = db_column_int(&q,2)==0;
271 int chnged = db_column_int(&q,3);
272 int renamed = db_column_int(&q,4);
273 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
274 if( showAge ){
275 fossil_print("%s %s\n", db_column_text(&q, 5), zPathname);
276 }else if( isBrief ){
277 fossil_print("%s\n", zPathname);
278 }else if( isNew ){
279 fossil_print("ADDED %s\n", zPathname);
280 }else if( isDeleted ){
281 fossil_print("DELETED %s\n", zPathname);
@@ -299,16 +327,17 @@
327 Blob path;
328 Blob repo;
329 Stmt q;
330 int n;
331 const char *zIgnoreFlag = find_option("ignore",0,1);
332 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
333 int cwdRelative = 0;
334 Glob *pIgnore;
335 Blob rewrittenPathname;
336 const char *zPathname, *zDisplayName;
337
338 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
339 db_must_be_within_tree();
340 cwdRelative = determine_cwd_relative_option();
341 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
342 filename_collation());
343 n = strlen(g.zLocalRoot);
@@ -315,11 +344,11 @@
344 blob_init(&path, g.zLocalRoot, n-1);
345 if( zIgnoreFlag==0 ){
346 zIgnoreFlag = db_get("ignore-glob", 0);
347 }
348 pIgnore = glob_create(zIgnoreFlag);
349 vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
350 glob_free(pIgnore);
351 db_prepare(&q,
352 "SELECT x FROM sfile"
353 " WHERE x NOT IN (%s)"
354 " ORDER BY 1",
@@ -370,34 +399,36 @@
399 ** Options:
400 ** --dotfiles include files beginning with a dot (".")
401 ** --force Remove files without prompting
402 ** --ignore <CSG> ignore files matching patterns from the
403 ** comma separated list of glob patterns.
404 ** --temp Remove only Fossil-generated temporary files
405 **
406 ** See also: addremove, extra, status
407 */
408 void clean_cmd(void){
409 int allFlag;
410 unsigned scanFlags = 0;
411 const char *zIgnoreFlag;
412 Blob path, repo;
413 Stmt q;
414 int n;
415 Glob *pIgnore;
416
417 allFlag = find_option("force","f",0)!=0;
418 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
419 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
420 zIgnoreFlag = find_option("ignore",0,1);
421 db_must_be_within_tree();
422 if( zIgnoreFlag==0 ){
423 zIgnoreFlag = db_get("ignore-glob", 0);
424 }
425 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
426 n = strlen(g.zLocalRoot);
427 blob_init(&path, g.zLocalRoot, n-1);
428 pIgnore = glob_create(zIgnoreFlag);
429 vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
430 glob_free(pIgnore);
431 db_prepare(&q,
432 "SELECT %Q || x FROM sfile"
433 " WHERE x NOT IN (%s)"
434 " ORDER BY 1",
@@ -806,14 +837,10 @@
837 }
838 if( zColor && zColor[0] ){
839 /* One-time background color */
840 blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
841 }
 
 
 
 
842 if( azTag ){
843 for(i=0; azTag[i]; i++){
844 /* Add a symbolic tag to this check-in. The tag names have already
845 ** been sorted and converted using the %F format */
846 blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
847
+46 -19
--- src/checkin.c
+++ src/checkin.c
@@ -163,11 +163,11 @@
163163
int cwdRelative = 0;
164164
db_must_be_within_tree();
165165
cwdRelative = determine_cwd_relative_option();
166166
blob_zero(&report);
167167
vid = db_lget_int("checkout", 0);
168
- vfile_check_signature(vid, 0, useSha1sum);
168
+ vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
169169
status_report(&report, "", 0, cwdRelative);
170170
if( verbose && blob_size(&report)==0 ){
171171
blob_append(&report, " (none)\n", -1);
172172
}
173173
if( showHdr && blob_size(&report)>0 ){
@@ -208,46 +208,74 @@
208208
show_common_info(vid, "checkout:", 1, 1);
209209
}
210210
db_record_repository_filename(0);
211211
changes_cmd();
212212
}
213
+
214
+/*
215
+** Implementation of the checkin_mtime SQL function
216
+*/
217
+
213218
214219
/*
215220
** COMMAND: ls
216221
**
217
-** Usage: %fossil ls ?OPTIONS?
222
+** Usage: %fossil ls ?OPTIONS? ?VERSION?
218223
**
219224
** Show the names of all files in the current checkout. The -l provides
220225
** extra information about each file.
221226
**
222227
** Options:
223
-** -l Provide extra information about each file.
228
+** -l Provide extra information about each file.
229
+** --age Show when each file was committed
224230
**
225231
** See also: changes, extra, status
226232
*/
227233
void ls_cmd(void){
228234
int vid;
229235
Stmt q;
230236
int isBrief;
237
+ int showAge;
238
+ char *zOrderBy = "pathname";
231239
232240
isBrief = find_option("l","l", 0)==0;
241
+ showAge = find_option("age",0,0)!=0;
233242
db_must_be_within_tree();
234243
vid = db_lget_int("checkout", 0);
235
- vfile_check_signature(vid, 0, 0);
236
- db_prepare(&q,
237
- "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
238
- " FROM vfile"
239
- " ORDER BY 1"
240
- );
244
+ if( find_option("t","t",0)!=0 ){
245
+ if( showAge ){
246
+ zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
247
+ }else{
248
+ zOrderBy = "mtime DESC";
249
+ }
250
+ }
251
+ verify_all_options();
252
+ vfile_check_signature(vid, 0);
253
+ if( showAge ){
254
+ db_prepare(&q,
255
+ "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
256
+ " datetime(checkin_mtime(%d,rid),'unixepoch','localtime')"
257
+ " FROM vfile"
258
+ " ORDER BY %s", vid, zOrderBy
259
+ );
260
+ }else{
261
+ db_prepare(&q,
262
+ "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
263
+ " FROM vfile"
264
+ " ORDER BY %s", zOrderBy
265
+ );
266
+ }
241267
while( db_step(&q)==SQLITE_ROW ){
242268
const char *zPathname = db_column_text(&q,0);
243269
int isDeleted = db_column_int(&q, 1);
244270
int isNew = db_column_int(&q,2)==0;
245271
int chnged = db_column_int(&q,3);
246272
int renamed = db_column_int(&q,4);
247273
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
248
- if( isBrief ){
274
+ if( showAge ){
275
+ fossil_print("%s %s\n", db_column_text(&q, 5), zPathname);
276
+ }else if( isBrief ){
249277
fossil_print("%s\n", zPathname);
250278
}else if( isNew ){
251279
fossil_print("ADDED %s\n", zPathname);
252280
}else if( isDeleted ){
253281
fossil_print("DELETED %s\n", zPathname);
@@ -299,16 +327,17 @@
299327
Blob path;
300328
Blob repo;
301329
Stmt q;
302330
int n;
303331
const char *zIgnoreFlag = find_option("ignore",0,1);
304
- int allFlag = find_option("dotfiles",0,0)!=0;
332
+ unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
305333
int cwdRelative = 0;
306334
Glob *pIgnore;
307335
Blob rewrittenPathname;
308336
const char *zPathname, *zDisplayName;
309337
338
+ if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
310339
db_must_be_within_tree();
311340
cwdRelative = determine_cwd_relative_option();
312341
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
313342
filename_collation());
314343
n = strlen(g.zLocalRoot);
@@ -315,11 +344,11 @@
315344
blob_init(&path, g.zLocalRoot, n-1);
316345
if( zIgnoreFlag==0 ){
317346
zIgnoreFlag = db_get("ignore-glob", 0);
318347
}
319348
pIgnore = glob_create(zIgnoreFlag);
320
- vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
349
+ vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
321350
glob_free(pIgnore);
322351
db_prepare(&q,
323352
"SELECT x FROM sfile"
324353
" WHERE x NOT IN (%s)"
325354
" ORDER BY 1",
@@ -370,34 +399,36 @@
370399
** Options:
371400
** --dotfiles include files beginning with a dot (".")
372401
** --force Remove files without prompting
373402
** --ignore <CSG> ignore files matching patterns from the
374403
** comma separated list of glob patterns.
404
+** --temp Remove only Fossil-generated temporary files
375405
**
376406
** See also: addremove, extra, status
377407
*/
378408
void clean_cmd(void){
379409
int allFlag;
380
- int dotfilesFlag;
410
+ unsigned scanFlags = 0;
381411
const char *zIgnoreFlag;
382412
Blob path, repo;
383413
Stmt q;
384414
int n;
385415
Glob *pIgnore;
386416
387417
allFlag = find_option("force","f",0)!=0;
388
- dotfilesFlag = find_option("dotfiles",0,0)!=0;
418
+ if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
419
+ if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
389420
zIgnoreFlag = find_option("ignore",0,1);
390421
db_must_be_within_tree();
391422
if( zIgnoreFlag==0 ){
392423
zIgnoreFlag = db_get("ignore-glob", 0);
393424
}
394425
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
395426
n = strlen(g.zLocalRoot);
396427
blob_init(&path, g.zLocalRoot, n-1);
397428
pIgnore = glob_create(zIgnoreFlag);
398
- vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
429
+ vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
399430
glob_free(pIgnore);
400431
db_prepare(&q,
401432
"SELECT %Q || x FROM sfile"
402433
" WHERE x NOT IN (%s)"
403434
" ORDER BY 1",
@@ -806,14 +837,10 @@
806837
}
807838
if( zColor && zColor[0] ){
808839
/* One-time background color */
809840
blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
810841
}
811
- if( g.markPrivate ){
812
- /* If this manifest is private, mark it as such */
813
- blob_appendf(pOut, "T +private *\n");
814
- }
815842
if( azTag ){
816843
for(i=0; azTag[i]; i++){
817844
/* Add a symbolic tag to this check-in. The tag names have already
818845
** been sorted and converted using the %F format */
819846
blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
820847
--- src/checkin.c
+++ src/checkin.c
@@ -163,11 +163,11 @@
163 int cwdRelative = 0;
164 db_must_be_within_tree();
165 cwdRelative = determine_cwd_relative_option();
166 blob_zero(&report);
167 vid = db_lget_int("checkout", 0);
168 vfile_check_signature(vid, 0, useSha1sum);
169 status_report(&report, "", 0, cwdRelative);
170 if( verbose && blob_size(&report)==0 ){
171 blob_append(&report, " (none)\n", -1);
172 }
173 if( showHdr && blob_size(&report)>0 ){
@@ -208,46 +208,74 @@
208 show_common_info(vid, "checkout:", 1, 1);
209 }
210 db_record_repository_filename(0);
211 changes_cmd();
212 }
 
 
 
 
 
213
214 /*
215 ** COMMAND: ls
216 **
217 ** Usage: %fossil ls ?OPTIONS?
218 **
219 ** Show the names of all files in the current checkout. The -l provides
220 ** extra information about each file.
221 **
222 ** Options:
223 ** -l Provide extra information about each file.
 
224 **
225 ** See also: changes, extra, status
226 */
227 void ls_cmd(void){
228 int vid;
229 Stmt q;
230 int isBrief;
 
 
231
232 isBrief = find_option("l","l", 0)==0;
 
233 db_must_be_within_tree();
234 vid = db_lget_int("checkout", 0);
235 vfile_check_signature(vid, 0, 0);
236 db_prepare(&q,
237 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
238 " FROM vfile"
239 " ORDER BY 1"
240 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241 while( db_step(&q)==SQLITE_ROW ){
242 const char *zPathname = db_column_text(&q,0);
243 int isDeleted = db_column_int(&q, 1);
244 int isNew = db_column_int(&q,2)==0;
245 int chnged = db_column_int(&q,3);
246 int renamed = db_column_int(&q,4);
247 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
248 if( isBrief ){
 
 
249 fossil_print("%s\n", zPathname);
250 }else if( isNew ){
251 fossil_print("ADDED %s\n", zPathname);
252 }else if( isDeleted ){
253 fossil_print("DELETED %s\n", zPathname);
@@ -299,16 +327,17 @@
299 Blob path;
300 Blob repo;
301 Stmt q;
302 int n;
303 const char *zIgnoreFlag = find_option("ignore",0,1);
304 int allFlag = find_option("dotfiles",0,0)!=0;
305 int cwdRelative = 0;
306 Glob *pIgnore;
307 Blob rewrittenPathname;
308 const char *zPathname, *zDisplayName;
309
 
310 db_must_be_within_tree();
311 cwdRelative = determine_cwd_relative_option();
312 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
313 filename_collation());
314 n = strlen(g.zLocalRoot);
@@ -315,11 +344,11 @@
315 blob_init(&path, g.zLocalRoot, n-1);
316 if( zIgnoreFlag==0 ){
317 zIgnoreFlag = db_get("ignore-glob", 0);
318 }
319 pIgnore = glob_create(zIgnoreFlag);
320 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
321 glob_free(pIgnore);
322 db_prepare(&q,
323 "SELECT x FROM sfile"
324 " WHERE x NOT IN (%s)"
325 " ORDER BY 1",
@@ -370,34 +399,36 @@
370 ** Options:
371 ** --dotfiles include files beginning with a dot (".")
372 ** --force Remove files without prompting
373 ** --ignore <CSG> ignore files matching patterns from the
374 ** comma separated list of glob patterns.
 
375 **
376 ** See also: addremove, extra, status
377 */
378 void clean_cmd(void){
379 int allFlag;
380 int dotfilesFlag;
381 const char *zIgnoreFlag;
382 Blob path, repo;
383 Stmt q;
384 int n;
385 Glob *pIgnore;
386
387 allFlag = find_option("force","f",0)!=0;
388 dotfilesFlag = find_option("dotfiles",0,0)!=0;
 
389 zIgnoreFlag = find_option("ignore",0,1);
390 db_must_be_within_tree();
391 if( zIgnoreFlag==0 ){
392 zIgnoreFlag = db_get("ignore-glob", 0);
393 }
394 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
395 n = strlen(g.zLocalRoot);
396 blob_init(&path, g.zLocalRoot, n-1);
397 pIgnore = glob_create(zIgnoreFlag);
398 vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
399 glob_free(pIgnore);
400 db_prepare(&q,
401 "SELECT %Q || x FROM sfile"
402 " WHERE x NOT IN (%s)"
403 " ORDER BY 1",
@@ -806,14 +837,10 @@
806 }
807 if( zColor && zColor[0] ){
808 /* One-time background color */
809 blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
810 }
811 if( g.markPrivate ){
812 /* If this manifest is private, mark it as such */
813 blob_appendf(pOut, "T +private *\n");
814 }
815 if( azTag ){
816 for(i=0; azTag[i]; i++){
817 /* Add a symbolic tag to this check-in. The tag names have already
818 ** been sorted and converted using the %F format */
819 blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
820
--- src/checkin.c
+++ src/checkin.c
@@ -163,11 +163,11 @@
163 int cwdRelative = 0;
164 db_must_be_within_tree();
165 cwdRelative = determine_cwd_relative_option();
166 blob_zero(&report);
167 vid = db_lget_int("checkout", 0);
168 vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
169 status_report(&report, "", 0, cwdRelative);
170 if( verbose && blob_size(&report)==0 ){
171 blob_append(&report, " (none)\n", -1);
172 }
173 if( showHdr && blob_size(&report)>0 ){
@@ -208,46 +208,74 @@
208 show_common_info(vid, "checkout:", 1, 1);
209 }
210 db_record_repository_filename(0);
211 changes_cmd();
212 }
213
214 /*
215 ** Implementation of the checkin_mtime SQL function
216 */
217
218
219 /*
220 ** COMMAND: ls
221 **
222 ** Usage: %fossil ls ?OPTIONS? ?VERSION?
223 **
224 ** Show the names of all files in the current checkout. The -l provides
225 ** extra information about each file.
226 **
227 ** Options:
228 ** -l Provide extra information about each file.
229 ** --age Show when each file was committed
230 **
231 ** See also: changes, extra, status
232 */
233 void ls_cmd(void){
234 int vid;
235 Stmt q;
236 int isBrief;
237 int showAge;
238 char *zOrderBy = "pathname";
239
240 isBrief = find_option("l","l", 0)==0;
241 showAge = find_option("age",0,0)!=0;
242 db_must_be_within_tree();
243 vid = db_lget_int("checkout", 0);
244 if( find_option("t","t",0)!=0 ){
245 if( showAge ){
246 zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
247 }else{
248 zOrderBy = "mtime DESC";
249 }
250 }
251 verify_all_options();
252 vfile_check_signature(vid, 0);
253 if( showAge ){
254 db_prepare(&q,
255 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
256 " datetime(checkin_mtime(%d,rid),'unixepoch','localtime')"
257 " FROM vfile"
258 " ORDER BY %s", vid, zOrderBy
259 );
260 }else{
261 db_prepare(&q,
262 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
263 " FROM vfile"
264 " ORDER BY %s", zOrderBy
265 );
266 }
267 while( db_step(&q)==SQLITE_ROW ){
268 const char *zPathname = db_column_text(&q,0);
269 int isDeleted = db_column_int(&q, 1);
270 int isNew = db_column_int(&q,2)==0;
271 int chnged = db_column_int(&q,3);
272 int renamed = db_column_int(&q,4);
273 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
274 if( showAge ){
275 fossil_print("%s %s\n", db_column_text(&q, 5), zPathname);
276 }else if( isBrief ){
277 fossil_print("%s\n", zPathname);
278 }else if( isNew ){
279 fossil_print("ADDED %s\n", zPathname);
280 }else if( isDeleted ){
281 fossil_print("DELETED %s\n", zPathname);
@@ -299,16 +327,17 @@
327 Blob path;
328 Blob repo;
329 Stmt q;
330 int n;
331 const char *zIgnoreFlag = find_option("ignore",0,1);
332 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
333 int cwdRelative = 0;
334 Glob *pIgnore;
335 Blob rewrittenPathname;
336 const char *zPathname, *zDisplayName;
337
338 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
339 db_must_be_within_tree();
340 cwdRelative = determine_cwd_relative_option();
341 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
342 filename_collation());
343 n = strlen(g.zLocalRoot);
@@ -315,11 +344,11 @@
344 blob_init(&path, g.zLocalRoot, n-1);
345 if( zIgnoreFlag==0 ){
346 zIgnoreFlag = db_get("ignore-glob", 0);
347 }
348 pIgnore = glob_create(zIgnoreFlag);
349 vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
350 glob_free(pIgnore);
351 db_prepare(&q,
352 "SELECT x FROM sfile"
353 " WHERE x NOT IN (%s)"
354 " ORDER BY 1",
@@ -370,34 +399,36 @@
399 ** Options:
400 ** --dotfiles include files beginning with a dot (".")
401 ** --force Remove files without prompting
402 ** --ignore <CSG> ignore files matching patterns from the
403 ** comma separated list of glob patterns.
404 ** --temp Remove only Fossil-generated temporary files
405 **
406 ** See also: addremove, extra, status
407 */
408 void clean_cmd(void){
409 int allFlag;
410 unsigned scanFlags = 0;
411 const char *zIgnoreFlag;
412 Blob path, repo;
413 Stmt q;
414 int n;
415 Glob *pIgnore;
416
417 allFlag = find_option("force","f",0)!=0;
418 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
419 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
420 zIgnoreFlag = find_option("ignore",0,1);
421 db_must_be_within_tree();
422 if( zIgnoreFlag==0 ){
423 zIgnoreFlag = db_get("ignore-glob", 0);
424 }
425 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
426 n = strlen(g.zLocalRoot);
427 blob_init(&path, g.zLocalRoot, n-1);
428 pIgnore = glob_create(zIgnoreFlag);
429 vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
430 glob_free(pIgnore);
431 db_prepare(&q,
432 "SELECT %Q || x FROM sfile"
433 " WHERE x NOT IN (%s)"
434 " ORDER BY 1",
@@ -806,14 +837,10 @@
837 }
838 if( zColor && zColor[0] ){
839 /* One-time background color */
840 blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
841 }
 
 
 
 
842 if( azTag ){
843 for(i=0; azTag[i]; i++){
844 /* Add a symbolic tag to this check-in. The tag names have already
845 ** been sorted and converted using the %F format */
846 blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
847
+1 -1
--- src/checkout.c
+++ src/checkout.c
@@ -33,11 +33,11 @@
3333
int unsaved_changes(void){
3434
int vid;
3535
db_must_be_within_tree();
3636
vid = db_lget_int("checkout",0);
3737
if( vid==0 ) return 2;
38
- vfile_check_signature(vid, 1, 0);
38
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
3939
return db_exists("SELECT 1 FROM vfile WHERE chnged"
4040
" OR coalesce(origname!=pathname,0)");
4141
}
4242
4343
/*
4444
--- src/checkout.c
+++ src/checkout.c
@@ -33,11 +33,11 @@
33 int unsaved_changes(void){
34 int vid;
35 db_must_be_within_tree();
36 vid = db_lget_int("checkout",0);
37 if( vid==0 ) return 2;
38 vfile_check_signature(vid, 1, 0);
39 return db_exists("SELECT 1 FROM vfile WHERE chnged"
40 " OR coalesce(origname!=pathname,0)");
41 }
42
43 /*
44
--- src/checkout.c
+++ src/checkout.c
@@ -33,11 +33,11 @@
33 int unsaved_changes(void){
34 int vid;
35 db_must_be_within_tree();
36 vid = db_lget_int("checkout",0);
37 if( vid==0 ) return 2;
38 vfile_check_signature(vid, CKSIG_ENOTFILE);
39 return db_exists("SELECT 1 FROM vfile WHERE chnged"
40 " OR coalesce(origname!=pathname,0)");
41 }
42
43 /*
44
--- src/content.c
+++ src/content.c
@@ -894,5 +894,37 @@
894894
}
895895
db_finalize(&q);
896896
fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
897897
n2, n1, nErr);
898898
}
899
+
900
+/*
901
+** COMMAND: test-orphans
902
+**
903
+** Search the repository for orphaned artifacts
904
+*/
905
+void test_orphans(void){
906
+ Stmt q;
907
+ int cnt = 0;
908
+
909
+ db_find_and_open_repository(0, 0);
910
+ db_multi_exec(
911
+ "CREATE TEMP TABLE used(id INTEGER PRIMARY KEY ON CONFLICT IGNORE);"
912
+ "INSERT INTO used SELECT mid FROM mlink;" /* Manifests */
913
+ "INSERT INTO used SELECT fid FROM mlink;" /* Files */
914
+ "INSERT INTO used SELECT srcid FROM tagxref WHERE srcid>0;" /* Tags */
915
+ "INSERT INTO used SELECT rid FROM tagxref;" /* Wiki & tickets */
916
+ "INSERT INTO used SELECT rid FROM attachment JOIN blob ON src=uuid;"
917
+ "INSERT INTO used SELECT attachid FROM attachment;"
918
+ "INSERT INTO used SELECT objid FROM event;"
919
+ );
920
+ db_prepare(&q, "SELECT rid, uuid, size FROM blob WHERE rid NOT IN used");
921
+ while( db_step(&q)==SQLITE_ROW ){
922
+ fossil_print("%7d %s size: %d\n",
923
+ db_column_int(&q, 0),
924
+ db_column_text(&q, 1),
925
+ db_column_int(&q,2));
926
+ cnt++;
927
+ }
928
+ db_finalize(&q);
929
+ fossil_print("%d orphans\n", cnt);
930
+}
899931
--- src/content.c
+++ src/content.c
@@ -894,5 +894,37 @@
894 }
895 db_finalize(&q);
896 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
897 n2, n1, nErr);
898 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
899
--- src/content.c
+++ src/content.c
@@ -894,5 +894,37 @@
894 }
895 db_finalize(&q);
896 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
897 n2, n1, nErr);
898 }
899
900 /*
901 ** COMMAND: test-orphans
902 **
903 ** Search the repository for orphaned artifacts
904 */
905 void test_orphans(void){
906 Stmt q;
907 int cnt = 0;
908
909 db_find_and_open_repository(0, 0);
910 db_multi_exec(
911 "CREATE TEMP TABLE used(id INTEGER PRIMARY KEY ON CONFLICT IGNORE);"
912 "INSERT INTO used SELECT mid FROM mlink;" /* Manifests */
913 "INSERT INTO used SELECT fid FROM mlink;" /* Files */
914 "INSERT INTO used SELECT srcid FROM tagxref WHERE srcid>0;" /* Tags */
915 "INSERT INTO used SELECT rid FROM tagxref;" /* Wiki & tickets */
916 "INSERT INTO used SELECT rid FROM attachment JOIN blob ON src=uuid;"
917 "INSERT INTO used SELECT attachid FROM attachment;"
918 "INSERT INTO used SELECT objid FROM event;"
919 );
920 db_prepare(&q, "SELECT rid, uuid, size FROM blob WHERE rid NOT IN used");
921 while( db_step(&q)==SQLITE_ROW ){
922 fossil_print("%7d %s size: %d\n",
923 db_column_int(&q, 0),
924 db_column_text(&q, 1),
925 db_column_int(&q,2));
926 cnt++;
927 }
928 db_finalize(&q);
929 fossil_print("%d orphans\n", cnt);
930 }
931
+21 -3
--- src/db.c
+++ src/db.c
@@ -676,10 +676,26 @@
676676
sqlite3_value **argv
677677
){
678678
sqlite3_result_int64(context, time(0));
679679
}
680680
681
+/*
682
+** Function to return the check-in time for a file.
683
+*/
684
+void db_checkin_mtime_function(
685
+ sqlite3_context *context,
686
+ int argc,
687
+ sqlite3_value **argv
688
+){
689
+ i64 mtime;
690
+ int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
691
+ sqlite3_value_int(argv[1]), &mtime);
692
+ if( rc==0 ){
693
+ sqlite3_result_int64(context, mtime);
694
+ }
695
+}
696
+
681697
682698
/*
683699
** Open a database file. Return a pointer to the new database
684700
** connection. An error results in process abort.
685701
*/
@@ -698,10 +714,12 @@
698714
db_err(sqlite3_errmsg(db));
699715
}
700716
sqlite3_busy_timeout(db, 5000);
701717
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
702718
sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
719
+ sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
720
+ db_checkin_mtime_function, 0, 0);
703721
return db;
704722
}
705723
706724
707725
/*
@@ -722,11 +740,11 @@
722740
/*
723741
** zDbName is the name of a database file. If no other database
724742
** file is open, then open this one. If another database file is
725743
** already open, then attach zDbName using the name zLabel.
726744
*/
727
-static void db_open_or_attach(const char *zDbName, const char *zLabel){
745
+void db_open_or_attach(const char *zDbName, const char *zLabel){
728746
if( !g.db ){
729747
g.db = openDatabase(zDbName);
730748
g.zMainDbType = zLabel;
731749
db_connection_init();
732750
}else{
@@ -1591,19 +1609,19 @@
15911609
15921610
/*
15931611
** Return true if the string zVal represents "true" (or "false").
15941612
*/
15951613
int is_truth(const char *zVal){
1596
- static const char *azOn[] = { "on", "yes", "true", "1" };
1614
+ static const char *const azOn[] = { "on", "yes", "true", "1" };
15971615
int i;
15981616
for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
15991617
if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
16001618
}
16011619
return 0;
16021620
}
16031621
int is_false(const char *zVal){
1604
- static const char *azOff[] = { "off", "no", "false", "0" };
1622
+ static const char *const azOff[] = { "off", "no", "false", "0" };
16051623
int i;
16061624
for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
16071625
if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
16081626
}
16091627
return 0;
16101628
--- src/db.c
+++ src/db.c
@@ -676,10 +676,26 @@
676 sqlite3_value **argv
677 ){
678 sqlite3_result_int64(context, time(0));
679 }
680
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
682 /*
683 ** Open a database file. Return a pointer to the new database
684 ** connection. An error results in process abort.
685 */
@@ -698,10 +714,12 @@
698 db_err(sqlite3_errmsg(db));
699 }
700 sqlite3_busy_timeout(db, 5000);
701 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
702 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
 
 
703 return db;
704 }
705
706
707 /*
@@ -722,11 +740,11 @@
722 /*
723 ** zDbName is the name of a database file. If no other database
724 ** file is open, then open this one. If another database file is
725 ** already open, then attach zDbName using the name zLabel.
726 */
727 static void db_open_or_attach(const char *zDbName, const char *zLabel){
728 if( !g.db ){
729 g.db = openDatabase(zDbName);
730 g.zMainDbType = zLabel;
731 db_connection_init();
732 }else{
@@ -1591,19 +1609,19 @@
1591
1592 /*
1593 ** Return true if the string zVal represents "true" (or "false").
1594 */
1595 int is_truth(const char *zVal){
1596 static const char *azOn[] = { "on", "yes", "true", "1" };
1597 int i;
1598 for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
1599 if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
1600 }
1601 return 0;
1602 }
1603 int is_false(const char *zVal){
1604 static const char *azOff[] = { "off", "no", "false", "0" };
1605 int i;
1606 for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1607 if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
1608 }
1609 return 0;
1610
--- src/db.c
+++ src/db.c
@@ -676,10 +676,26 @@
676 sqlite3_value **argv
677 ){
678 sqlite3_result_int64(context, time(0));
679 }
680
681 /*
682 ** Function to return the check-in time for a file.
683 */
684 void db_checkin_mtime_function(
685 sqlite3_context *context,
686 int argc,
687 sqlite3_value **argv
688 ){
689 i64 mtime;
690 int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
691 sqlite3_value_int(argv[1]), &mtime);
692 if( rc==0 ){
693 sqlite3_result_int64(context, mtime);
694 }
695 }
696
697
698 /*
699 ** Open a database file. Return a pointer to the new database
700 ** connection. An error results in process abort.
701 */
@@ -698,10 +714,12 @@
714 db_err(sqlite3_errmsg(db));
715 }
716 sqlite3_busy_timeout(db, 5000);
717 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
718 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
719 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
720 db_checkin_mtime_function, 0, 0);
721 return db;
722 }
723
724
725 /*
@@ -722,11 +740,11 @@
740 /*
741 ** zDbName is the name of a database file. If no other database
742 ** file is open, then open this one. If another database file is
743 ** already open, then attach zDbName using the name zLabel.
744 */
745 void db_open_or_attach(const char *zDbName, const char *zLabel){
746 if( !g.db ){
747 g.db = openDatabase(zDbName);
748 g.zMainDbType = zLabel;
749 db_connection_init();
750 }else{
@@ -1591,19 +1609,19 @@
1609
1610 /*
1611 ** Return true if the string zVal represents "true" (or "false").
1612 */
1613 int is_truth(const char *zVal){
1614 static const char *const azOn[] = { "on", "yes", "true", "1" };
1615 int i;
1616 for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
1617 if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
1618 }
1619 return 0;
1620 }
1621 int is_false(const char *zVal){
1622 static const char *const azOff[] = { "off", "no", "false", "0" };
1623 int i;
1624 for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1625 if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
1626 }
1627 return 0;
1628
+21 -3
--- src/db.c
+++ src/db.c
@@ -676,10 +676,26 @@
676676
sqlite3_value **argv
677677
){
678678
sqlite3_result_int64(context, time(0));
679679
}
680680
681
+/*
682
+** Function to return the check-in time for a file.
683
+*/
684
+void db_checkin_mtime_function(
685
+ sqlite3_context *context,
686
+ int argc,
687
+ sqlite3_value **argv
688
+){
689
+ i64 mtime;
690
+ int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
691
+ sqlite3_value_int(argv[1]), &mtime);
692
+ if( rc==0 ){
693
+ sqlite3_result_int64(context, mtime);
694
+ }
695
+}
696
+
681697
682698
/*
683699
** Open a database file. Return a pointer to the new database
684700
** connection. An error results in process abort.
685701
*/
@@ -698,10 +714,12 @@
698714
db_err(sqlite3_errmsg(db));
699715
}
700716
sqlite3_busy_timeout(db, 5000);
701717
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
702718
sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
719
+ sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
720
+ db_checkin_mtime_function, 0, 0);
703721
return db;
704722
}
705723
706724
707725
/*
@@ -722,11 +740,11 @@
722740
/*
723741
** zDbName is the name of a database file. If no other database
724742
** file is open, then open this one. If another database file is
725743
** already open, then attach zDbName using the name zLabel.
726744
*/
727
-static void db_open_or_attach(const char *zDbName, const char *zLabel){
745
+void db_open_or_attach(const char *zDbName, const char *zLabel){
728746
if( !g.db ){
729747
g.db = openDatabase(zDbName);
730748
g.zMainDbType = zLabel;
731749
db_connection_init();
732750
}else{
@@ -1591,19 +1609,19 @@
15911609
15921610
/*
15931611
** Return true if the string zVal represents "true" (or "false").
15941612
*/
15951613
int is_truth(const char *zVal){
1596
- static const char *azOn[] = { "on", "yes", "true", "1" };
1614
+ static const char *const azOn[] = { "on", "yes", "true", "1" };
15971615
int i;
15981616
for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
15991617
if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
16001618
}
16011619
return 0;
16021620
}
16031621
int is_false(const char *zVal){
1604
- static const char *azOff[] = { "off", "no", "false", "0" };
1622
+ static const char *const azOff[] = { "off", "no", "false", "0" };
16051623
int i;
16061624
for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
16071625
if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
16081626
}
16091627
return 0;
16101628
--- src/db.c
+++ src/db.c
@@ -676,10 +676,26 @@
676 sqlite3_value **argv
677 ){
678 sqlite3_result_int64(context, time(0));
679 }
680
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
682 /*
683 ** Open a database file. Return a pointer to the new database
684 ** connection. An error results in process abort.
685 */
@@ -698,10 +714,12 @@
698 db_err(sqlite3_errmsg(db));
699 }
700 sqlite3_busy_timeout(db, 5000);
701 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
702 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
 
 
703 return db;
704 }
705
706
707 /*
@@ -722,11 +740,11 @@
722 /*
723 ** zDbName is the name of a database file. If no other database
724 ** file is open, then open this one. If another database file is
725 ** already open, then attach zDbName using the name zLabel.
726 */
727 static void db_open_or_attach(const char *zDbName, const char *zLabel){
728 if( !g.db ){
729 g.db = openDatabase(zDbName);
730 g.zMainDbType = zLabel;
731 db_connection_init();
732 }else{
@@ -1591,19 +1609,19 @@
1591
1592 /*
1593 ** Return true if the string zVal represents "true" (or "false").
1594 */
1595 int is_truth(const char *zVal){
1596 static const char *azOn[] = { "on", "yes", "true", "1" };
1597 int i;
1598 for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
1599 if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
1600 }
1601 return 0;
1602 }
1603 int is_false(const char *zVal){
1604 static const char *azOff[] = { "off", "no", "false", "0" };
1605 int i;
1606 for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1607 if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
1608 }
1609 return 0;
1610
--- src/db.c
+++ src/db.c
@@ -676,10 +676,26 @@
676 sqlite3_value **argv
677 ){
678 sqlite3_result_int64(context, time(0));
679 }
680
681 /*
682 ** Function to return the check-in time for a file.
683 */
684 void db_checkin_mtime_function(
685 sqlite3_context *context,
686 int argc,
687 sqlite3_value **argv
688 ){
689 i64 mtime;
690 int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
691 sqlite3_value_int(argv[1]), &mtime);
692 if( rc==0 ){
693 sqlite3_result_int64(context, mtime);
694 }
695 }
696
697
698 /*
699 ** Open a database file. Return a pointer to the new database
700 ** connection. An error results in process abort.
701 */
@@ -698,10 +714,12 @@
714 db_err(sqlite3_errmsg(db));
715 }
716 sqlite3_busy_timeout(db, 5000);
717 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
718 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
719 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
720 db_checkin_mtime_function, 0, 0);
721 return db;
722 }
723
724
725 /*
@@ -722,11 +740,11 @@
740 /*
741 ** zDbName is the name of a database file. If no other database
742 ** file is open, then open this one. If another database file is
743 ** already open, then attach zDbName using the name zLabel.
744 */
745 void db_open_or_attach(const char *zDbName, const char *zLabel){
746 if( !g.db ){
747 g.db = openDatabase(zDbName);
748 g.zMainDbType = zLabel;
749 db_connection_init();
750 }else{
@@ -1591,19 +1609,19 @@
1609
1610 /*
1611 ** Return true if the string zVal represents "true" (or "false").
1612 */
1613 int is_truth(const char *zVal){
1614 static const char *const azOn[] = { "on", "yes", "true", "1" };
1615 int i;
1616 for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
1617 if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
1618 }
1619 return 0;
1620 }
1621 int is_false(const char *zVal){
1622 static const char *const azOff[] = { "off", "no", "false", "0" };
1623 int i;
1624 for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1625 if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
1626 }
1627 return 0;
1628
--- src/descendants.c
+++ src/descendants.c
@@ -156,11 +156,11 @@
156156
157157
/*
158158
** Load the record ID rid and up to N-1 closest ancestors into
159159
** the "ok" table.
160160
*/
161
-void compute_ancestors(int rid, int N){
161
+void compute_ancestors(int rid, int N, int directOnly){
162162
Bag seen;
163163
PQueue queue;
164164
Stmt ins;
165165
Stmt q;
166166
bag_init(&seen);
@@ -168,11 +168,12 @@
168168
bag_insert(&seen, rid);
169169
pqueuex_insert(&queue, rid, 0.0, 0);
170170
db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
171171
db_prepare(&q,
172172
"SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
173
- " WHERE a.cid=:rid"
173
+ " WHERE a.cid=:rid %s",
174
+ directOnly ? " AND a.isprim" : ""
174175
);
175176
while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){
176177
db_bind_int(&ins, ":rid", rid);
177178
db_step(&ins);
178179
db_reset(&ins);
@@ -202,11 +203,12 @@
202203
void compute_direct_ancestors(int rid, int N){
203204
Stmt ins;
204205
Stmt q;
205206
int gen = 0;
206207
db_multi_exec(
207
- "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER, generation INTEGER PRIMARY KEY);"
208
+ "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER,"
209
+ " generation INTEGER PRIMARY KEY);"
208210
"DELETE FROM ancestor;"
209211
"INSERT INTO ancestor VALUES(%d, 0);", rid
210212
);
211213
db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
212214
db_prepare(&q,
@@ -225,10 +227,44 @@
225227
db_reset(&ins);
226228
}
227229
db_finalize(&ins);
228230
db_finalize(&q);
229231
}
232
+
233
+/*
234
+** Compute the "mtime" of the file given whose blob.rid is "fid" that
235
+** is part of check-in "vid". The mtime will be the mtime on vid or
236
+** some ancestor of vid where fid first appears.
237
+*/
238
+int mtime_of_manifest_file(
239
+ int vid, /* The check-in that contains fid */
240
+ int fid, /* The id of the file whose check-in time is sought */
241
+ i64 *pMTime /* Write result here */
242
+){
243
+ static int prevVid = -1;
244
+ static Stmt q;
245
+
246
+ if( prevVid!=vid ){
247
+ prevVid = vid;
248
+ db_multi_exec("DROP TABLE IF EXISTS temp.ok;"
249
+ "CREATE TEMP TABLE ok(x INTEGER PRIMARY KEY);");
250
+ compute_ancestors(vid, 100000000, 1);
251
+ }
252
+ db_static_prepare(&q,
253
+ "SELECT (max(event.mtime)-2440587.5)*86400 FROM mlink, event"
254
+ " WHERE mlink.mid=event.objid"
255
+ " AND +mlink.mid IN ok"
256
+ " AND mlink.fid=:fid");
257
+ db_bind_int(&q, ":fid", fid);
258
+ if( db_step(&q)!=SQLITE_ROW ){
259
+ db_reset(&q);
260
+ return 1;
261
+ }
262
+ *pMTime = db_column_int64(&q, 0);
263
+ db_reset(&q);
264
+ return 0;
265
+}
230266
231267
/*
232268
** Load the record ID rid and up to N-1 closest descendants into
233269
** the "ok" table.
234270
*/
235271
--- src/descendants.c
+++ src/descendants.c
@@ -156,11 +156,11 @@
156
157 /*
158 ** Load the record ID rid and up to N-1 closest ancestors into
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);
@@ -168,11 +168,12 @@
168 bag_insert(&seen, rid);
169 pqueuex_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 = pqueuex_extract(&queue, 0))!=0 ){
176 db_bind_int(&ins, ":rid", rid);
177 db_step(&ins);
178 db_reset(&ins);
@@ -202,11 +203,12 @@
202 void compute_direct_ancestors(int rid, int N){
203 Stmt ins;
204 Stmt q;
205 int gen = 0;
206 db_multi_exec(
207 "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER, generation INTEGER PRIMARY KEY);"
 
208 "DELETE FROM ancestor;"
209 "INSERT INTO ancestor VALUES(%d, 0);", rid
210 );
211 db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
212 db_prepare(&q,
@@ -225,10 +227,44 @@
225 db_reset(&ins);
226 }
227 db_finalize(&ins);
228 db_finalize(&q);
229 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
231 /*
232 ** Load the record ID rid and up to N-1 closest descendants into
233 ** the "ok" table.
234 */
235
--- src/descendants.c
+++ src/descendants.c
@@ -156,11 +156,11 @@
156
157 /*
158 ** Load the record ID rid and up to N-1 closest ancestors into
159 ** the "ok" table.
160 */
161 void compute_ancestors(int rid, int N, int directOnly){
162 Bag seen;
163 PQueue queue;
164 Stmt ins;
165 Stmt q;
166 bag_init(&seen);
@@ -168,11 +168,12 @@
168 bag_insert(&seen, rid);
169 pqueuex_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 %s",
174 directOnly ? " AND a.isprim" : ""
175 );
176 while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){
177 db_bind_int(&ins, ":rid", rid);
178 db_step(&ins);
179 db_reset(&ins);
@@ -202,11 +203,12 @@
203 void compute_direct_ancestors(int rid, int N){
204 Stmt ins;
205 Stmt q;
206 int gen = 0;
207 db_multi_exec(
208 "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER,"
209 " generation INTEGER PRIMARY KEY);"
210 "DELETE FROM ancestor;"
211 "INSERT INTO ancestor VALUES(%d, 0);", rid
212 );
213 db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
214 db_prepare(&q,
@@ -225,10 +227,44 @@
227 db_reset(&ins);
228 }
229 db_finalize(&ins);
230 db_finalize(&q);
231 }
232
233 /*
234 ** Compute the "mtime" of the file given whose blob.rid is "fid" that
235 ** is part of check-in "vid". The mtime will be the mtime on vid or
236 ** some ancestor of vid where fid first appears.
237 */
238 int mtime_of_manifest_file(
239 int vid, /* The check-in that contains fid */
240 int fid, /* The id of the file whose check-in time is sought */
241 i64 *pMTime /* Write result here */
242 ){
243 static int prevVid = -1;
244 static Stmt q;
245
246 if( prevVid!=vid ){
247 prevVid = vid;
248 db_multi_exec("DROP TABLE IF EXISTS temp.ok;"
249 "CREATE TEMP TABLE ok(x INTEGER PRIMARY KEY);");
250 compute_ancestors(vid, 100000000, 1);
251 }
252 db_static_prepare(&q,
253 "SELECT (max(event.mtime)-2440587.5)*86400 FROM mlink, event"
254 " WHERE mlink.mid=event.objid"
255 " AND +mlink.mid IN ok"
256 " AND mlink.fid=:fid");
257 db_bind_int(&q, ":fid", fid);
258 if( db_step(&q)!=SQLITE_ROW ){
259 db_reset(&q);
260 return 1;
261 }
262 *pMTime = db_column_int64(&q, 0);
263 db_reset(&q);
264 return 0;
265 }
266
267 /*
268 ** Load the record ID rid and up to N-1 closest descendants into
269 ** the "ok" table.
270 */
271
+1 -1
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -329,11 +329,11 @@
329329
Stmt q;
330330
int asNewFile; /* Treat non-existant files as empty files */
331331
332332
asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
333333
vid = db_lget_int("checkout", 0);
334
- vfile_check_signature(vid, 1, 0);
334
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
335335
blob_zero(&sql);
336336
db_begin_transaction();
337337
if( zFrom ){
338338
int rid = name_to_typed_rid(zFrom, "ci");
339339
if( !is_a_version(rid) ){
340340
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -329,11 +329,11 @@
329 Stmt q;
330 int asNewFile; /* Treat non-existant files as empty files */
331
332 asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
333 vid = db_lget_int("checkout", 0);
334 vfile_check_signature(vid, 1, 0);
335 blob_zero(&sql);
336 db_begin_transaction();
337 if( zFrom ){
338 int rid = name_to_typed_rid(zFrom, "ci");
339 if( !is_a_version(rid) ){
340
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -329,11 +329,11 @@
329 Stmt q;
330 int asNewFile; /* Treat non-existant files as empty files */
331
332 asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
333 vid = db_lget_int("checkout", 0);
334 vfile_check_signature(vid, CKSIG_ENOTFILE);
335 blob_zero(&sql);
336 db_begin_transaction();
337 if( zFrom ){
338 int rid = name_to_typed_rid(zFrom, "ci");
339 if( !is_a_version(rid) ){
340
+1 -1
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -329,11 +329,11 @@
329329
Stmt q;
330330
int asNewFile; /* Treat non-existant files as empty files */
331331
332332
asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
333333
vid = db_lget_int("checkout", 0);
334
- vfile_check_signature(vid, 1, 0);
334
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
335335
blob_zero(&sql);
336336
db_begin_transaction();
337337
if( zFrom ){
338338
int rid = name_to_typed_rid(zFrom, "ci");
339339
if( !is_a_version(rid) ){
340340
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -329,11 +329,11 @@
329 Stmt q;
330 int asNewFile; /* Treat non-existant files as empty files */
331
332 asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
333 vid = db_lget_int("checkout", 0);
334 vfile_check_signature(vid, 1, 0);
335 blob_zero(&sql);
336 db_begin_transaction();
337 if( zFrom ){
338 int rid = name_to_typed_rid(zFrom, "ci");
339 if( !is_a_version(rid) ){
340
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -329,11 +329,11 @@
329 Stmt q;
330 int asNewFile; /* Treat non-existant files as empty files */
331
332 asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
333 vid = db_lget_int("checkout", 0);
334 vfile_check_signature(vid, CKSIG_ENOTFILE);
335 blob_zero(&sql);
336 db_begin_transaction();
337 if( zFrom ){
338 int rid = name_to_typed_rid(zFrom, "ci");
339 if( !is_a_version(rid) ){
340
+44
--- src/file.c
+++ src/file.c
@@ -34,10 +34,11 @@
3434
** On Windows, include the Platform SDK header file.
3535
*/
3636
#ifdef _WIN32
3737
# include <direct.h>
3838
# include <windows.h>
39
+# include <sys/utime.h>
3940
#endif
4041
4142
/*
4243
** The file status information from the most recent stat() call.
4344
**
@@ -389,10 +390,53 @@
389390
}
390391
}
391392
#endif /* _WIN32 */
392393
return rc;
393394
}
395
+
396
+/*
397
+** Set the mtime for a file.
398
+*/
399
+void file_set_mtime(const char *zFilename, i64 newMTime){
400
+#if !defined(_WIN32)
401
+ struct timeval tv[2];
402
+ memset(tv, 0, sizeof(tv[0])*2);
403
+ tv[0].tv_sec = newMTime;
404
+ tv[1].tv_sec = newMTime;
405
+ utimes(zFilename, tv);
406
+#else
407
+ struct _utimbuf tb;
408
+ wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
409
+ tb.actime = newMTime;
410
+ tb.modtime = newMTime;
411
+ _wutime(zMbcs, &tb);
412
+ fossil_mbcs_free(zMbcs);
413
+#endif
414
+}
415
+
416
+/*
417
+** COMMAND: test-set-mtime
418
+**
419
+** Usage: %fossil test-set-mtime FILENAME DATE/TIME
420
+**
421
+** Sets the mtime of the named file to the date/time shown.
422
+*/
423
+void test_set_mtime(void){
424
+ const char *zFile;
425
+ char *zDate;
426
+ i64 iMTime;
427
+ if( g.argc!=4 ){
428
+ usage("test-set-mtime FILENAME DATE/TIME");
429
+ }
430
+ db_open_or_attach(":memory:", "mem");
431
+ iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]);
432
+ zFile = g.argv[2];
433
+ file_set_mtime(zFile, iMTime);
434
+ iMTime = file_wd_mtime(zFile);
435
+ zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime);
436
+ fossil_print("Set mtime of \"%s\" to %s (%lld)\n", zFile, zDate, iMTime);
437
+}
394438
395439
/*
396440
** Delete a file.
397441
*/
398442
void file_delete(const char *zFilename){
399443
--- src/file.c
+++ src/file.c
@@ -34,10 +34,11 @@
34 ** On Windows, include the Platform SDK header file.
35 */
36 #ifdef _WIN32
37 # include <direct.h>
38 # include <windows.h>
 
39 #endif
40
41 /*
42 ** The file status information from the most recent stat() call.
43 **
@@ -389,10 +390,53 @@
389 }
390 }
391 #endif /* _WIN32 */
392 return rc;
393 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
395 /*
396 ** Delete a file.
397 */
398 void file_delete(const char *zFilename){
399
--- src/file.c
+++ src/file.c
@@ -34,10 +34,11 @@
34 ** On Windows, include the Platform SDK header file.
35 */
36 #ifdef _WIN32
37 # include <direct.h>
38 # include <windows.h>
39 # include <sys/utime.h>
40 #endif
41
42 /*
43 ** The file status information from the most recent stat() call.
44 **
@@ -389,10 +390,53 @@
390 }
391 }
392 #endif /* _WIN32 */
393 return rc;
394 }
395
396 /*
397 ** Set the mtime for a file.
398 */
399 void file_set_mtime(const char *zFilename, i64 newMTime){
400 #if !defined(_WIN32)
401 struct timeval tv[2];
402 memset(tv, 0, sizeof(tv[0])*2);
403 tv[0].tv_sec = newMTime;
404 tv[1].tv_sec = newMTime;
405 utimes(zFilename, tv);
406 #else
407 struct _utimbuf tb;
408 wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
409 tb.actime = newMTime;
410 tb.modtime = newMTime;
411 _wutime(zMbcs, &tb);
412 fossil_mbcs_free(zMbcs);
413 #endif
414 }
415
416 /*
417 ** COMMAND: test-set-mtime
418 **
419 ** Usage: %fossil test-set-mtime FILENAME DATE/TIME
420 **
421 ** Sets the mtime of the named file to the date/time shown.
422 */
423 void test_set_mtime(void){
424 const char *zFile;
425 char *zDate;
426 i64 iMTime;
427 if( g.argc!=4 ){
428 usage("test-set-mtime FILENAME DATE/TIME");
429 }
430 db_open_or_attach(":memory:", "mem");
431 iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]);
432 zFile = g.argv[2];
433 file_set_mtime(zFile, iMTime);
434 iMTime = file_wd_mtime(zFile);
435 zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime);
436 fossil_print("Set mtime of \"%s\" to %s (%lld)\n", zFile, zDate, iMTime);
437 }
438
439 /*
440 ** Delete a file.
441 */
442 void file_delete(const char *zFilename){
443
+1 -1
--- src/finfo.c
+++ src/finfo.c
@@ -66,11 +66,11 @@
6666
if( g.argc!=3 ) usage("-s|--status FILENAME");
6767
vid = db_lget_int("checkout", 0);
6868
if( vid==0 ){
6969
fossil_panic("no checkout to finfo files in");
7070
}
71
- vfile_check_signature(vid, 1, 0);
71
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
7272
file_tree_name(g.argv[2], &fname, 1);
7373
db_prepare(&q,
7474
"SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
7575
" FROM vfile WHERE vfile.pathname=%B %s",
7676
&fname, filename_collation());
7777
--- src/finfo.c
+++ src/finfo.c
@@ -66,11 +66,11 @@
66 if( g.argc!=3 ) usage("-s|--status FILENAME");
67 vid = db_lget_int("checkout", 0);
68 if( vid==0 ){
69 fossil_panic("no checkout to finfo files in");
70 }
71 vfile_check_signature(vid, 1, 0);
72 file_tree_name(g.argv[2], &fname, 1);
73 db_prepare(&q,
74 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
75 " FROM vfile WHERE vfile.pathname=%B %s",
76 &fname, filename_collation());
77
--- src/finfo.c
+++ src/finfo.c
@@ -66,11 +66,11 @@
66 if( g.argc!=3 ) usage("-s|--status FILENAME");
67 vid = db_lget_int("checkout", 0);
68 if( vid==0 ){
69 fossil_panic("no checkout to finfo files in");
70 }
71 vfile_check_signature(vid, CKSIG_ENOTFILE);
72 file_tree_name(g.argv[2], &fname, 1);
73 db_prepare(&q,
74 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
75 " FROM vfile WHERE vfile.pathname=%B %s",
76 &fname, filename_collation());
77
+3 -2
--- src/info.c
+++ src/info.c
@@ -631,10 +631,11 @@
631631
}
632632
@ </td></tr>
633633
@ <tr><th>Other&nbsp;Links:</th>
634634
@ <td>
635635
@ %z(href("%R/dir?ci=%S",zUuid))files</a>
636
+ @ | %z(href("%R/fileage?name=%S",zUuid))file ages</a>
636637
@ | %z(href("%R/artifact/%S",zUuid))manifest</a>
637638
@ | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)">
638639
@ vdiff to parent branch</a>
639640
if( g.perm.Write ){
640641
@ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
@@ -983,15 +984,15 @@
983984
}else{
984985
cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
985986
}
986987
if( cmp<0 ){
987988
append_file_change_line(pFileFrom->zName,
988
- pFileFrom->zUuid, 0, 0, 0, 0);
989
+ pFileFrom->zUuid, 0, 0, diffFlags, 0);
989990
pFileFrom = manifest_file_next(pFrom, 0);
990991
}else if( cmp>0 ){
991992
append_file_change_line(pFileTo->zName,
992
- 0, pFileTo->zUuid, 0, 0,
993
+ 0, pFileTo->zUuid, 0, diffFlags,
993994
manifest_file_mperm(pFileTo));
994995
pFileTo = manifest_file_next(pTo, 0);
995996
}else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
996997
/* No changes */
997998
pFileFrom = manifest_file_next(pFrom, 0);
998999
--- src/info.c
+++ src/info.c
@@ -631,10 +631,11 @@
631 }
632 @ </td></tr>
633 @ <tr><th>Other&nbsp;Links:</th>
634 @ <td>
635 @ %z(href("%R/dir?ci=%S",zUuid))files</a>
 
636 @ | %z(href("%R/artifact/%S",zUuid))manifest</a>
637 @ | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)">
638 @ vdiff to parent branch</a>
639 if( g.perm.Write ){
640 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
@@ -983,15 +984,15 @@
983 }else{
984 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
985 }
986 if( cmp<0 ){
987 append_file_change_line(pFileFrom->zName,
988 pFileFrom->zUuid, 0, 0, 0, 0);
989 pFileFrom = manifest_file_next(pFrom, 0);
990 }else if( cmp>0 ){
991 append_file_change_line(pFileTo->zName,
992 0, pFileTo->zUuid, 0, 0,
993 manifest_file_mperm(pFileTo));
994 pFileTo = manifest_file_next(pTo, 0);
995 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
996 /* No changes */
997 pFileFrom = manifest_file_next(pFrom, 0);
998
--- src/info.c
+++ src/info.c
@@ -631,10 +631,11 @@
631 }
632 @ </td></tr>
633 @ <tr><th>Other&nbsp;Links:</th>
634 @ <td>
635 @ %z(href("%R/dir?ci=%S",zUuid))files</a>
636 @ | %z(href("%R/fileage?name=%S",zUuid))file ages</a>
637 @ | %z(href("%R/artifact/%S",zUuid))manifest</a>
638 @ | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)">
639 @ vdiff to parent branch</a>
640 if( g.perm.Write ){
641 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
@@ -983,15 +984,15 @@
984 }else{
985 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
986 }
987 if( cmp<0 ){
988 append_file_change_line(pFileFrom->zName,
989 pFileFrom->zUuid, 0, 0, diffFlags, 0);
990 pFileFrom = manifest_file_next(pFrom, 0);
991 }else if( cmp>0 ){
992 append_file_change_line(pFileTo->zName,
993 0, pFileTo->zUuid, 0, diffFlags,
994 manifest_file_mperm(pFileTo));
995 pFileTo = manifest_file_next(pTo, 0);
996 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
997 /* No changes */
998 pFileFrom = manifest_file_next(pFrom, 0);
999
+3 -2
--- src/info.c
+++ src/info.c
@@ -631,10 +631,11 @@
631631
}
632632
@ </td></tr>
633633
@ <tr><th>Other&nbsp;Links:</th>
634634
@ <td>
635635
@ %z(href("%R/dir?ci=%S",zUuid))files</a>
636
+ @ | %z(href("%R/fileage?name=%S",zUuid))file ages</a>
636637
@ | %z(href("%R/artifact/%S",zUuid))manifest</a>
637638
@ | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)">
638639
@ vdiff to parent branch</a>
639640
if( g.perm.Write ){
640641
@ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
@@ -983,15 +984,15 @@
983984
}else{
984985
cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
985986
}
986987
if( cmp<0 ){
987988
append_file_change_line(pFileFrom->zName,
988
- pFileFrom->zUuid, 0, 0, 0, 0);
989
+ pFileFrom->zUuid, 0, 0, diffFlags, 0);
989990
pFileFrom = manifest_file_next(pFrom, 0);
990991
}else if( cmp>0 ){
991992
append_file_change_line(pFileTo->zName,
992
- 0, pFileTo->zUuid, 0, 0,
993
+ 0, pFileTo->zUuid, 0, diffFlags,
993994
manifest_file_mperm(pFileTo));
994995
pFileTo = manifest_file_next(pTo, 0);
995996
}else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
996997
/* No changes */
997998
pFileFrom = manifest_file_next(pFrom, 0);
998999
--- src/info.c
+++ src/info.c
@@ -631,10 +631,11 @@
631 }
632 @ </td></tr>
633 @ <tr><th>Other&nbsp;Links:</th>
634 @ <td>
635 @ %z(href("%R/dir?ci=%S",zUuid))files</a>
 
636 @ | %z(href("%R/artifact/%S",zUuid))manifest</a>
637 @ | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)">
638 @ vdiff to parent branch</a>
639 if( g.perm.Write ){
640 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
@@ -983,15 +984,15 @@
983 }else{
984 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
985 }
986 if( cmp<0 ){
987 append_file_change_line(pFileFrom->zName,
988 pFileFrom->zUuid, 0, 0, 0, 0);
989 pFileFrom = manifest_file_next(pFrom, 0);
990 }else if( cmp>0 ){
991 append_file_change_line(pFileTo->zName,
992 0, pFileTo->zUuid, 0, 0,
993 manifest_file_mperm(pFileTo));
994 pFileTo = manifest_file_next(pTo, 0);
995 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
996 /* No changes */
997 pFileFrom = manifest_file_next(pFrom, 0);
998
--- src/info.c
+++ src/info.c
@@ -631,10 +631,11 @@
631 }
632 @ </td></tr>
633 @ <tr><th>Other&nbsp;Links:</th>
634 @ <td>
635 @ %z(href("%R/dir?ci=%S",zUuid))files</a>
636 @ | %z(href("%R/fileage?name=%S",zUuid))file ages</a>
637 @ | %z(href("%R/artifact/%S",zUuid))manifest</a>
638 @ | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)">
639 @ vdiff to parent branch</a>
640 if( g.perm.Write ){
641 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
@@ -983,15 +984,15 @@
984 }else{
985 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
986 }
987 if( cmp<0 ){
988 append_file_change_line(pFileFrom->zName,
989 pFileFrom->zUuid, 0, 0, diffFlags, 0);
990 pFileFrom = manifest_file_next(pFrom, 0);
991 }else if( cmp>0 ){
992 append_file_change_line(pFileTo->zName,
993 0, pFileTo->zUuid, 0, diffFlags,
994 manifest_file_mperm(pFileTo));
995 pFileTo = manifest_file_next(pTo, 0);
996 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
997 /* No changes */
998 pFileFrom = manifest_file_next(pFrom, 0);
999
+2
--- src/main.c
+++ src/main.c
@@ -555,10 +555,11 @@
555555
newArgv[j] = 0;
556556
g.argc = j;
557557
g.argv = newArgv;
558558
}
559559
560
+#ifdef FOSSIL_ENABLE_TCL
560561
/*
561562
** Make a deep copy of the provided argument array and return it.
562563
*/
563564
static char **copy_args(int argc, char **argv){
564565
char **zNewArgv;
@@ -568,10 +569,11 @@
568569
for(i=0; i<argc; i++){
569570
zNewArgv[i] = fossil_strdup(argv[i]);
570571
}
571572
return zNewArgv;
572573
}
574
+#endif
573575
574576
/*
575577
** This procedure runs first.
576578
*/
577579
int main(int argc, char **argv)
578580
--- src/main.c
+++ src/main.c
@@ -555,10 +555,11 @@
555 newArgv[j] = 0;
556 g.argc = j;
557 g.argv = newArgv;
558 }
559
 
560 /*
561 ** Make a deep copy of the provided argument array and return it.
562 */
563 static char **copy_args(int argc, char **argv){
564 char **zNewArgv;
@@ -568,10 +569,11 @@
568 for(i=0; i<argc; i++){
569 zNewArgv[i] = fossil_strdup(argv[i]);
570 }
571 return zNewArgv;
572 }
 
573
574 /*
575 ** This procedure runs first.
576 */
577 int main(int argc, char **argv)
578
--- src/main.c
+++ src/main.c
@@ -555,10 +555,11 @@
555 newArgv[j] = 0;
556 g.argc = j;
557 g.argv = newArgv;
558 }
559
560 #ifdef FOSSIL_ENABLE_TCL
561 /*
562 ** Make a deep copy of the provided argument array and return it.
563 */
564 static char **copy_args(int argc, char **argv){
565 char **zNewArgv;
@@ -568,10 +569,11 @@
569 for(i=0; i<argc; i++){
570 zNewArgv[i] = fossil_strdup(argv[i]);
571 }
572 return zNewArgv;
573 }
574 #endif
575
576 /*
577 ** This procedure runs first.
578 */
579 int main(int argc, char **argv)
580
+1 -1
--- src/merge.c
+++ src/merge.c
@@ -189,11 +189,11 @@
189189
}
190190
if( detailFlag ){
191191
print_checkin_description(mid, 12, "merge-from:");
192192
print_checkin_description(pid, 12, "baseline:");
193193
}
194
- vfile_check_signature(vid, 1, 0);
194
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
195195
db_begin_transaction();
196196
if( !nochangeFlag ) undo_begin();
197197
load_vfile_from_rid(mid);
198198
load_vfile_from_rid(pid);
199199
if( debugFlag ){
200200
--- src/merge.c
+++ src/merge.c
@@ -189,11 +189,11 @@
189 }
190 if( detailFlag ){
191 print_checkin_description(mid, 12, "merge-from:");
192 print_checkin_description(pid, 12, "baseline:");
193 }
194 vfile_check_signature(vid, 1, 0);
195 db_begin_transaction();
196 if( !nochangeFlag ) undo_begin();
197 load_vfile_from_rid(mid);
198 load_vfile_from_rid(pid);
199 if( debugFlag ){
200
--- src/merge.c
+++ src/merge.c
@@ -189,11 +189,11 @@
189 }
190 if( detailFlag ){
191 print_checkin_description(mid, 12, "merge-from:");
192 print_checkin_description(pid, 12, "baseline:");
193 }
194 vfile_check_signature(vid, CKSIG_ENOTFILE);
195 db_begin_transaction();
196 if( !nochangeFlag ) undo_begin();
197 load_vfile_from_rid(mid);
198 load_vfile_from_rid(pid);
199 if( debugFlag ){
200
+1 -1
--- src/merge.c
+++ src/merge.c
@@ -189,11 +189,11 @@
189189
}
190190
if( detailFlag ){
191191
print_checkin_description(mid, 12, "merge-from:");
192192
print_checkin_description(pid, 12, "baseline:");
193193
}
194
- vfile_check_signature(vid, 1, 0);
194
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
195195
db_begin_transaction();
196196
if( !nochangeFlag ) undo_begin();
197197
load_vfile_from_rid(mid);
198198
load_vfile_from_rid(pid);
199199
if( debugFlag ){
200200
--- src/merge.c
+++ src/merge.c
@@ -189,11 +189,11 @@
189 }
190 if( detailFlag ){
191 print_checkin_description(mid, 12, "merge-from:");
192 print_checkin_description(pid, 12, "baseline:");
193 }
194 vfile_check_signature(vid, 1, 0);
195 db_begin_transaction();
196 if( !nochangeFlag ) undo_begin();
197 load_vfile_from_rid(mid);
198 load_vfile_from_rid(pid);
199 if( debugFlag ){
200
--- src/merge.c
+++ src/merge.c
@@ -189,11 +189,11 @@
189 }
190 if( detailFlag ){
191 print_checkin_description(mid, 12, "merge-from:");
192 print_checkin_description(pid, 12, "baseline:");
193 }
194 vfile_check_signature(vid, CKSIG_ENOTFILE);
195 db_begin_transaction();
196 if( !nochangeFlag ) undo_begin();
197 load_vfile_from_rid(mid);
198 load_vfile_from_rid(pid);
199 if( debugFlag ){
200
+9 -5
--- src/name.c
+++ src/name.c
@@ -261,15 +261,19 @@
261261
if( rid>0 ) return rid;
262262
263263
/* Undocumented: numeric tags get translated directly into the RID */
264264
for(i=0; fossil_isdigit(zTag[i]); i++){}
265265
if( zTag[i]==0 ){
266
- rid = db_int(0,
267
- "SELECT event.objid"
268
- " FROM event"
269
- " WHERE event.objid=%s"
270
- " AND event.type GLOB '%q'", zTag, zType);
266
+ if( strcmp(zType,"*")==0 ){
267
+ rid = atoi(zTag);
268
+ }else{
269
+ rid = db_int(0,
270
+ "SELECT event.objid"
271
+ " FROM event"
272
+ " WHERE event.objid=%s"
273
+ " AND event.type GLOB '%q'", zTag, zType);
274
+ }
271275
}
272276
return rid;
273277
}
274278
275279
276280
--- src/name.c
+++ src/name.c
@@ -261,15 +261,19 @@
261 if( rid>0 ) return rid;
262
263 /* Undocumented: numeric tags get translated directly into the RID */
264 for(i=0; fossil_isdigit(zTag[i]); i++){}
265 if( zTag[i]==0 ){
266 rid = db_int(0,
267 "SELECT event.objid"
268 " FROM event"
269 " WHERE event.objid=%s"
270 " AND event.type GLOB '%q'", zTag, zType);
 
 
 
 
271 }
272 return rid;
273 }
274
275
276
--- src/name.c
+++ src/name.c
@@ -261,15 +261,19 @@
261 if( rid>0 ) return rid;
262
263 /* Undocumented: numeric tags get translated directly into the RID */
264 for(i=0; fossil_isdigit(zTag[i]); i++){}
265 if( zTag[i]==0 ){
266 if( strcmp(zType,"*")==0 ){
267 rid = atoi(zTag);
268 }else{
269 rid = db_int(0,
270 "SELECT event.objid"
271 " FROM event"
272 " WHERE event.objid=%s"
273 " AND event.type GLOB '%q'", zTag, zType);
274 }
275 }
276 return rid;
277 }
278
279
280
+9 -5
--- src/name.c
+++ src/name.c
@@ -261,15 +261,19 @@
261261
if( rid>0 ) return rid;
262262
263263
/* Undocumented: numeric tags get translated directly into the RID */
264264
for(i=0; fossil_isdigit(zTag[i]); i++){}
265265
if( zTag[i]==0 ){
266
- rid = db_int(0,
267
- "SELECT event.objid"
268
- " FROM event"
269
- " WHERE event.objid=%s"
270
- " AND event.type GLOB '%q'", zTag, zType);
266
+ if( strcmp(zType,"*")==0 ){
267
+ rid = atoi(zTag);
268
+ }else{
269
+ rid = db_int(0,
270
+ "SELECT event.objid"
271
+ " FROM event"
272
+ " WHERE event.objid=%s"
273
+ " AND event.type GLOB '%q'", zTag, zType);
274
+ }
271275
}
272276
return rid;
273277
}
274278
275279
276280
--- src/name.c
+++ src/name.c
@@ -261,15 +261,19 @@
261 if( rid>0 ) return rid;
262
263 /* Undocumented: numeric tags get translated directly into the RID */
264 for(i=0; fossil_isdigit(zTag[i]); i++){}
265 if( zTag[i]==0 ){
266 rid = db_int(0,
267 "SELECT event.objid"
268 " FROM event"
269 " WHERE event.objid=%s"
270 " AND event.type GLOB '%q'", zTag, zType);
 
 
 
 
271 }
272 return rid;
273 }
274
275
276
--- src/name.c
+++ src/name.c
@@ -261,15 +261,19 @@
261 if( rid>0 ) return rid;
262
263 /* Undocumented: numeric tags get translated directly into the RID */
264 for(i=0; fossil_isdigit(zTag[i]); i++){}
265 if( zTag[i]==0 ){
266 if( strcmp(zType,"*")==0 ){
267 rid = atoi(zTag);
268 }else{
269 rid = db_int(0,
270 "SELECT event.objid"
271 " FROM event"
272 " WHERE event.objid=%s"
273 " AND event.type GLOB '%q'", zTag, zType);
274 }
275 }
276 return rid;
277 }
278
279
280
+21 -14
--- src/rebuild.c
+++ src/rebuild.c
@@ -925,27 +925,20 @@
925925
**
926926
** Options:
927927
** -R|--repository REPOSITORY deconstruct given REPOSITORY
928928
** -L|--prefixlength N set the length of the names of the DESTINATION
929929
** subdirectories to N
930
+** --private Include private artifacts.
930931
**
931932
** See also: rebuild, reconstruct
932933
*/
933934
void deconstruct_cmd(void){
934935
const char *zDestDir;
935936
const char *zPrefixOpt;
936937
Stmt s;
937
-
938
- /* check number of arguments */
939
- if( (g.argc != 3) && (g.argc != 5) && (g.argc != 7)){
940
- usage ("?-R|--repository REPOSITORY? ?-L|--prefixlength N? DESTINATION");
941
- }
942
- /* get and check argument destination directory */
943
- zDestDir = g.argv[g.argc-1];
944
- if( !*zDestDir || !file_isdir(zDestDir)) {
945
- fossil_panic("DESTINATION(%s) is not a directory!",zDestDir);
946
- }
938
+ int privateFlag;
939
+
947940
/* get and check prefix length argument and build format string */
948941
zPrefixOpt=find_option("prefixlength","L",1);
949942
if( !zPrefixOpt ){
950943
prefixLength = 2;
951944
}else{
@@ -953,10 +946,23 @@
953946
prefixLength = (int)(*zPrefixOpt-'0');
954947
}else{
955948
fossil_fatal("N(%s) is not a a valid prefix length!",zPrefixOpt);
956949
}
957950
}
951
+ /* open repository and open query for all artifacts */
952
+ db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
953
+ privateFlag = find_option("private",0,0)!=0;
954
+ verify_all_options();
955
+ /* check number of arguments */
956
+ if( g.argc!=3 ){
957
+ usage ("?OPTIONS? DESTINATION");
958
+ }
959
+ /* get and check argument destination directory */
960
+ zDestDir = g.argv[g.argc-1];
961
+ if( !*zDestDir || !file_isdir(zDestDir)) {
962
+ fossil_fatal("DESTINATION(%s) is not a directory!",zDestDir);
963
+ }
958964
#ifndef _WIN32
959965
if( file_access(zDestDir, W_OK) ){
960966
fossil_fatal("DESTINATION(%s) is not writeable!",zDestDir);
961967
}
962968
#else
@@ -967,12 +973,11 @@
967973
if( prefixLength ){
968974
zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength);
969975
}else{
970976
zFNameFormat = mprintf("%s/%%s",zDestDir);
971977
}
972
- /* open repository and open query for all artifacts */
973
- db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
978
+
974979
bag_init(&bagDone);
975980
ttyOutput = 1;
976981
processCnt = 0;
977982
if (!g.fQuiet) {
978983
fossil_print("0 (0%%)...\r");
@@ -980,11 +985,12 @@
980985
}
981986
totalSize = db_int(0, "SELECT count(*) FROM blob");
982987
db_prepare(&s,
983988
"SELECT rid, size FROM blob /*scan*/"
984989
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
985
- " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
990
+ " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid) %s",
991
+ privateFlag==0 ? "AND rid NOT IN private" : ""
986992
);
987993
while( db_step(&s)==SQLITE_ROW ){
988994
int rid = db_column_int(&s, 0);
989995
int size = db_column_int(&s, 1);
990996
if( size>=0 ){
@@ -994,11 +1000,12 @@
9941000
}
9951001
}
9961002
db_finalize(&s);
9971003
db_prepare(&s,
9981004
"SELECT rid, size FROM blob"
999
- " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
1005
+ " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
1006
+ privateFlag==0 ? "AND rid NOT IN private" : ""
10001007
);
10011008
while( db_step(&s)==SQLITE_ROW ){
10021009
int rid = db_column_int(&s, 0);
10031010
int size = db_column_int(&s, 1);
10041011
if( size>=0 ){
10051012
--- src/rebuild.c
+++ src/rebuild.c
@@ -925,27 +925,20 @@
925 **
926 ** Options:
927 ** -R|--repository REPOSITORY deconstruct given REPOSITORY
928 ** -L|--prefixlength N set the length of the names of the DESTINATION
929 ** subdirectories to N
 
930 **
931 ** See also: rebuild, reconstruct
932 */
933 void deconstruct_cmd(void){
934 const char *zDestDir;
935 const char *zPrefixOpt;
936 Stmt s;
937
938 /* check number of arguments */
939 if( (g.argc != 3) && (g.argc != 5) && (g.argc != 7)){
940 usage ("?-R|--repository REPOSITORY? ?-L|--prefixlength N? DESTINATION");
941 }
942 /* get and check argument destination directory */
943 zDestDir = g.argv[g.argc-1];
944 if( !*zDestDir || !file_isdir(zDestDir)) {
945 fossil_panic("DESTINATION(%s) is not a directory!",zDestDir);
946 }
947 /* get and check prefix length argument and build format string */
948 zPrefixOpt=find_option("prefixlength","L",1);
949 if( !zPrefixOpt ){
950 prefixLength = 2;
951 }else{
@@ -953,10 +946,23 @@
953 prefixLength = (int)(*zPrefixOpt-'0');
954 }else{
955 fossil_fatal("N(%s) is not a a valid prefix length!",zPrefixOpt);
956 }
957 }
 
 
 
 
 
 
 
 
 
 
 
 
 
958 #ifndef _WIN32
959 if( file_access(zDestDir, W_OK) ){
960 fossil_fatal("DESTINATION(%s) is not writeable!",zDestDir);
961 }
962 #else
@@ -967,12 +973,11 @@
967 if( prefixLength ){
968 zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength);
969 }else{
970 zFNameFormat = mprintf("%s/%%s",zDestDir);
971 }
972 /* open repository and open query for all artifacts */
973 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
974 bag_init(&bagDone);
975 ttyOutput = 1;
976 processCnt = 0;
977 if (!g.fQuiet) {
978 fossil_print("0 (0%%)...\r");
@@ -980,11 +985,12 @@
980 }
981 totalSize = db_int(0, "SELECT count(*) FROM blob");
982 db_prepare(&s,
983 "SELECT rid, size FROM blob /*scan*/"
984 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
985 " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
 
986 );
987 while( db_step(&s)==SQLITE_ROW ){
988 int rid = db_column_int(&s, 0);
989 int size = db_column_int(&s, 1);
990 if( size>=0 ){
@@ -994,11 +1000,12 @@
994 }
995 }
996 db_finalize(&s);
997 db_prepare(&s,
998 "SELECT rid, size FROM blob"
999 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
 
1000 );
1001 while( db_step(&s)==SQLITE_ROW ){
1002 int rid = db_column_int(&s, 0);
1003 int size = db_column_int(&s, 1);
1004 if( size>=0 ){
1005
--- src/rebuild.c
+++ src/rebuild.c
@@ -925,27 +925,20 @@
925 **
926 ** Options:
927 ** -R|--repository REPOSITORY deconstruct given REPOSITORY
928 ** -L|--prefixlength N set the length of the names of the DESTINATION
929 ** subdirectories to N
930 ** --private Include private artifacts.
931 **
932 ** See also: rebuild, reconstruct
933 */
934 void deconstruct_cmd(void){
935 const char *zDestDir;
936 const char *zPrefixOpt;
937 Stmt s;
938 int privateFlag;
939
 
 
 
 
 
 
 
 
940 /* get and check prefix length argument and build format string */
941 zPrefixOpt=find_option("prefixlength","L",1);
942 if( !zPrefixOpt ){
943 prefixLength = 2;
944 }else{
@@ -953,10 +946,23 @@
946 prefixLength = (int)(*zPrefixOpt-'0');
947 }else{
948 fossil_fatal("N(%s) is not a a valid prefix length!",zPrefixOpt);
949 }
950 }
951 /* open repository and open query for all artifacts */
952 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
953 privateFlag = find_option("private",0,0)!=0;
954 verify_all_options();
955 /* check number of arguments */
956 if( g.argc!=3 ){
957 usage ("?OPTIONS? DESTINATION");
958 }
959 /* get and check argument destination directory */
960 zDestDir = g.argv[g.argc-1];
961 if( !*zDestDir || !file_isdir(zDestDir)) {
962 fossil_fatal("DESTINATION(%s) is not a directory!",zDestDir);
963 }
964 #ifndef _WIN32
965 if( file_access(zDestDir, W_OK) ){
966 fossil_fatal("DESTINATION(%s) is not writeable!",zDestDir);
967 }
968 #else
@@ -967,12 +973,11 @@
973 if( prefixLength ){
974 zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength);
975 }else{
976 zFNameFormat = mprintf("%s/%%s",zDestDir);
977 }
978
 
979 bag_init(&bagDone);
980 ttyOutput = 1;
981 processCnt = 0;
982 if (!g.fQuiet) {
983 fossil_print("0 (0%%)...\r");
@@ -980,11 +985,12 @@
985 }
986 totalSize = db_int(0, "SELECT count(*) FROM blob");
987 db_prepare(&s,
988 "SELECT rid, size FROM blob /*scan*/"
989 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
990 " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid) %s",
991 privateFlag==0 ? "AND rid NOT IN private" : ""
992 );
993 while( db_step(&s)==SQLITE_ROW ){
994 int rid = db_column_int(&s, 0);
995 int size = db_column_int(&s, 1);
996 if( size>=0 ){
@@ -994,11 +1000,12 @@
1000 }
1001 }
1002 db_finalize(&s);
1003 db_prepare(&s,
1004 "SELECT rid, size FROM blob"
1005 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
1006 privateFlag==0 ? "AND rid NOT IN private" : ""
1007 );
1008 while( db_step(&s)==SQLITE_ROW ){
1009 int rid = db_column_int(&s, 0);
1010 int size = db_column_int(&s, 1);
1011 if( size>=0 ){
1012
+1 -1
--- src/report.c
+++ src/report.c
@@ -170,11 +170,11 @@
170170
case SQLITE_SELECT:
171171
case SQLITE_FUNCTION: {
172172
break;
173173
}
174174
case SQLITE_READ: {
175
- static const char *azAllowed[] = {
175
+ static const char *const azAllowed[] = {
176176
"ticket",
177177
"blob",
178178
"filename",
179179
"mlink",
180180
"plink",
181181
--- src/report.c
+++ src/report.c
@@ -170,11 +170,11 @@
170 case SQLITE_SELECT:
171 case SQLITE_FUNCTION: {
172 break;
173 }
174 case SQLITE_READ: {
175 static const char *azAllowed[] = {
176 "ticket",
177 "blob",
178 "filename",
179 "mlink",
180 "plink",
181
--- src/report.c
+++ src/report.c
@@ -170,11 +170,11 @@
170 case SQLITE_SELECT:
171 case SQLITE_FUNCTION: {
172 break;
173 }
174 case SQLITE_READ: {
175 static const char *const azAllowed[] = {
176 "ticket",
177 "blob",
178 "filename",
179 "mlink",
180 "plink",
181
+1 -1
--- src/stash.c
+++ src/stash.c
@@ -172,11 +172,11 @@
172172
zComment = blob_str(&comment);
173173
}
174174
stashid = db_lget_int("stash-next", 1);
175175
db_lset_int("stash-next", stashid+1);
176176
vid = db_lget_int("checkout", 0);
177
- vfile_check_signature(vid, 0, 0);
177
+ vfile_check_signature(vid, 0);
178178
db_multi_exec(
179179
"INSERT INTO stash(stashid,vid,comment,ctime)"
180180
"VALUES(%d,%d,%Q,julianday('now'))",
181181
stashid, vid, zComment
182182
);
183183
--- src/stash.c
+++ src/stash.c
@@ -172,11 +172,11 @@
172 zComment = blob_str(&comment);
173 }
174 stashid = db_lget_int("stash-next", 1);
175 db_lset_int("stash-next", stashid+1);
176 vid = db_lget_int("checkout", 0);
177 vfile_check_signature(vid, 0, 0);
178 db_multi_exec(
179 "INSERT INTO stash(stashid,vid,comment,ctime)"
180 "VALUES(%d,%d,%Q,julianday('now'))",
181 stashid, vid, zComment
182 );
183
--- src/stash.c
+++ src/stash.c
@@ -172,11 +172,11 @@
172 zComment = blob_str(&comment);
173 }
174 stashid = db_lget_int("stash-next", 1);
175 db_lset_int("stash-next", stashid+1);
176 vid = db_lget_int("checkout", 0);
177 vfile_check_signature(vid, 0);
178 db_multi_exec(
179 "INSERT INTO stash(stashid,vid,comment,ctime)"
180 "VALUES(%d,%d,%Q,julianday('now'))",
181 stashid, vid, zComment
182 );
183
+2 -2
--- src/timeline.c
+++ src/timeline.c
@@ -1022,11 +1022,11 @@
10221022
if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
10231023
if( useDividers ) timeline_add_dividers(0, d_rid);
10241024
db_multi_exec("DELETE FROM ok");
10251025
}
10261026
if( p_rid ){
1027
- compute_ancestors(p_rid, nEntry+1);
1027
+ compute_ancestors(p_rid, nEntry+1, 0);
10281028
np = db_int(0, "SELECT count(*)-1 FROM ok");
10291029
if( np>0 ){
10301030
if( nd>0 ) blob_appendf(&desc, " and ");
10311031
blob_appendf(&desc, "%d ancestors", np);
10321032
db_multi_exec("%s", blob_str(&sql));
@@ -1537,11 +1537,11 @@
15371537
if( mode==3 || mode==4 ){
15381538
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
15391539
if( mode==3 ){
15401540
compute_descendants(objid, n);
15411541
}else{
1542
- compute_ancestors(objid, n);
1542
+ compute_ancestors(objid, n, 0);
15431543
}
15441544
blob_appendf(&sql, " AND blob.rid IN ok");
15451545
}
15461546
if( zType && (zType[0]!='a') ){
15471547
blob_appendf(&sql, " AND event.type=%Q ", zType);
15481548
--- src/timeline.c
+++ src/timeline.c
@@ -1022,11 +1022,11 @@
1022 if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
1023 if( useDividers ) timeline_add_dividers(0, d_rid);
1024 db_multi_exec("DELETE FROM ok");
1025 }
1026 if( p_rid ){
1027 compute_ancestors(p_rid, nEntry+1);
1028 np = db_int(0, "SELECT count(*)-1 FROM ok");
1029 if( np>0 ){
1030 if( nd>0 ) blob_appendf(&desc, " and ");
1031 blob_appendf(&desc, "%d ancestors", np);
1032 db_multi_exec("%s", blob_str(&sql));
@@ -1537,11 +1537,11 @@
1537 if( mode==3 || mode==4 ){
1538 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
1539 if( mode==3 ){
1540 compute_descendants(objid, n);
1541 }else{
1542 compute_ancestors(objid, n);
1543 }
1544 blob_appendf(&sql, " AND blob.rid IN ok");
1545 }
1546 if( zType && (zType[0]!='a') ){
1547 blob_appendf(&sql, " AND event.type=%Q ", zType);
1548
--- src/timeline.c
+++ src/timeline.c
@@ -1022,11 +1022,11 @@
1022 if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
1023 if( useDividers ) timeline_add_dividers(0, d_rid);
1024 db_multi_exec("DELETE FROM ok");
1025 }
1026 if( p_rid ){
1027 compute_ancestors(p_rid, nEntry+1, 0);
1028 np = db_int(0, "SELECT count(*)-1 FROM ok");
1029 if( np>0 ){
1030 if( nd>0 ) blob_appendf(&desc, " and ");
1031 blob_appendf(&desc, "%d ancestors", np);
1032 db_multi_exec("%s", blob_str(&sql));
@@ -1537,11 +1537,11 @@
1537 if( mode==3 || mode==4 ){
1538 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
1539 if( mode==3 ){
1540 compute_descendants(objid, n);
1541 }else{
1542 compute_ancestors(objid, n, 0);
1543 }
1544 blob_appendf(&sql, " AND blob.rid IN ok");
1545 }
1546 if( zType && (zType[0]!='a') ){
1547 blob_appendf(&sql, " AND event.type=%Q ", zType);
1548
+2 -2
--- src/timeline.c
+++ src/timeline.c
@@ -1022,11 +1022,11 @@
10221022
if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
10231023
if( useDividers ) timeline_add_dividers(0, d_rid);
10241024
db_multi_exec("DELETE FROM ok");
10251025
}
10261026
if( p_rid ){
1027
- compute_ancestors(p_rid, nEntry+1);
1027
+ compute_ancestors(p_rid, nEntry+1, 0);
10281028
np = db_int(0, "SELECT count(*)-1 FROM ok");
10291029
if( np>0 ){
10301030
if( nd>0 ) blob_appendf(&desc, " and ");
10311031
blob_appendf(&desc, "%d ancestors", np);
10321032
db_multi_exec("%s", blob_str(&sql));
@@ -1537,11 +1537,11 @@
15371537
if( mode==3 || mode==4 ){
15381538
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
15391539
if( mode==3 ){
15401540
compute_descendants(objid, n);
15411541
}else{
1542
- compute_ancestors(objid, n);
1542
+ compute_ancestors(objid, n, 0);
15431543
}
15441544
blob_appendf(&sql, " AND blob.rid IN ok");
15451545
}
15461546
if( zType && (zType[0]!='a') ){
15471547
blob_appendf(&sql, " AND event.type=%Q ", zType);
15481548
--- src/timeline.c
+++ src/timeline.c
@@ -1022,11 +1022,11 @@
1022 if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
1023 if( useDividers ) timeline_add_dividers(0, d_rid);
1024 db_multi_exec("DELETE FROM ok");
1025 }
1026 if( p_rid ){
1027 compute_ancestors(p_rid, nEntry+1);
1028 np = db_int(0, "SELECT count(*)-1 FROM ok");
1029 if( np>0 ){
1030 if( nd>0 ) blob_appendf(&desc, " and ");
1031 blob_appendf(&desc, "%d ancestors", np);
1032 db_multi_exec("%s", blob_str(&sql));
@@ -1537,11 +1537,11 @@
1537 if( mode==3 || mode==4 ){
1538 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
1539 if( mode==3 ){
1540 compute_descendants(objid, n);
1541 }else{
1542 compute_ancestors(objid, n);
1543 }
1544 blob_appendf(&sql, " AND blob.rid IN ok");
1545 }
1546 if( zType && (zType[0]!='a') ){
1547 blob_appendf(&sql, " AND event.type=%Q ", zType);
1548
--- src/timeline.c
+++ src/timeline.c
@@ -1022,11 +1022,11 @@
1022 if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
1023 if( useDividers ) timeline_add_dividers(0, d_rid);
1024 db_multi_exec("DELETE FROM ok");
1025 }
1026 if( p_rid ){
1027 compute_ancestors(p_rid, nEntry+1, 0);
1028 np = db_int(0, "SELECT count(*)-1 FROM ok");
1029 if( np>0 ){
1030 if( nd>0 ) blob_appendf(&desc, " and ");
1031 blob_appendf(&desc, "%d ancestors", np);
1032 db_multi_exec("%s", blob_str(&sql));
@@ -1537,11 +1537,11 @@
1537 if( mode==3 || mode==4 ){
1538 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
1539 if( mode==3 ){
1540 compute_descendants(objid, n);
1541 }else{
1542 compute_ancestors(objid, n, 0);
1543 }
1544 blob_appendf(&sql, " AND blob.rid IN ok");
1545 }
1546 if( zType && (zType[0]!='a') ){
1547 blob_appendf(&sql, " AND event.type=%Q ", zType);
1548
+6
--- src/tkt.c
+++ src/tkt.c
@@ -433,10 +433,11 @@
433433
){
434434
char *zDate;
435435
const char *zUuid;
436436
int i;
437437
int rid;
438
+ int nJ = 0;
438439
Blob tktchng, cksum;
439440
440441
login_verify_csrf_secret();
441442
zUuid = (const char *)pUuid;
442443
blob_zero(&tktchng);
@@ -461,10 +462,11 @@
461462
zValue = db_conceal(zValue, nValue);
462463
blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue);
463464
}else{
464465
blob_appendf(&tktchng, "J %s %#F\n", azField[i], nValue, zValue);
465466
}
467
+ nJ++;
466468
}
467469
}
468470
}
469471
if( *(char**)pUuid ){
470472
zUuid = db_text(0,
@@ -476,10 +478,14 @@
476478
*(const char**)pUuid = zUuid;
477479
blob_appendf(&tktchng, "K %s\n", zUuid);
478480
blob_appendf(&tktchng, "U %F\n", g.zLogin ? g.zLogin : "");
479481
md5sum_blob(&tktchng, &cksum);
480482
blob_appendf(&tktchng, "Z %b\n", &cksum);
483
+ if( nJ==0 ){
484
+ blob_reset(&tktchng);
485
+ return TH_OK;
486
+ }
481487
if( g.zPath[0]=='d' ){
482488
/* If called from /debug_tktnew or /debug_tktedit... */
483489
@ <font color="blue">
484490
@ <p>Ticket artifact that would have been submitted:</p>
485491
@ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
486492
--- src/tkt.c
+++ src/tkt.c
@@ -433,10 +433,11 @@
433 ){
434 char *zDate;
435 const char *zUuid;
436 int i;
437 int rid;
 
438 Blob tktchng, cksum;
439
440 login_verify_csrf_secret();
441 zUuid = (const char *)pUuid;
442 blob_zero(&tktchng);
@@ -461,10 +462,11 @@
461 zValue = db_conceal(zValue, nValue);
462 blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue);
463 }else{
464 blob_appendf(&tktchng, "J %s %#F\n", azField[i], nValue, zValue);
465 }
 
466 }
467 }
468 }
469 if( *(char**)pUuid ){
470 zUuid = db_text(0,
@@ -476,10 +478,14 @@
476 *(const char**)pUuid = zUuid;
477 blob_appendf(&tktchng, "K %s\n", zUuid);
478 blob_appendf(&tktchng, "U %F\n", g.zLogin ? g.zLogin : "");
479 md5sum_blob(&tktchng, &cksum);
480 blob_appendf(&tktchng, "Z %b\n", &cksum);
 
 
 
 
481 if( g.zPath[0]=='d' ){
482 /* If called from /debug_tktnew or /debug_tktedit... */
483 @ <font color="blue">
484 @ <p>Ticket artifact that would have been submitted:</p>
485 @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
486
--- src/tkt.c
+++ src/tkt.c
@@ -433,10 +433,11 @@
433 ){
434 char *zDate;
435 const char *zUuid;
436 int i;
437 int rid;
438 int nJ = 0;
439 Blob tktchng, cksum;
440
441 login_verify_csrf_secret();
442 zUuid = (const char *)pUuid;
443 blob_zero(&tktchng);
@@ -461,10 +462,11 @@
462 zValue = db_conceal(zValue, nValue);
463 blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue);
464 }else{
465 blob_appendf(&tktchng, "J %s %#F\n", azField[i], nValue, zValue);
466 }
467 nJ++;
468 }
469 }
470 }
471 if( *(char**)pUuid ){
472 zUuid = db_text(0,
@@ -476,10 +478,14 @@
478 *(const char**)pUuid = zUuid;
479 blob_appendf(&tktchng, "K %s\n", zUuid);
480 blob_appendf(&tktchng, "U %F\n", g.zLogin ? g.zLogin : "");
481 md5sum_blob(&tktchng, &cksum);
482 blob_appendf(&tktchng, "Z %b\n", &cksum);
483 if( nJ==0 ){
484 blob_reset(&tktchng);
485 return TH_OK;
486 }
487 if( g.zPath[0]=='d' ){
488 /* If called from /debug_tktnew or /debug_tktedit... */
489 @ <font color="blue">
490 @ <p>Ticket artifact that would have been submitted:</p>
491 @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
492
+5 -2
--- src/update.c
+++ src/update.c
@@ -100,10 +100,11 @@
100100
Stmt q;
101101
int latestFlag; /* --latest. Pick the latest version if true */
102102
int nochangeFlag; /* -n or --nochange. Do a dry run */
103103
int verboseFlag; /* -v or --verbose. Output extra information */
104104
int debugFlag; /* --debug option */
105
+ int setmtimeFlag; /* --setmtime. Set mtimes on files */
105106
int nChng; /* Number of file renames */
106107
int *aChng; /* Array of file renames */
107108
int i; /* Loop counter */
108109
int nConflict = 0; /* Number of merge conflicts */
109110
int nOverwrite = 0; /* Number of unmanaged files overwritten */
@@ -116,10 +117,11 @@
116117
}
117118
latestFlag = find_option("latest",0, 0)!=0;
118119
nochangeFlag = find_option("nochange","n",0)!=0;
119120
verboseFlag = find_option("verbose","v",0)!=0;
120121
debugFlag = find_option("debug",0,0)!=0;
122
+ setmtimeFlag = find_option("setmtime",0,0)!=0;
121123
db_must_be_within_tree();
122124
vid = db_lget_int("checkout", 0);
123125
if( vid==0 ){
124126
fossil_fatal("cannot find current version");
125127
}
@@ -194,11 +196,11 @@
194196
if( tid==0 ){
195197
fossil_panic("Internal Error: unable to find a version to update to.");
196198
}
197199
198200
db_begin_transaction();
199
- vfile_check_signature(vid, 1, 0);
201
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
200202
if( !nochangeFlag && !internalUpdate ) undo_begin();
201203
load_vfile_from_rid(tid);
202204
203205
/*
204206
** The record.fn field is used to match files against each other. The
@@ -529,10 +531,11 @@
529531
/* A subset of files have been checked out. Keep the current
530532
** checkout unchanged. */
531533
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
532534
}
533535
if( !internalUpdate ) undo_finish();
536
+ if( setmtimeFlag ) vfile_check_signature(vid, CKSIG_SETMTIME);
534537
db_end_transaction(0);
535538
}
536539
}
537540
538541
/*
@@ -696,11 +699,11 @@
696699
blob_reset(&fname);
697700
}
698701
}else{
699702
int vid;
700703
vid = db_lget_int("checkout", 0);
701
- vfile_check_signature(vid, 0, 0);
704
+ vfile_check_signature(vid, 0);
702705
db_multi_exec(
703706
"DELETE FROM vmerge;"
704707
"INSERT INTO torevert "
705708
"SELECT pathname"
706709
" FROM vfile "
707710
--- src/update.c
+++ src/update.c
@@ -100,10 +100,11 @@
100 Stmt q;
101 int latestFlag; /* --latest. Pick the latest version if true */
102 int nochangeFlag; /* -n or --nochange. Do a dry run */
103 int verboseFlag; /* -v or --verbose. Output extra information */
104 int debugFlag; /* --debug option */
 
105 int nChng; /* Number of file renames */
106 int *aChng; /* Array of file renames */
107 int i; /* Loop counter */
108 int nConflict = 0; /* Number of merge conflicts */
109 int nOverwrite = 0; /* Number of unmanaged files overwritten */
@@ -116,10 +117,11 @@
116 }
117 latestFlag = find_option("latest",0, 0)!=0;
118 nochangeFlag = find_option("nochange","n",0)!=0;
119 verboseFlag = find_option("verbose","v",0)!=0;
120 debugFlag = find_option("debug",0,0)!=0;
 
121 db_must_be_within_tree();
122 vid = db_lget_int("checkout", 0);
123 if( vid==0 ){
124 fossil_fatal("cannot find current version");
125 }
@@ -194,11 +196,11 @@
194 if( tid==0 ){
195 fossil_panic("Internal Error: unable to find a version to update to.");
196 }
197
198 db_begin_transaction();
199 vfile_check_signature(vid, 1, 0);
200 if( !nochangeFlag && !internalUpdate ) undo_begin();
201 load_vfile_from_rid(tid);
202
203 /*
204 ** The record.fn field is used to match files against each other. The
@@ -529,10 +531,11 @@
529 /* A subset of files have been checked out. Keep the current
530 ** checkout unchanged. */
531 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
532 }
533 if( !internalUpdate ) undo_finish();
 
534 db_end_transaction(0);
535 }
536 }
537
538 /*
@@ -696,11 +699,11 @@
696 blob_reset(&fname);
697 }
698 }else{
699 int vid;
700 vid = db_lget_int("checkout", 0);
701 vfile_check_signature(vid, 0, 0);
702 db_multi_exec(
703 "DELETE FROM vmerge;"
704 "INSERT INTO torevert "
705 "SELECT pathname"
706 " FROM vfile "
707
--- src/update.c
+++ src/update.c
@@ -100,10 +100,11 @@
100 Stmt q;
101 int latestFlag; /* --latest. Pick the latest version if true */
102 int nochangeFlag; /* -n or --nochange. Do a dry run */
103 int verboseFlag; /* -v or --verbose. Output extra information */
104 int debugFlag; /* --debug option */
105 int setmtimeFlag; /* --setmtime. Set mtimes on files */
106 int nChng; /* Number of file renames */
107 int *aChng; /* Array of file renames */
108 int i; /* Loop counter */
109 int nConflict = 0; /* Number of merge conflicts */
110 int nOverwrite = 0; /* Number of unmanaged files overwritten */
@@ -116,10 +117,11 @@
117 }
118 latestFlag = find_option("latest",0, 0)!=0;
119 nochangeFlag = find_option("nochange","n",0)!=0;
120 verboseFlag = find_option("verbose","v",0)!=0;
121 debugFlag = find_option("debug",0,0)!=0;
122 setmtimeFlag = find_option("setmtime",0,0)!=0;
123 db_must_be_within_tree();
124 vid = db_lget_int("checkout", 0);
125 if( vid==0 ){
126 fossil_fatal("cannot find current version");
127 }
@@ -194,11 +196,11 @@
196 if( tid==0 ){
197 fossil_panic("Internal Error: unable to find a version to update to.");
198 }
199
200 db_begin_transaction();
201 vfile_check_signature(vid, CKSIG_ENOTFILE);
202 if( !nochangeFlag && !internalUpdate ) undo_begin();
203 load_vfile_from_rid(tid);
204
205 /*
206 ** The record.fn field is used to match files against each other. The
@@ -529,10 +531,11 @@
531 /* A subset of files have been checked out. Keep the current
532 ** checkout unchanged. */
533 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
534 }
535 if( !internalUpdate ) undo_finish();
536 if( setmtimeFlag ) vfile_check_signature(vid, CKSIG_SETMTIME);
537 db_end_transaction(0);
538 }
539 }
540
541 /*
@@ -696,11 +699,11 @@
699 blob_reset(&fname);
700 }
701 }else{
702 int vid;
703 vid = db_lget_int("checkout", 0);
704 vfile_check_signature(vid, 0);
705 db_multi_exec(
706 "DELETE FROM vmerge;"
707 "INSERT INTO torevert "
708 "SELECT pathname"
709 " FROM vfile "
710
+76 -15
--- src/vfile.c
+++ src/vfile.c
@@ -118,19 +118,30 @@
118118
db_finalize(&ins);
119119
manifest_destroy(p);
120120
db_end_transaction(0);
121121
}
122122
123
+#if INTERFACE
124
+/*
125
+** The cksigFlags parameter to vfile_check_signature() is an OR-ed
126
+** combination of the following bits:
127
+*/
128
+#define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */
129
+#define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */
130
+#define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */
131
+
132
+#endif /* INTERFACE */
133
+
123134
/*
124
-** Look at every VFILE entry with the given vid and set update
125
-** VFILE.CHNGED field on every file according to whether or not
126
-** the file has changes. 0 means no change. 1 means edited. 2 means
135
+** Look at every VFILE entry with the given vid and update
136
+** VFILE.CHNGED field according to whether or not
137
+** the file has changed. 0 means no change. 1 means edited. 2 means
127138
** the file has changed due to a merge. 3 means the file was added
128139
** by a merge.
129140
**
130
-** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was
131
-** either removed from managemented via "fossil rm" or added via
141
+** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
142
+** removed from configuration management via "fossil rm" or added via
132143
** "fossil add", respectively, and in both cases we always know that
133144
** the file has changed without having the check the size, mtime,
134145
** or on-disk content.
135146
**
136147
** If the size of the file has changed, then we always know that the file
@@ -144,15 +155,16 @@
144155
**
145156
** If the mtime is used, it is used only to determine if files are the same.
146157
** If the mtime of a file has changed, we still examine the on-disk content
147158
** to see whether or not the edit was a null-edit.
148159
*/
149
-void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){
160
+void vfile_check_signature(int vid, unsigned int cksigFlags){
150161
int nErr = 0;
151162
Stmt q;
152163
Blob fileCksum, origCksum;
153
- int useMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);
164
+ int useMtime = (cksigFlags & CKSIG_SHA1)==0
165
+ && db_get_boolean("mtime-changes", 1);
154166
155167
db_begin_transaction();
156168
db_prepare(&q, "SELECT id, %Q || pathname,"
157169
" vfile.mrid, deleted, chnged, uuid, size, mtime"
158170
" FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -178,11 +190,11 @@
178190
currentMtime = file_wd_mtime(0);
179191
if( chnged==0 && (isDeleted || rid==0) ){
180192
/* "fossil rm" or "fossil add" always change the file */
181193
chnged = 1;
182194
}else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
183
- if( notFileIsFatal ){
195
+ if( cksigFlags & CKSIG_ENOTFILE ){
184196
fossil_warning("not an ordinary file: %s", zName);
185197
nErr++;
186198
}
187199
chnged = 1;
188200
}
@@ -217,10 +229,19 @@
217229
if( blob_compare(&fileCksum, &origCksum) ){
218230
chnged = 1;
219231
}
220232
blob_reset(&origCksum);
221233
blob_reset(&fileCksum);
234
+ }
235
+ if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2) ){
236
+ i64 desiredMtime;
237
+ if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
238
+ if( currentMtime!=desiredMtime ){
239
+ file_set_mtime(zName, desiredMtime);
240
+ currentMtime = file_wd_mtime(zName);
241
+ }
242
+ }
222243
}
223244
if( currentMtime!=oldMtime || chnged!=oldChnged ){
224245
db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
225246
currentMtime, chnged, id);
226247
}
@@ -360,10 +381,48 @@
360381
fossil_free(zFile);
361382
}
362383
return fileFound;
363384
}
364385
386
+/*
387
+** Return TRUE if zFile is a temporary file. Return FALSE if not.
388
+*/
389
+static int is_temporary_file(const char *zName){
390
+ static const char *const azTemp[] = {
391
+ "baseline",
392
+ "merge",
393
+ "original",
394
+ "output",
395
+ };
396
+ int i, j, n;
397
+
398
+ if( strglob("ci-comment-????????????.txt", zName) ) return 1;
399
+ for(; zName[0]!=0; zName++){
400
+ if( zName[0]=='/' && strglob("/ci-comment-????????????.txt", zName) ){
401
+ return 1;
402
+ }
403
+ if( zName[0]!='-' ) continue;
404
+ for(i=0; i<sizeof(azTemp)/sizeof(azTemp[0]); i++){
405
+ n = (int)strlen(azTemp[i]);
406
+ if( memcmp(azTemp[i], zName+1, n) ) continue;
407
+ if( zName[n+1]==0 ) return 1;
408
+ if( zName[n+1]=='-' ){
409
+ for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){}
410
+ if( zName[j]==0 ) return 1;
411
+ }
412
+ }
413
+ }
414
+ return 0;
415
+}
416
+
417
+#if INTERFACE
418
+/*
419
+** Values for the scanFlags parameter to vfile_scan().
420
+*/
421
+#define SCAN_ALL 0x001 /* Includes files that begin with "." */
422
+#define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */
423
+#endif /* INTERFACE */
365424
366425
/*
367426
** Load into table SFILE the name of every ordinary file in
368427
** the directory pPath. Omit the first nPrefix characters of
369428
** of pPath when inserting into the SFILE table.
@@ -375,11 +434,11 @@
375434
**
376435
** Any files or directories that match the glob pattern pIgnore are
377436
** excluded from the scan. Name matching occurs after the first
378437
** nPrefix characters are elided from the filename.
379438
*/
380
-void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){
439
+void vfile_scan(Blob *pPath, int nPrefix, unsigned scanFlags, Glob *pIgnore){
381440
DIR *d;
382441
int origSize;
383442
const char *zDir;
384443
struct dirent *pEntry;
385444
int skipAll = 0;
@@ -409,29 +468,31 @@
409468
if( d ){
410469
while( (pEntry=readdir(d))!=0 ){
411470
char *zPath;
412471
char *zUtf8;
413472
if( pEntry->d_name[0]=='.' ){
414
- if( !allFlag ) continue;
473
+ if( (scanFlags & SCAN_ALL)==0 ) continue;
415474
if( pEntry->d_name[1]==0 ) continue;
416475
if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
417476
}
418477
zUtf8 = fossil_unicode_to_utf8(pEntry->d_name);
419478
blob_appendf(pPath, "/%s", zUtf8);
420
- fossil_mbcs_free(zUtf8);
421479
zPath = blob_str(pPath);
422480
if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
423481
/* do nothing */
424482
}else if( file_wd_isdir(zPath)==1 ){
425483
if( !vfile_top_of_checkout(zPath) ){
426
- vfile_scan(pPath, nPrefix, allFlag, pIgnore);
484
+ vfile_scan(pPath, nPrefix, scanFlags, pIgnore);
427485
}
428486
}else if( file_wd_isfile_or_link(zPath) ){
429
- db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
430
- db_step(&ins);
431
- db_reset(&ins);
487
+ if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){
488
+ db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
489
+ db_step(&ins);
490
+ db_reset(&ins);
491
+ }
432492
}
493
+ fossil_mbcs_free(zUtf8);
433494
blob_resize(pPath, origSize);
434495
}
435496
closedir(d);
436497
}
437498
fossil_mbcs_free(zMbcs);
438499
--- src/vfile.c
+++ src/vfile.c
@@ -118,19 +118,30 @@
118 db_finalize(&ins);
119 manifest_destroy(p);
120 db_end_transaction(0);
121 }
122
 
 
 
 
 
 
 
 
 
 
 
123 /*
124 ** Look at every VFILE entry with the given vid and set update
125 ** VFILE.CHNGED field on every file according to whether or not
126 ** the file has changes. 0 means no change. 1 means edited. 2 means
127 ** the file has changed due to a merge. 3 means the file was added
128 ** by a merge.
129 **
130 ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was
131 ** either removed from managemented via "fossil rm" or added via
132 ** "fossil add", respectively, and in both cases we always know that
133 ** the file has changed without having the check the size, mtime,
134 ** or on-disk content.
135 **
136 ** If the size of the file has changed, then we always know that the file
@@ -144,15 +155,16 @@
144 **
145 ** If the mtime is used, it is used only to determine if files are the same.
146 ** If the mtime of a file has changed, we still examine the on-disk content
147 ** to see whether or not the edit was a null-edit.
148 */
149 void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){
150 int nErr = 0;
151 Stmt q;
152 Blob fileCksum, origCksum;
153 int useMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);
 
154
155 db_begin_transaction();
156 db_prepare(&q, "SELECT id, %Q || pathname,"
157 " vfile.mrid, deleted, chnged, uuid, size, mtime"
158 " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -178,11 +190,11 @@
178 currentMtime = file_wd_mtime(0);
179 if( chnged==0 && (isDeleted || rid==0) ){
180 /* "fossil rm" or "fossil add" always change the file */
181 chnged = 1;
182 }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
183 if( notFileIsFatal ){
184 fossil_warning("not an ordinary file: %s", zName);
185 nErr++;
186 }
187 chnged = 1;
188 }
@@ -217,10 +229,19 @@
217 if( blob_compare(&fileCksum, &origCksum) ){
218 chnged = 1;
219 }
220 blob_reset(&origCksum);
221 blob_reset(&fileCksum);
 
 
 
 
 
 
 
 
 
222 }
223 if( currentMtime!=oldMtime || chnged!=oldChnged ){
224 db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
225 currentMtime, chnged, id);
226 }
@@ -360,10 +381,48 @@
360 fossil_free(zFile);
361 }
362 return fileFound;
363 }
364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
366 /*
367 ** Load into table SFILE the name of every ordinary file in
368 ** the directory pPath. Omit the first nPrefix characters of
369 ** of pPath when inserting into the SFILE table.
@@ -375,11 +434,11 @@
375 **
376 ** Any files or directories that match the glob pattern pIgnore are
377 ** excluded from the scan. Name matching occurs after the first
378 ** nPrefix characters are elided from the filename.
379 */
380 void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){
381 DIR *d;
382 int origSize;
383 const char *zDir;
384 struct dirent *pEntry;
385 int skipAll = 0;
@@ -409,29 +468,31 @@
409 if( d ){
410 while( (pEntry=readdir(d))!=0 ){
411 char *zPath;
412 char *zUtf8;
413 if( pEntry->d_name[0]=='.' ){
414 if( !allFlag ) continue;
415 if( pEntry->d_name[1]==0 ) continue;
416 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
417 }
418 zUtf8 = fossil_unicode_to_utf8(pEntry->d_name);
419 blob_appendf(pPath, "/%s", zUtf8);
420 fossil_mbcs_free(zUtf8);
421 zPath = blob_str(pPath);
422 if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
423 /* do nothing */
424 }else if( file_wd_isdir(zPath)==1 ){
425 if( !vfile_top_of_checkout(zPath) ){
426 vfile_scan(pPath, nPrefix, allFlag, pIgnore);
427 }
428 }else if( file_wd_isfile_or_link(zPath) ){
429 db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
430 db_step(&ins);
431 db_reset(&ins);
 
 
432 }
 
433 blob_resize(pPath, origSize);
434 }
435 closedir(d);
436 }
437 fossil_mbcs_free(zMbcs);
438
--- src/vfile.c
+++ src/vfile.c
@@ -118,19 +118,30 @@
118 db_finalize(&ins);
119 manifest_destroy(p);
120 db_end_transaction(0);
121 }
122
123 #if INTERFACE
124 /*
125 ** The cksigFlags parameter to vfile_check_signature() is an OR-ed
126 ** combination of the following bits:
127 */
128 #define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */
129 #define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */
130 #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */
131
132 #endif /* INTERFACE */
133
134 /*
135 ** Look at every VFILE entry with the given vid and update
136 ** VFILE.CHNGED field according to whether or not
137 ** the file has changed. 0 means no change. 1 means edited. 2 means
138 ** the file has changed due to a merge. 3 means the file was added
139 ** by a merge.
140 **
141 ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
142 ** removed from configuration management via "fossil rm" or added via
143 ** "fossil add", respectively, and in both cases we always know that
144 ** the file has changed without having the check the size, mtime,
145 ** or on-disk content.
146 **
147 ** If the size of the file has changed, then we always know that the file
@@ -144,15 +155,16 @@
155 **
156 ** If the mtime is used, it is used only to determine if files are the same.
157 ** If the mtime of a file has changed, we still examine the on-disk content
158 ** to see whether or not the edit was a null-edit.
159 */
160 void vfile_check_signature(int vid, unsigned int cksigFlags){
161 int nErr = 0;
162 Stmt q;
163 Blob fileCksum, origCksum;
164 int useMtime = (cksigFlags & CKSIG_SHA1)==0
165 && db_get_boolean("mtime-changes", 1);
166
167 db_begin_transaction();
168 db_prepare(&q, "SELECT id, %Q || pathname,"
169 " vfile.mrid, deleted, chnged, uuid, size, mtime"
170 " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -178,11 +190,11 @@
190 currentMtime = file_wd_mtime(0);
191 if( chnged==0 && (isDeleted || rid==0) ){
192 /* "fossil rm" or "fossil add" always change the file */
193 chnged = 1;
194 }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
195 if( cksigFlags & CKSIG_ENOTFILE ){
196 fossil_warning("not an ordinary file: %s", zName);
197 nErr++;
198 }
199 chnged = 1;
200 }
@@ -217,10 +229,19 @@
229 if( blob_compare(&fileCksum, &origCksum) ){
230 chnged = 1;
231 }
232 blob_reset(&origCksum);
233 blob_reset(&fileCksum);
234 }
235 if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2) ){
236 i64 desiredMtime;
237 if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
238 if( currentMtime!=desiredMtime ){
239 file_set_mtime(zName, desiredMtime);
240 currentMtime = file_wd_mtime(zName);
241 }
242 }
243 }
244 if( currentMtime!=oldMtime || chnged!=oldChnged ){
245 db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
246 currentMtime, chnged, id);
247 }
@@ -360,10 +381,48 @@
381 fossil_free(zFile);
382 }
383 return fileFound;
384 }
385
386 /*
387 ** Return TRUE if zFile is a temporary file. Return FALSE if not.
388 */
389 static int is_temporary_file(const char *zName){
390 static const char *const azTemp[] = {
391 "baseline",
392 "merge",
393 "original",
394 "output",
395 };
396 int i, j, n;
397
398 if( strglob("ci-comment-????????????.txt", zName) ) return 1;
399 for(; zName[0]!=0; zName++){
400 if( zName[0]=='/' && strglob("/ci-comment-????????????.txt", zName) ){
401 return 1;
402 }
403 if( zName[0]!='-' ) continue;
404 for(i=0; i<sizeof(azTemp)/sizeof(azTemp[0]); i++){
405 n = (int)strlen(azTemp[i]);
406 if( memcmp(azTemp[i], zName+1, n) ) continue;
407 if( zName[n+1]==0 ) return 1;
408 if( zName[n+1]=='-' ){
409 for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){}
410 if( zName[j]==0 ) return 1;
411 }
412 }
413 }
414 return 0;
415 }
416
417 #if INTERFACE
418 /*
419 ** Values for the scanFlags parameter to vfile_scan().
420 */
421 #define SCAN_ALL 0x001 /* Includes files that begin with "." */
422 #define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */
423 #endif /* INTERFACE */
424
425 /*
426 ** Load into table SFILE the name of every ordinary file in
427 ** the directory pPath. Omit the first nPrefix characters of
428 ** of pPath when inserting into the SFILE table.
@@ -375,11 +434,11 @@
434 **
435 ** Any files or directories that match the glob pattern pIgnore are
436 ** excluded from the scan. Name matching occurs after the first
437 ** nPrefix characters are elided from the filename.
438 */
439 void vfile_scan(Blob *pPath, int nPrefix, unsigned scanFlags, Glob *pIgnore){
440 DIR *d;
441 int origSize;
442 const char *zDir;
443 struct dirent *pEntry;
444 int skipAll = 0;
@@ -409,29 +468,31 @@
468 if( d ){
469 while( (pEntry=readdir(d))!=0 ){
470 char *zPath;
471 char *zUtf8;
472 if( pEntry->d_name[0]=='.' ){
473 if( (scanFlags & SCAN_ALL)==0 ) continue;
474 if( pEntry->d_name[1]==0 ) continue;
475 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
476 }
477 zUtf8 = fossil_unicode_to_utf8(pEntry->d_name);
478 blob_appendf(pPath, "/%s", zUtf8);
 
479 zPath = blob_str(pPath);
480 if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
481 /* do nothing */
482 }else if( file_wd_isdir(zPath)==1 ){
483 if( !vfile_top_of_checkout(zPath) ){
484 vfile_scan(pPath, nPrefix, scanFlags, pIgnore);
485 }
486 }else if( file_wd_isfile_or_link(zPath) ){
487 if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){
488 db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
489 db_step(&ins);
490 db_reset(&ins);
491 }
492 }
493 fossil_mbcs_free(zUtf8);
494 blob_resize(pPath, origSize);
495 }
496 closedir(d);
497 }
498 fossil_mbcs_free(zMbcs);
499
+1 -1
--- src/xfer.c
+++ src/xfer.c
@@ -270,11 +270,11 @@
270270
int rid, /* record id of the file to send */
271271
int isPrivate, /* True if rid is a private artifact */
272272
Blob *pContent, /* The content of the file to send */
273273
Blob *pUuid /* The UUID of the file to send */
274274
){
275
- static const char *azQuery[] = {
275
+ static const char *const azQuery[] = {
276276
"SELECT pid FROM plink x"
277277
" WHERE cid=%d"
278278
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
279279
" AND NOT EXISTS(SELECT 1 FROM plink y"
280280
" WHERE y.pid=x.cid AND y.cid=x.pid)",
281281
--- src/xfer.c
+++ src/xfer.c
@@ -270,11 +270,11 @@
270 int rid, /* record id of the file to send */
271 int isPrivate, /* True if rid is a private artifact */
272 Blob *pContent, /* The content of the file to send */
273 Blob *pUuid /* The UUID of the file to send */
274 ){
275 static const char *azQuery[] = {
276 "SELECT pid FROM plink x"
277 " WHERE cid=%d"
278 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
279 " AND NOT EXISTS(SELECT 1 FROM plink y"
280 " WHERE y.pid=x.cid AND y.cid=x.pid)",
281
--- src/xfer.c
+++ src/xfer.c
@@ -270,11 +270,11 @@
270 int rid, /* record id of the file to send */
271 int isPrivate, /* True if rid is a private artifact */
272 Blob *pContent, /* The content of the file to send */
273 Blob *pUuid /* The UUID of the file to send */
274 ){
275 static const char *const azQuery[] = {
276 "SELECT pid FROM plink x"
277 " WHERE cid=%d"
278 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
279 " AND NOT EXISTS(SELECT 1 FROM plink y"
280 " WHERE y.pid=x.cid AND y.cid=x.pid)",
281

Keyboard Shortcuts

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