Fossil SCM

Cherrypick changes [0c37874941c8972], [9ba8a393fcc569b], and [ae092ec605eed11] in order to backport the --setmtime option of "fossil update" and the --age and -t options of "fossil ls" to version 1.19.

drh 2012-10-11 19:45 trunk
Commit 773c6c5f2c386031f0a313967e397bde001db2be
+42 -9
--- src/checkin.c
+++ src/checkin.c
@@ -153,11 +153,11 @@
153153
int cwdRelative = 0;
154154
db_must_be_within_tree();
155155
cwdRelative = determine_cwd_relative_option();
156156
blob_zero(&report);
157157
vid = db_lget_int("checkout", 0);
158
- vfile_check_signature(vid, 0, useSha1sum);
158
+ vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
159159
status_report(&report, "", 0, cwdRelative);
160160
blob_write_to_file(&report, "-");
161161
}
162162
163163
/*
@@ -191,41 +191,74 @@
191191
if( vid ){
192192
show_common_info(vid, "checkout:", 1, 1);
193193
}
194194
changes_cmd();
195195
}
196
+
197
+/*
198
+** Implementation of the checkin_mtime SQL function
199
+*/
200
+
196201
197202
/*
198203
** COMMAND: ls
199204
**
200
-** Usage: %fossil ls [-l]
205
+** Usage: %fossil ls ?OPTIONS? ?VERSION?
201206
**
202207
** Show the names of all files in the current checkout. The -l provides
203208
** extra information about each file.
209
+**
210
+** Options:
211
+** -l Provide extra information about each file.
212
+** --age Show when each file was committed
213
+**
214
+** See also: changes, extra, status
204215
*/
205216
void ls_cmd(void){
206217
int vid;
207218
Stmt q;
208219
int isBrief;
220
+ int showAge;
221
+ char *zOrderBy = "pathname";
209222
210223
isBrief = find_option("l","l", 0)==0;
224
+ showAge = find_option("age",0,0)!=0;
211225
db_must_be_within_tree();
212226
vid = db_lget_int("checkout", 0);
213
- vfile_check_signature(vid, 0, 0);
214
- db_prepare(&q,
215
- "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
216
- " FROM vfile"
217
- " ORDER BY 1"
218
- );
227
+ if( find_option("t","t",0)!=0 ){
228
+ if( showAge ){
229
+ zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
230
+ }else{
231
+ zOrderBy = "mtime DESC";
232
+ }
233
+ }
234
+ verify_all_options();
235
+ vfile_check_signature(vid, 0);
236
+ if( showAge ){
237
+ db_prepare(&q,
238
+ "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
239
+ " datetime(checkin_mtime(%d,rid),'unixepoch','localtime')"
240
+ " FROM vfile"
241
+ " ORDER BY %s", vid, zOrderBy
242
+ );
243
+ }else{
244
+ db_prepare(&q,
245
+ "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
246
+ " FROM vfile"
247
+ " ORDER BY %s", zOrderBy
248
+ );
249
+ }
219250
while( db_step(&q)==SQLITE_ROW ){
220251
const char *zPathname = db_column_text(&q,0);
221252
int isDeleted = db_column_int(&q, 1);
222253
int isNew = db_column_int(&q,2)==0;
223254
int chnged = db_column_int(&q,3);
224255
int renamed = db_column_int(&q,4);
225256
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
226
- if( isBrief ){
257
+ if( showAge ){
258
+ fossil_print("%s %s\n", db_column_text(&q, 5), zPathname);
259
+ }else if( isBrief ){
227260
fossil_print("%s\n", zPathname);
228261
}else if( isNew ){
229262
fossil_print("ADDED %s\n", zPathname);
230263
}else if( isDeleted ){
231264
fossil_print("DELETED %s\n", zPathname);
232265
--- src/checkin.c
+++ src/checkin.c
@@ -153,11 +153,11 @@
153 int cwdRelative = 0;
154 db_must_be_within_tree();
155 cwdRelative = determine_cwd_relative_option();
156 blob_zero(&report);
157 vid = db_lget_int("checkout", 0);
158 vfile_check_signature(vid, 0, useSha1sum);
159 status_report(&report, "", 0, cwdRelative);
160 blob_write_to_file(&report, "-");
161 }
162
163 /*
@@ -191,41 +191,74 @@
191 if( vid ){
192 show_common_info(vid, "checkout:", 1, 1);
193 }
194 changes_cmd();
195 }
 
 
 
 
 
196
197 /*
198 ** COMMAND: ls
199 **
200 ** Usage: %fossil ls [-l]
201 **
202 ** Show the names of all files in the current checkout. The -l provides
203 ** extra information about each file.
 
 
 
 
 
 
204 */
205 void ls_cmd(void){
206 int vid;
207 Stmt q;
208 int isBrief;
 
 
209
210 isBrief = find_option("l","l", 0)==0;
 
211 db_must_be_within_tree();
212 vid = db_lget_int("checkout", 0);
213 vfile_check_signature(vid, 0, 0);
214 db_prepare(&q,
215 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
216 " FROM vfile"
217 " ORDER BY 1"
218 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219 while( db_step(&q)==SQLITE_ROW ){
220 const char *zPathname = db_column_text(&q,0);
221 int isDeleted = db_column_int(&q, 1);
222 int isNew = db_column_int(&q,2)==0;
223 int chnged = db_column_int(&q,3);
224 int renamed = db_column_int(&q,4);
225 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
226 if( isBrief ){
 
 
227 fossil_print("%s\n", zPathname);
228 }else if( isNew ){
229 fossil_print("ADDED %s\n", zPathname);
230 }else if( isDeleted ){
231 fossil_print("DELETED %s\n", zPathname);
232
--- src/checkin.c
+++ src/checkin.c
@@ -153,11 +153,11 @@
153 int cwdRelative = 0;
154 db_must_be_within_tree();
155 cwdRelative = determine_cwd_relative_option();
156 blob_zero(&report);
157 vid = db_lget_int("checkout", 0);
158 vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
159 status_report(&report, "", 0, cwdRelative);
160 blob_write_to_file(&report, "-");
161 }
162
163 /*
@@ -191,41 +191,74 @@
191 if( vid ){
192 show_common_info(vid, "checkout:", 1, 1);
193 }
194 changes_cmd();
195 }
196
197 /*
198 ** Implementation of the checkin_mtime SQL function
199 */
200
201
202 /*
203 ** COMMAND: ls
204 **
205 ** Usage: %fossil ls ?OPTIONS? ?VERSION?
206 **
207 ** Show the names of all files in the current checkout. The -l provides
208 ** extra information about each file.
209 **
210 ** Options:
211 ** -l Provide extra information about each file.
212 ** --age Show when each file was committed
213 **
214 ** See also: changes, extra, status
215 */
216 void ls_cmd(void){
217 int vid;
218 Stmt q;
219 int isBrief;
220 int showAge;
221 char *zOrderBy = "pathname";
222
223 isBrief = find_option("l","l", 0)==0;
224 showAge = find_option("age",0,0)!=0;
225 db_must_be_within_tree();
226 vid = db_lget_int("checkout", 0);
227 if( find_option("t","t",0)!=0 ){
228 if( showAge ){
229 zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
230 }else{
231 zOrderBy = "mtime DESC";
232 }
233 }
234 verify_all_options();
235 vfile_check_signature(vid, 0);
236 if( showAge ){
237 db_prepare(&q,
238 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
239 " datetime(checkin_mtime(%d,rid),'unixepoch','localtime')"
240 " FROM vfile"
241 " ORDER BY %s", vid, zOrderBy
242 );
243 }else{
244 db_prepare(&q,
245 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
246 " FROM vfile"
247 " ORDER BY %s", zOrderBy
248 );
249 }
250 while( db_step(&q)==SQLITE_ROW ){
251 const char *zPathname = db_column_text(&q,0);
252 int isDeleted = db_column_int(&q, 1);
253 int isNew = db_column_int(&q,2)==0;
254 int chnged = db_column_int(&q,3);
255 int renamed = db_column_int(&q,4);
256 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
257 if( showAge ){
258 fossil_print("%s %s\n", db_column_text(&q, 5), zPathname);
259 }else if( isBrief ){
260 fossil_print("%s\n", zPathname);
261 }else if( isNew ){
262 fossil_print("ADDED %s\n", zPathname);
263 }else if( isDeleted ){
264 fossil_print("DELETED %s\n", zPathname);
265
+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
+19 -1
--- src/db.c
+++ src/db.c
@@ -627,10 +627,26 @@
627627
sqlite3_value **argv
628628
){
629629
sqlite3_result_int64(context, time(0));
630630
}
631631
632
+/*
633
+** Function to return the check-in time for a file.
634
+*/
635
+void db_checkin_mtime_function(
636
+ sqlite3_context *context,
637
+ int argc,
638
+ sqlite3_value **argv
639
+){
640
+ i64 mtime;
641
+ int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
642
+ sqlite3_value_int(argv[1]), &mtime);
643
+ if( rc==0 ){
644
+ sqlite3_result_int64(context, mtime);
645
+ }
646
+}
647
+
632648
633649
/*
634650
** Open a database file. Return a pointer to the new database
635651
** connection. An error results in process abort.
636652
*/
@@ -649,20 +665,22 @@
649665
db_err(sqlite3_errmsg(db));
650666
}
651667
sqlite3_busy_timeout(db, 5000);
652668
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
653669
sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
670
+ sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
671
+ db_checkin_mtime_function, 0, 0);
654672
return db;
655673
}
656674
657675
658676
/*
659677
** zDbName is the name of a database file. If no other database
660678
** file is open, then open this one. If another database file is
661679
** already open, then attach zDbName using the name zLabel.
662680
*/
663
-static void db_open_or_attach(const char *zDbName, const char *zLabel){
681
+void db_open_or_attach(const char *zDbName, const char *zLabel){
664682
if( !g.db ){
665683
g.db = openDatabase(zDbName);
666684
g.zMainDbType = zLabel;
667685
db_connection_init();
668686
}else{
669687
--- src/db.c
+++ src/db.c
@@ -627,10 +627,26 @@
627 sqlite3_value **argv
628 ){
629 sqlite3_result_int64(context, time(0));
630 }
631
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
632
633 /*
634 ** Open a database file. Return a pointer to the new database
635 ** connection. An error results in process abort.
636 */
@@ -649,20 +665,22 @@
649 db_err(sqlite3_errmsg(db));
650 }
651 sqlite3_busy_timeout(db, 5000);
652 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
653 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
 
 
654 return db;
655 }
656
657
658 /*
659 ** zDbName is the name of a database file. If no other database
660 ** file is open, then open this one. If another database file is
661 ** already open, then attach zDbName using the name zLabel.
662 */
663 static void db_open_or_attach(const char *zDbName, const char *zLabel){
664 if( !g.db ){
665 g.db = openDatabase(zDbName);
666 g.zMainDbType = zLabel;
667 db_connection_init();
668 }else{
669
--- src/db.c
+++ src/db.c
@@ -627,10 +627,26 @@
627 sqlite3_value **argv
628 ){
629 sqlite3_result_int64(context, time(0));
630 }
631
632 /*
633 ** Function to return the check-in time for a file.
634 */
635 void db_checkin_mtime_function(
636 sqlite3_context *context,
637 int argc,
638 sqlite3_value **argv
639 ){
640 i64 mtime;
641 int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
642 sqlite3_value_int(argv[1]), &mtime);
643 if( rc==0 ){
644 sqlite3_result_int64(context, mtime);
645 }
646 }
647
648
649 /*
650 ** Open a database file. Return a pointer to the new database
651 ** connection. An error results in process abort.
652 */
@@ -649,20 +665,22 @@
665 db_err(sqlite3_errmsg(db));
666 }
667 sqlite3_busy_timeout(db, 5000);
668 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
669 sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
670 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
671 db_checkin_mtime_function, 0, 0);
672 return db;
673 }
674
675
676 /*
677 ** zDbName is the name of a database file. If no other database
678 ** file is open, then open this one. If another database file is
679 ** already open, then attach zDbName using the name zLabel.
680 */
681 void db_open_or_attach(const char *zDbName, const char *zLabel){
682 if( !g.db ){
683 g.db = openDatabase(zDbName);
684 g.zMainDbType = zLabel;
685 db_connection_init();
686 }else{
687
--- 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
pqueue_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 = pqueue_extract(&queue, 0))!=0 ){
176177
db_bind_int(&ins, ":rid", rid);
177178
db_step(&ins);
178179
db_reset(&ins);
@@ -202,11 +203,13 @@
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 ancestor(rid INTEGER, generation INTEGER PRIMARY KEY);"
208
+ "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER,"
209
+ " generation INTEGER PRIMARY KEY);"
210
+ "DELETE FROM ancestor;"
208211
"INSERT INTO ancestor VALUES(%d, 0);", rid
209212
);
210213
db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
211214
db_prepare(&q,
212215
"SELECT pid FROM plink"
@@ -224,10 +227,44 @@
224227
db_reset(&ins);
225228
}
226229
db_finalize(&ins);
227230
db_finalize(&q);
228231
}
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
+}
229266
230267
/*
231268
** Load the record ID rid and up to N-1 closest descendants into
232269
** the "ok" table.
233270
*/
234271
--- 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 pqueue_insert(&queue, rid, 0.0, 0);
170 db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
171 db_prepare(&q,
172 "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
173 " WHERE a.cid=:rid"
 
174 );
175 while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
176 db_bind_int(&ins, ":rid", rid);
177 db_step(&ins);
178 db_reset(&ins);
@@ -202,11 +203,13 @@
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 ancestor(rid INTEGER, generation INTEGER PRIMARY KEY);"
 
 
208 "INSERT INTO ancestor VALUES(%d, 0);", rid
209 );
210 db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
211 db_prepare(&q,
212 "SELECT pid FROM plink"
@@ -224,10 +227,44 @@
224 db_reset(&ins);
225 }
226 db_finalize(&ins);
227 db_finalize(&q);
228 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
230 /*
231 ** Load the record ID rid and up to N-1 closest descendants into
232 ** the "ok" table.
233 */
234
--- 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 pqueue_insert(&queue, rid, 0.0, 0);
170 db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
171 db_prepare(&q,
172 "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
173 " WHERE a.cid=:rid %s",
174 directOnly ? " AND a.isprim" : ""
175 );
176 while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
177 db_bind_int(&ins, ":rid", rid);
178 db_step(&ins);
179 db_reset(&ins);
@@ -202,11 +203,13 @@
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,
215 "SELECT pid FROM plink"
@@ -224,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
@@ -212,11 +212,11 @@
212212
int asNewFile; /* Treat non-existant files as empty files */
213213
214214
ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0;
215215
asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
216216
vid = db_lget_int("checkout", 0);
217
- vfile_check_signature(vid, 1, 0);
217
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
218218
blob_zero(&sql);
219219
db_begin_transaction();
220220
if( zFrom ){
221221
int rid = name_to_typed_rid(zFrom, "ci");
222222
if( !is_a_version(rid) ){
223223
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -212,11 +212,11 @@
212 int asNewFile; /* Treat non-existant files as empty files */
213
214 ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0;
215 asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
216 vid = db_lget_int("checkout", 0);
217 vfile_check_signature(vid, 1, 0);
218 blob_zero(&sql);
219 db_begin_transaction();
220 if( zFrom ){
221 int rid = name_to_typed_rid(zFrom, "ci");
222 if( !is_a_version(rid) ){
223
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -212,11 +212,11 @@
212 int asNewFile; /* Treat non-existant files as empty files */
213
214 ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0;
215 asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
216 vid = db_lget_int("checkout", 0);
217 vfile_check_signature(vid, CKSIG_ENOTFILE);
218 blob_zero(&sql);
219 db_begin_transaction();
220 if( zFrom ){
221 int rid = name_to_typed_rid(zFrom, "ci");
222 if( !is_a_version(rid) ){
223
+49
--- src/file.c
+++ src/file.c
@@ -23,10 +23,16 @@
2323
#include <unistd.h>
2424
#include <string.h>
2525
#include <errno.h>
2626
#include "file.h"
2727
28
+#ifdef _WIN32
29
+# include <sys/utime.h>
30
+#else
31
+# include <sys/time.h>
32
+#endif
33
+
2834
/*
2935
** The file status information from the most recent stat() call.
3036
**
3137
** Use _stati64 rather than stat on windows, in order to handle files
3238
** larger than 2GB.
@@ -215,10 +221,53 @@
215221
}
216222
}
217223
#endif /* _WIN32 */
218224
return rc;
219225
}
226
+
227
+/*
228
+** Set the mtime for a file.
229
+*/
230
+void file_set_mtime(const char *zFilename, i64 newMTime){
231
+#if !defined(_WIN32)
232
+ struct timeval tv[2];
233
+ memset(tv, 0, sizeof(tv[0])*2);
234
+ tv[0].tv_sec = newMTime;
235
+ tv[1].tv_sec = newMTime;
236
+ utimes(zFilename, tv);
237
+#else
238
+ struct utimbuf tb;
239
+ wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
240
+ tb.actime = newMTime;
241
+ tb.modtime = newMTime;
242
+ _wutime(zMbcs, &tb);
243
+ fossil_mbcs_free(zMbcs);
244
+#endif
245
+}
246
+
247
+/*
248
+** COMMAND: test-set-mtime
249
+**
250
+** Usage: %fossil test-set-mtime FILENAME DATE/TIME
251
+**
252
+** Sets the mtime of the named file to the date/time shown.
253
+*/
254
+void test_set_mtime(void){
255
+ const char *zFile;
256
+ char *zDate;
257
+ i64 iMTime;
258
+ if( g.argc!=4 ){
259
+ usage("test-set-mtime FILENAME DATE/TIME");
260
+ }
261
+ db_open_or_attach(":memory:", "mem");
262
+ iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]);
263
+ zFile = g.argv[2];
264
+ file_set_mtime(zFile, iMTime);
265
+ iMTime = file_mtime(zFile);
266
+ zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime);
267
+ fossil_print("Set mtime of \"%s\" to %s (%lld)\n", zFile, zDate, iMTime);
268
+}
220269
221270
/*
222271
** Delete a file.
223272
*/
224273
void file_delete(const char *zFilename){
225274
--- src/file.c
+++ src/file.c
@@ -23,10 +23,16 @@
23 #include <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include "file.h"
27
 
 
 
 
 
 
28 /*
29 ** The file status information from the most recent stat() call.
30 **
31 ** Use _stati64 rather than stat on windows, in order to handle files
32 ** larger than 2GB.
@@ -215,10 +221,53 @@
215 }
216 }
217 #endif /* _WIN32 */
218 return rc;
219 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
221 /*
222 ** Delete a file.
223 */
224 void file_delete(const char *zFilename){
225
--- src/file.c
+++ src/file.c
@@ -23,10 +23,16 @@
23 #include <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include "file.h"
27
28 #ifdef _WIN32
29 # include <sys/utime.h>
30 #else
31 # include <sys/time.h>
32 #endif
33
34 /*
35 ** The file status information from the most recent stat() call.
36 **
37 ** Use _stati64 rather than stat on windows, in order to handle files
38 ** larger than 2GB.
@@ -215,10 +221,53 @@
221 }
222 }
223 #endif /* _WIN32 */
224 return rc;
225 }
226
227 /*
228 ** Set the mtime for a file.
229 */
230 void file_set_mtime(const char *zFilename, i64 newMTime){
231 #if !defined(_WIN32)
232 struct timeval tv[2];
233 memset(tv, 0, sizeof(tv[0])*2);
234 tv[0].tv_sec = newMTime;
235 tv[1].tv_sec = newMTime;
236 utimes(zFilename, tv);
237 #else
238 struct utimbuf tb;
239 wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
240 tb.actime = newMTime;
241 tb.modtime = newMTime;
242 _wutime(zMbcs, &tb);
243 fossil_mbcs_free(zMbcs);
244 #endif
245 }
246
247 /*
248 ** COMMAND: test-set-mtime
249 **
250 ** Usage: %fossil test-set-mtime FILENAME DATE/TIME
251 **
252 ** Sets the mtime of the named file to the date/time shown.
253 */
254 void test_set_mtime(void){
255 const char *zFile;
256 char *zDate;
257 i64 iMTime;
258 if( g.argc!=4 ){
259 usage("test-set-mtime FILENAME DATE/TIME");
260 }
261 db_open_or_attach(":memory:", "mem");
262 iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]);
263 zFile = g.argv[2];
264 file_set_mtime(zFile, iMTime);
265 iMTime = file_mtime(zFile);
266 zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime);
267 fossil_print("Set mtime of \"%s\" to %s (%lld)\n", zFile, zDate, iMTime);
268 }
269
270 /*
271 ** Delete a file.
272 */
273 void file_delete(const char *zFilename){
274
+1 -1
--- src/finfo.c
+++ src/finfo.c
@@ -51,11 +51,11 @@
5151
if( g.argc!=3 ) usage("-s|--status FILENAME");
5252
vid = db_lget_int("checkout", 0);
5353
if( vid==0 ){
5454
fossil_panic("no checkout to finfo files in");
5555
}
56
- vfile_check_signature(vid, 1, 0);
56
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
5757
file_tree_name(g.argv[2], &fname, 1);
5858
db_prepare(&q,
5959
"SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
6060
" FROM vfile WHERE vfile.pathname=%B", &fname);
6161
blob_zero(&line);
6262
--- src/finfo.c
+++ src/finfo.c
@@ -51,11 +51,11 @@
51 if( g.argc!=3 ) usage("-s|--status FILENAME");
52 vid = db_lget_int("checkout", 0);
53 if( vid==0 ){
54 fossil_panic("no checkout to finfo files in");
55 }
56 vfile_check_signature(vid, 1, 0);
57 file_tree_name(g.argv[2], &fname, 1);
58 db_prepare(&q,
59 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
60 " FROM vfile WHERE vfile.pathname=%B", &fname);
61 blob_zero(&line);
62
--- src/finfo.c
+++ src/finfo.c
@@ -51,11 +51,11 @@
51 if( g.argc!=3 ) usage("-s|--status FILENAME");
52 vid = db_lget_int("checkout", 0);
53 if( vid==0 ){
54 fossil_panic("no checkout to finfo files in");
55 }
56 vfile_check_signature(vid, CKSIG_ENOTFILE);
57 file_tree_name(g.argv[2], &fname, 1);
58 db_prepare(&q,
59 "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
60 " FROM vfile WHERE vfile.pathname=%B", &fname);
61 blob_zero(&line);
62
+1 -1
--- src/merge.c
+++ src/merge.c
@@ -143,11 +143,11 @@
143143
mid = t;
144144
}
145145
if( !is_a_version(pid) ){
146146
fossil_fatal("not a version: record #%d", pid);
147147
}
148
- vfile_check_signature(vid, 1, 0);
148
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
149149
db_begin_transaction();
150150
if( !nochangeFlag ) undo_begin();
151151
load_vfile_from_rid(mid);
152152
load_vfile_from_rid(pid);
153153
154154
--- src/merge.c
+++ src/merge.c
@@ -143,11 +143,11 @@
143 mid = t;
144 }
145 if( !is_a_version(pid) ){
146 fossil_fatal("not a version: record #%d", pid);
147 }
148 vfile_check_signature(vid, 1, 0);
149 db_begin_transaction();
150 if( !nochangeFlag ) undo_begin();
151 load_vfile_from_rid(mid);
152 load_vfile_from_rid(pid);
153
154
--- src/merge.c
+++ src/merge.c
@@ -143,11 +143,11 @@
143 mid = t;
144 }
145 if( !is_a_version(pid) ){
146 fossil_fatal("not a version: record #%d", pid);
147 }
148 vfile_check_signature(vid, CKSIG_ENOTFILE);
149 db_begin_transaction();
150 if( !nochangeFlag ) undo_begin();
151 load_vfile_from_rid(mid);
152 load_vfile_from_rid(pid);
153
154
+1 -1
--- src/stash.c
+++ src/stash.c
@@ -144,11 +144,11 @@
144144
zComment = find_option("comment", "m", 1);
145145
verify_all_options();
146146
stashid = db_lget_int("stash-next", 1);
147147
db_lset_int("stash-next", stashid+1);
148148
vid = db_lget_int("checkout", 0);
149
- vfile_check_signature(vid, 0, 0);
149
+ vfile_check_signature(vid, 0);
150150
db_multi_exec(
151151
"INSERT INTO stash(stashid,vid,comment,ctime)"
152152
"VALUES(%d,%d,%Q,julianday('now'))",
153153
stashid, vid, zComment
154154
);
155155
--- src/stash.c
+++ src/stash.c
@@ -144,11 +144,11 @@
144 zComment = find_option("comment", "m", 1);
145 verify_all_options();
146 stashid = db_lget_int("stash-next", 1);
147 db_lset_int("stash-next", stashid+1);
148 vid = db_lget_int("checkout", 0);
149 vfile_check_signature(vid, 0, 0);
150 db_multi_exec(
151 "INSERT INTO stash(stashid,vid,comment,ctime)"
152 "VALUES(%d,%d,%Q,julianday('now'))",
153 stashid, vid, zComment
154 );
155
--- src/stash.c
+++ src/stash.c
@@ -144,11 +144,11 @@
144 zComment = find_option("comment", "m", 1);
145 verify_all_options();
146 stashid = db_lget_int("stash-next", 1);
147 db_lset_int("stash-next", stashid+1);
148 vid = db_lget_int("checkout", 0);
149 vfile_check_signature(vid, 0);
150 db_multi_exec(
151 "INSERT INTO stash(stashid,vid,comment,ctime)"
152 "VALUES(%d,%d,%Q,julianday('now'))",
153 stashid, vid, zComment
154 );
155
+2 -2
--- src/timeline.c
+++ src/timeline.c
@@ -986,11 +986,11 @@
986986
}
987987
if( useDividers ) timeline_add_dividers(0, d_rid);
988988
db_multi_exec("DELETE FROM ok");
989989
}
990990
if( p_rid ){
991
- compute_ancestors(p_rid, nEntry+1);
991
+ compute_ancestors(p_rid, nEntry+1, 0);
992992
np = db_int(0, "SELECT count(*)-1 FROM ok");
993993
if( np>0 ){
994994
if( nd>0 ) blob_appendf(&desc, " and ");
995995
blob_appendf(&desc, "%d ancestors", np);
996996
db_multi_exec("%s", blob_str(&sql));
@@ -1507,11 +1507,11 @@
15071507
if( mode==3 || mode==4 ){
15081508
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
15091509
if( mode==3 ){
15101510
compute_descendants(objid, n);
15111511
}else{
1512
- compute_ancestors(objid, n);
1512
+ compute_ancestors(objid, n, 0);
15131513
}
15141514
blob_appendf(&sql, " AND blob.rid IN ok");
15151515
}
15161516
if( zType && (zType[0]!='a') ){
15171517
blob_appendf(&sql, " AND event.type=%Q ", zType);
15181518
--- src/timeline.c
+++ src/timeline.c
@@ -986,11 +986,11 @@
986 }
987 if( useDividers ) timeline_add_dividers(0, d_rid);
988 db_multi_exec("DELETE FROM ok");
989 }
990 if( p_rid ){
991 compute_ancestors(p_rid, nEntry+1);
992 np = db_int(0, "SELECT count(*)-1 FROM ok");
993 if( np>0 ){
994 if( nd>0 ) blob_appendf(&desc, " and ");
995 blob_appendf(&desc, "%d ancestors", np);
996 db_multi_exec("%s", blob_str(&sql));
@@ -1507,11 +1507,11 @@
1507 if( mode==3 || mode==4 ){
1508 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
1509 if( mode==3 ){
1510 compute_descendants(objid, n);
1511 }else{
1512 compute_ancestors(objid, n);
1513 }
1514 blob_appendf(&sql, " AND blob.rid IN ok");
1515 }
1516 if( zType && (zType[0]!='a') ){
1517 blob_appendf(&sql, " AND event.type=%Q ", zType);
1518
--- src/timeline.c
+++ src/timeline.c
@@ -986,11 +986,11 @@
986 }
987 if( useDividers ) timeline_add_dividers(0, d_rid);
988 db_multi_exec("DELETE FROM ok");
989 }
990 if( p_rid ){
991 compute_ancestors(p_rid, nEntry+1, 0);
992 np = db_int(0, "SELECT count(*)-1 FROM ok");
993 if( np>0 ){
994 if( nd>0 ) blob_appendf(&desc, " and ");
995 blob_appendf(&desc, "%d ancestors", np);
996 db_multi_exec("%s", blob_str(&sql));
@@ -1507,11 +1507,11 @@
1507 if( mode==3 || mode==4 ){
1508 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
1509 if( mode==3 ){
1510 compute_descendants(objid, n);
1511 }else{
1512 compute_ancestors(objid, n, 0);
1513 }
1514 blob_appendf(&sql, " AND blob.rid IN ok");
1515 }
1516 if( zType && (zType[0]!='a') ){
1517 blob_appendf(&sql, " AND event.type=%Q ", zType);
1518
+5 -2
--- src/update.c
+++ src/update.c
@@ -92,10 +92,11 @@
9292
Stmt q;
9393
int latestFlag; /* --latest. Pick the latest version if true */
9494
int nochangeFlag; /* -n or --nochange. Do a dry run */
9595
int verboseFlag; /* -v or --verbose. Output extra information */
9696
int debugFlag; /* --debug option */
97
+ int setmtimeFlag; /* --setmtime. Set mtimes on files */
9798
int nChng; /* Number of file renames */
9899
int *aChng; /* Array of file renames */
99100
int i; /* Loop counter */
100101
int nConflict = 0; /* Number of merge conflicts */
101102
Stmt mtimeXfer; /* Statment to transfer mtimes */
@@ -106,10 +107,11 @@
106107
}
107108
latestFlag = find_option("latest",0, 0)!=0;
108109
nochangeFlag = find_option("nochange","n",0)!=0;
109110
verboseFlag = find_option("verbose","v",0)!=0;
110111
debugFlag = find_option("debug",0,0)!=0;
112
+ setmtimeFlag = find_option("setmtime",0,0)!=0;
111113
db_must_be_within_tree();
112114
vid = db_lget_int("checkout", 0);
113115
if( vid==0 ){
114116
fossil_fatal("cannot find current version");
115117
}
@@ -186,11 +188,11 @@
186188
if( tid==0 ){
187189
fossil_panic("Internal Error: unable to find a version to update to.");
188190
}
189191
190192
db_begin_transaction();
191
- vfile_check_signature(vid, 1, 0);
193
+ vfile_check_signature(vid, CKSIG_ENOTFILE);
192194
if( !nochangeFlag && !internalUpdate ) undo_begin();
193195
load_vfile_from_rid(tid);
194196
195197
/*
196198
** The record.fn field is used to match files against each other. The
@@ -456,10 +458,11 @@
456458
/* A subset of files have been checked out. Keep the current
457459
** checkout unchanged. */
458460
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
459461
}
460462
if( !internalUpdate ) undo_finish();
463
+ if( setmtimeFlag ) vfile_check_signature(vid, CKSIG_SETMTIME);
461464
db_end_transaction(0);
462465
}
463466
}
464467
465468
/*
@@ -610,11 +613,11 @@
610613
blob_reset(&fname);
611614
}
612615
}else{
613616
int vid;
614617
vid = db_lget_int("checkout", 0);
615
- vfile_check_signature(vid, 0, 0);
618
+ vfile_check_signature(vid, 0);
616619
db_multi_exec(
617620
"DELETE FROM vmerge;"
618621
"INSERT INTO torevert "
619622
"SELECT pathname"
620623
" FROM vfile "
621624
--- src/update.c
+++ src/update.c
@@ -92,10 +92,11 @@
92 Stmt q;
93 int latestFlag; /* --latest. Pick the latest version if true */
94 int nochangeFlag; /* -n or --nochange. Do a dry run */
95 int verboseFlag; /* -v or --verbose. Output extra information */
96 int debugFlag; /* --debug option */
 
97 int nChng; /* Number of file renames */
98 int *aChng; /* Array of file renames */
99 int i; /* Loop counter */
100 int nConflict = 0; /* Number of merge conflicts */
101 Stmt mtimeXfer; /* Statment to transfer mtimes */
@@ -106,10 +107,11 @@
106 }
107 latestFlag = find_option("latest",0, 0)!=0;
108 nochangeFlag = find_option("nochange","n",0)!=0;
109 verboseFlag = find_option("verbose","v",0)!=0;
110 debugFlag = find_option("debug",0,0)!=0;
 
111 db_must_be_within_tree();
112 vid = db_lget_int("checkout", 0);
113 if( vid==0 ){
114 fossil_fatal("cannot find current version");
115 }
@@ -186,11 +188,11 @@
186 if( tid==0 ){
187 fossil_panic("Internal Error: unable to find a version to update to.");
188 }
189
190 db_begin_transaction();
191 vfile_check_signature(vid, 1, 0);
192 if( !nochangeFlag && !internalUpdate ) undo_begin();
193 load_vfile_from_rid(tid);
194
195 /*
196 ** The record.fn field is used to match files against each other. The
@@ -456,10 +458,11 @@
456 /* A subset of files have been checked out. Keep the current
457 ** checkout unchanged. */
458 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
459 }
460 if( !internalUpdate ) undo_finish();
 
461 db_end_transaction(0);
462 }
463 }
464
465 /*
@@ -610,11 +613,11 @@
610 blob_reset(&fname);
611 }
612 }else{
613 int vid;
614 vid = db_lget_int("checkout", 0);
615 vfile_check_signature(vid, 0, 0);
616 db_multi_exec(
617 "DELETE FROM vmerge;"
618 "INSERT INTO torevert "
619 "SELECT pathname"
620 " FROM vfile "
621
--- src/update.c
+++ src/update.c
@@ -92,10 +92,11 @@
92 Stmt q;
93 int latestFlag; /* --latest. Pick the latest version if true */
94 int nochangeFlag; /* -n or --nochange. Do a dry run */
95 int verboseFlag; /* -v or --verbose. Output extra information */
96 int debugFlag; /* --debug option */
97 int setmtimeFlag; /* --setmtime. Set mtimes on files */
98 int nChng; /* Number of file renames */
99 int *aChng; /* Array of file renames */
100 int i; /* Loop counter */
101 int nConflict = 0; /* Number of merge conflicts */
102 Stmt mtimeXfer; /* Statment to transfer mtimes */
@@ -106,10 +107,11 @@
107 }
108 latestFlag = find_option("latest",0, 0)!=0;
109 nochangeFlag = find_option("nochange","n",0)!=0;
110 verboseFlag = find_option("verbose","v",0)!=0;
111 debugFlag = find_option("debug",0,0)!=0;
112 setmtimeFlag = find_option("setmtime",0,0)!=0;
113 db_must_be_within_tree();
114 vid = db_lget_int("checkout", 0);
115 if( vid==0 ){
116 fossil_fatal("cannot find current version");
117 }
@@ -186,11 +188,11 @@
188 if( tid==0 ){
189 fossil_panic("Internal Error: unable to find a version to update to.");
190 }
191
192 db_begin_transaction();
193 vfile_check_signature(vid, CKSIG_ENOTFILE);
194 if( !nochangeFlag && !internalUpdate ) undo_begin();
195 load_vfile_from_rid(tid);
196
197 /*
198 ** The record.fn field is used to match files against each other. The
@@ -456,10 +458,11 @@
458 /* A subset of files have been checked out. Keep the current
459 ** checkout unchanged. */
460 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
461 }
462 if( !internalUpdate ) undo_finish();
463 if( setmtimeFlag ) vfile_check_signature(vid, CKSIG_SETMTIME);
464 db_end_transaction(0);
465 }
466 }
467
468 /*
@@ -610,11 +613,11 @@
613 blob_reset(&fname);
614 }
615 }else{
616 int vid;
617 vid = db_lget_int("checkout", 0);
618 vfile_check_signature(vid, 0);
619 db_multi_exec(
620 "DELETE FROM vmerge;"
621 "INSERT INTO torevert "
622 "SELECT pathname"
623 " FROM vfile "
624
+86 -41
--- src/vfile.c
+++ src/vfile.c
@@ -122,31 +122,53 @@
122122
db_finalize(&ins);
123123
manifest_destroy(p);
124124
db_end_transaction(0);
125125
}
126126
127
+#if INTERFACE
128
+/*
129
+** The cksigFlags parameter to vfile_check_signature() is an OR-ed
130
+** combination of the following bits:
131
+*/
132
+#define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */
133
+#define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */
134
+#define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */
135
+
136
+#endif /* INTERFACE */
137
+
127138
/*
128
-** Check the file signature of the disk image for every VFILE of vid.
129
-**
130
-** Set the VFILE.CHNGED field on every file that has changed. Also
131
-** set VFILE.CHNGED on every folder that contains a file or folder
132
-** that has changed.
133
-**
134
-** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume
135
-** the file has changed without having the check the on-disk image.
136
-**
137
-** If the size of the file has changed, then we assume that it has
138
-** changed. If the mtime of the file has not changed and useSha1sum is false
139
-** and the mtime-changes setting is true (the default) then we assume that
140
-** the file has not changed. If the mtime has changed, we go ahead and
141
-** double-check that the file has changed by looking at its SHA1 sum.
142
-*/
143
-void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){
139
+** Look at every VFILE entry with the given vid and update
140
+** VFILE.CHNGED field according to whether or not
141
+** the file has changed. 0 means no change. 1 means edited. 2 means
142
+** the file has changed due to a merge. 3 means the file was added
143
+** by a merge.
144
+**
145
+** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
146
+** removed from configuration management via "fossil rm" or added via
147
+** "fossil add", respectively, and in both cases we always know that
148
+** the file has changed without having the check the size, mtime,
149
+** or on-disk content.
150
+**
151
+** If the size of the file has changed, then we always know that the file
152
+** changed without having to look at the mtime or on-disk content.
153
+**
154
+** The mtime of the file is only a factor if the mtime-changes setting
155
+** is false and the useSha1sum flag is false. If the mtime-changes
156
+** setting is true (or undefined - it defaults to true) or if useSha1sum
157
+** is true, then we do not trust the mtime and will examine the on-disk
158
+** content to determine if a file really is the same.
159
+**
160
+** If the mtime is used, it is used only to determine if files are the same.
161
+** If the mtime of a file has changed, we still examine the on-disk content
162
+** to see whether or not the edit was a null-edit.
163
+*/
164
+void vfile_check_signature(int vid, unsigned int cksigFlags){
144165
int nErr = 0;
145166
Stmt q;
146167
Blob fileCksum, origCksum;
147
- int checkMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);
168
+ int useMtime = (cksigFlags & CKSIG_SHA1)==0
169
+ && db_get_boolean("mtime-changes", 1);
148170
149171
db_begin_transaction();
150172
db_prepare(&q, "SELECT id, %Q || pathname,"
151173
" vfile.mrid, deleted, chnged, uuid, size, mtime"
152174
" FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -156,55 +178,78 @@
156178
const char *zName;
157179
int chnged = 0;
158180
int oldChnged;
159181
i64 oldMtime;
160182
i64 currentMtime;
183
+ i64 origSize;
184
+ i64 currentSize;
161185
162186
id = db_column_int(&q, 0);
163187
zName = db_column_text(&q, 1);
164188
rid = db_column_int(&q, 2);
165189
isDeleted = db_column_int(&q, 3);
166
- oldChnged = db_column_int(&q, 4);
190
+ oldChnged = chnged = db_column_int(&q, 4);
167191
oldMtime = db_column_int64(&q, 7);
168
- if( isDeleted ){
192
+ currentSize = file_size(zName);
193
+ origSize = db_column_int64(&q, 6);
194
+ currentMtime = file_mtime(0);
195
+ if( chnged==0 && (isDeleted || rid==0) ){
196
+ /* "fossil rm" or "fossil add" always change the file */
169197
chnged = 1;
170
- }else if( !file_isfile(zName) && file_size(0)>=0 ){
171
- if( notFileIsFatal ){
198
+ }else if( !file_isfile(0) && currentSize>=0 ){
199
+ if( cksigFlags & CKSIG_ENOTFILE ){
172200
fossil_warning("not an ordinary file: %s", zName);
173201
nErr++;
174202
}
175203
chnged = 1;
176
- }else if( oldChnged>=2 ){
177
- chnged = oldChnged;
178
- }else if( rid==0 ){
179
- chnged = 1;
180
- }
181
- if( chnged!=1 ){
182
- i64 origSize = db_column_int64(&q, 6);
183
- currentMtime = file_mtime(0);
184
- if( origSize!=file_size(0) ){
185
- /* A file size change is definitive - the file has changed. No
186
- ** need to check the sha1sum */
187
- chnged = 1;
188
- }
189
- }
190
- if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
204
+ }
205
+ if( origSize!=currentSize ){
206
+ if( chnged!=1 ){
207
+ /* A file size change is definitive - the file has changed. No
208
+ ** need to check the mtime or sha1sum */
209
+ chnged = 1;
210
+ }
211
+ }else if( chnged==1 && rid!=0 && !isDeleted ){
212
+ /* File is believed to have changed but it is the same size.
213
+ ** Double check that it really has changed by looking at content. */
214
+ assert( origSize==currentSize );
215
+ db_ephemeral_blob(&q, 5, &origCksum);
216
+ if( sha1sum_file(zName, &fileCksum) ){
217
+ blob_zero(&fileCksum);
218
+ }
219
+ if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0;
220
+ blob_reset(&origCksum);
221
+ blob_reset(&fileCksum);
222
+ }else if( (chnged==0 || chnged==2)
223
+ && (useMtime==0 || currentMtime!=oldMtime) ){
224
+ /* For files that were formerly believed to be unchanged or that were
225
+ ** changed by merging, if their mtime changes, or unconditionally
226
+ ** if --sha1sum is used, check to see if they have been edited by
227
+ ** looking at their SHA1 sum */
228
+ assert( origSize==currentSize );
191229
db_ephemeral_blob(&q, 5, &origCksum);
192230
if( sha1sum_file(zName, &fileCksum) ){
193231
blob_zero(&fileCksum);
194232
}
195233
if( blob_compare(&fileCksum, &origCksum) ){
196234
chnged = 1;
197
- }else if( currentMtime!=oldMtime ){
198
- db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
199
- currentMtime, id);
200235
}
201236
blob_reset(&origCksum);
202237
blob_reset(&fileCksum);
203238
}
204
- if( chnged!=oldChnged && (chnged || !checkMtime) ){
205
- db_multi_exec("UPDATE vfile SET chnged=%d WHERE id=%d", chnged, id);
239
+ if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2) ){
240
+ i64 desiredMtime;
241
+ if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
242
+ if( currentMtime!=desiredMtime ){
243
+ file_set_mtime(zName, desiredMtime);
244
+ currentMtime = file_mtime(zName);
245
+ }
246
+ }
247
+ }
248
+ if( currentMtime!=oldMtime || chnged!=oldChnged ){
249
+ db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
250
+ currentMtime, chnged, id);
206251
}
207252
}
208253
db_finalize(&q);
209254
if( nErr ) fossil_fatal("abort due to prior errors");
210255
db_end_transaction(0);
211256
--- src/vfile.c
+++ src/vfile.c
@@ -122,31 +122,53 @@
122 db_finalize(&ins);
123 manifest_destroy(p);
124 db_end_transaction(0);
125 }
126
 
 
 
 
 
 
 
 
 
 
 
127 /*
128 ** Check the file signature of the disk image for every VFILE of vid.
129 **
130 ** Set the VFILE.CHNGED field on every file that has changed. Also
131 ** set VFILE.CHNGED on every folder that contains a file or folder
132 ** that has changed.
133 **
134 ** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume
135 ** the file has changed without having the check the on-disk image.
136 **
137 ** If the size of the file has changed, then we assume that it has
138 ** changed. If the mtime of the file has not changed and useSha1sum is false
139 ** and the mtime-changes setting is true (the default) then we assume that
140 ** the file has not changed. If the mtime has changed, we go ahead and
141 ** double-check that the file has changed by looking at its SHA1 sum.
142 */
143 void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){
 
 
 
 
 
 
 
 
 
 
144 int nErr = 0;
145 Stmt q;
146 Blob fileCksum, origCksum;
147 int checkMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);
 
148
149 db_begin_transaction();
150 db_prepare(&q, "SELECT id, %Q || pathname,"
151 " vfile.mrid, deleted, chnged, uuid, size, mtime"
152 " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -156,55 +178,78 @@
156 const char *zName;
157 int chnged = 0;
158 int oldChnged;
159 i64 oldMtime;
160 i64 currentMtime;
 
 
161
162 id = db_column_int(&q, 0);
163 zName = db_column_text(&q, 1);
164 rid = db_column_int(&q, 2);
165 isDeleted = db_column_int(&q, 3);
166 oldChnged = db_column_int(&q, 4);
167 oldMtime = db_column_int64(&q, 7);
168 if( isDeleted ){
 
 
 
 
169 chnged = 1;
170 }else if( !file_isfile(zName) && file_size(0)>=0 ){
171 if( notFileIsFatal ){
172 fossil_warning("not an ordinary file: %s", zName);
173 nErr++;
174 }
175 chnged = 1;
176 }else if( oldChnged>=2 ){
177 chnged = oldChnged;
178 }else if( rid==0 ){
179 chnged = 1;
180 }
181 if( chnged!=1 ){
182 i64 origSize = db_column_int64(&q, 6);
183 currentMtime = file_mtime(0);
184 if( origSize!=file_size(0) ){
185 /* A file size change is definitive - the file has changed. No
186 ** need to check the sha1sum */
187 chnged = 1;
188 }
189 }
190 if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
 
 
 
 
 
 
 
 
 
 
191 db_ephemeral_blob(&q, 5, &origCksum);
192 if( sha1sum_file(zName, &fileCksum) ){
193 blob_zero(&fileCksum);
194 }
195 if( blob_compare(&fileCksum, &origCksum) ){
196 chnged = 1;
197 }else if( currentMtime!=oldMtime ){
198 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
199 currentMtime, id);
200 }
201 blob_reset(&origCksum);
202 blob_reset(&fileCksum);
203 }
204 if( chnged!=oldChnged && (chnged || !checkMtime) ){
205 db_multi_exec("UPDATE vfile SET chnged=%d WHERE id=%d", chnged, id);
 
 
 
 
 
 
 
 
 
 
206 }
207 }
208 db_finalize(&q);
209 if( nErr ) fossil_fatal("abort due to prior errors");
210 db_end_transaction(0);
211
--- src/vfile.c
+++ src/vfile.c
@@ -122,31 +122,53 @@
122 db_finalize(&ins);
123 manifest_destroy(p);
124 db_end_transaction(0);
125 }
126
127 #if INTERFACE
128 /*
129 ** The cksigFlags parameter to vfile_check_signature() is an OR-ed
130 ** combination of the following bits:
131 */
132 #define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */
133 #define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */
134 #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */
135
136 #endif /* INTERFACE */
137
138 /*
139 ** Look at every VFILE entry with the given vid and update
140 ** VFILE.CHNGED field according to whether or not
141 ** the file has changed. 0 means no change. 1 means edited. 2 means
142 ** the file has changed due to a merge. 3 means the file was added
143 ** by a merge.
144 **
145 ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
146 ** removed from configuration management via "fossil rm" or added via
147 ** "fossil add", respectively, and in both cases we always know that
148 ** the file has changed without having the check the size, mtime,
149 ** or on-disk content.
150 **
151 ** If the size of the file has changed, then we always know that the file
152 ** changed without having to look at the mtime or on-disk content.
153 **
154 ** The mtime of the file is only a factor if the mtime-changes setting
155 ** is false and the useSha1sum flag is false. If the mtime-changes
156 ** setting is true (or undefined - it defaults to true) or if useSha1sum
157 ** is true, then we do not trust the mtime and will examine the on-disk
158 ** content to determine if a file really is the same.
159 **
160 ** If the mtime is used, it is used only to determine if files are the same.
161 ** If the mtime of a file has changed, we still examine the on-disk content
162 ** to see whether or not the edit was a null-edit.
163 */
164 void vfile_check_signature(int vid, unsigned int cksigFlags){
165 int nErr = 0;
166 Stmt q;
167 Blob fileCksum, origCksum;
168 int useMtime = (cksigFlags & CKSIG_SHA1)==0
169 && db_get_boolean("mtime-changes", 1);
170
171 db_begin_transaction();
172 db_prepare(&q, "SELECT id, %Q || pathname,"
173 " vfile.mrid, deleted, chnged, uuid, size, mtime"
174 " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -156,55 +178,78 @@
178 const char *zName;
179 int chnged = 0;
180 int oldChnged;
181 i64 oldMtime;
182 i64 currentMtime;
183 i64 origSize;
184 i64 currentSize;
185
186 id = db_column_int(&q, 0);
187 zName = db_column_text(&q, 1);
188 rid = db_column_int(&q, 2);
189 isDeleted = db_column_int(&q, 3);
190 oldChnged = chnged = db_column_int(&q, 4);
191 oldMtime = db_column_int64(&q, 7);
192 currentSize = file_size(zName);
193 origSize = db_column_int64(&q, 6);
194 currentMtime = file_mtime(0);
195 if( chnged==0 && (isDeleted || rid==0) ){
196 /* "fossil rm" or "fossil add" always change the file */
197 chnged = 1;
198 }else if( !file_isfile(0) && currentSize>=0 ){
199 if( cksigFlags & CKSIG_ENOTFILE ){
200 fossil_warning("not an ordinary file: %s", zName);
201 nErr++;
202 }
203 chnged = 1;
204 }
205 if( origSize!=currentSize ){
206 if( chnged!=1 ){
207 /* A file size change is definitive - the file has changed. No
208 ** need to check the mtime or sha1sum */
209 chnged = 1;
210 }
211 }else if( chnged==1 && rid!=0 && !isDeleted ){
212 /* File is believed to have changed but it is the same size.
213 ** Double check that it really has changed by looking at content. */
214 assert( origSize==currentSize );
215 db_ephemeral_blob(&q, 5, &origCksum);
216 if( sha1sum_file(zName, &fileCksum) ){
217 blob_zero(&fileCksum);
218 }
219 if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0;
220 blob_reset(&origCksum);
221 blob_reset(&fileCksum);
222 }else if( (chnged==0 || chnged==2)
223 && (useMtime==0 || currentMtime!=oldMtime) ){
224 /* For files that were formerly believed to be unchanged or that were
225 ** changed by merging, if their mtime changes, or unconditionally
226 ** if --sha1sum is used, check to see if they have been edited by
227 ** looking at their SHA1 sum */
228 assert( origSize==currentSize );
229 db_ephemeral_blob(&q, 5, &origCksum);
230 if( sha1sum_file(zName, &fileCksum) ){
231 blob_zero(&fileCksum);
232 }
233 if( blob_compare(&fileCksum, &origCksum) ){
234 chnged = 1;
 
 
 
235 }
236 blob_reset(&origCksum);
237 blob_reset(&fileCksum);
238 }
239 if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2) ){
240 i64 desiredMtime;
241 if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
242 if( currentMtime!=desiredMtime ){
243 file_set_mtime(zName, desiredMtime);
244 currentMtime = file_mtime(zName);
245 }
246 }
247 }
248 if( currentMtime!=oldMtime || chnged!=oldChnged ){
249 db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
250 currentMtime, chnged, id);
251 }
252 }
253 db_finalize(&q);
254 if( nErr ) fossil_fatal("abort due to prior errors");
255 db_end_transaction(0);
256

Keyboard Shortcuts

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