Index: src/vfile.c
==================================================================
--- src/vfile.c
+++ src/vfile.c
@@ -124,40 +124,30 @@
   manifest_destroy(p);
   db_end_transaction(0);
 }
 
 /*
-** Look at every VFILE entry with the given vid and  set update
-** VFILE.CHNGED field on every file according to whether or not
-** the file has changes.  0 means no change.  1 means edited.  2 means
-** the file has changed due to a merge.  3 means the file was added
-** by a merge.
+** Check the file signature of the disk image for every VFILE of vid.
 **
-** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was
-** either removed from managemented via "fossil rm" or added via
-** "fossil add", respectively, and in both cases we always know that 
-** the file has changed without having the check the size, mtime,
-** or on-disk content.
+** Set the VFILE.CHNGED field on every file that has changed.  Also 
+** set VFILE.CHNGED on every folder that contains a file or folder 
+** that has changed.
 **
-** If the size of the file has changed, then we always know that the file
-** changed without having to look at the mtime or on-disk content.
+** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume
+** the file has changed without having the check the on-disk image.
 **
-** The mtime of the file is only a factor if the mtime-changes setting
-** is false and the useSha1sum flag is false.  If the mtime-changes
-** setting is true (or undefined - it defaults to true) or if useSha1sum
-** is true, then we do not trust the mtime and will examine the on-disk
-** content to determine if a file really is the same.
-**
-** If the mtime is used, it is used only to determine if files are the same.
-** If the mtime of a file has changed, we still examine the on-disk content
-** to see whether or not the edit was a null-edit.
+** If the size of the file has changed, then we assume that it has
+** changed.  If the mtime of the file has not changed and useSha1sum is false
+** and the mtime-changes setting is true (the default) then we assume that
+** the file has not changed.  If the mtime has changed, we go ahead and
+** double-check that the file has changed by looking at its SHA1 sum.
 */
 void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){
   int nErr = 0;
   Stmt q;
   Blob fileCksum, origCksum;
-  int useMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);
+  int checkMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1);
 
   db_begin_transaction();
   db_prepare(&q, "SELECT id, %Q || pathname,"
                  "       vfile.mrid, deleted, chnged, uuid, size, mtime"
                  "  FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -167,67 +157,55 @@
     const char *zName;
     int chnged = 0;
     int oldChnged;
     i64 oldMtime;
     i64 currentMtime;
-    i64 origSize;
-    i64 currentSize;
 
     id = db_column_int(&q, 0);
     zName = db_column_text(&q, 1);
     rid = db_column_int(&q, 2);
     isDeleted = db_column_int(&q, 3);
-    oldChnged = chnged = db_column_int(&q, 4);
+    oldChnged = db_column_int(&q, 4);
     oldMtime = db_column_int64(&q, 7);
-    currentSize = file_wd_size(zName);
-    origSize = db_column_int64(&q, 6);
-    currentMtime = file_wd_mtime(0);
-    if( chnged==0 && (isDeleted || rid==0) ){
-      /* "fossil rm" or "fossil add" always change the file */
+    if( isDeleted ){
       chnged = 1;
-    }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
+    }else if( !file_wd_isfile_or_link(zName) && file_wd_size(0)>=0 ){
       if( notFileIsFatal ){
         fossil_warning("not an ordinary file: %s", zName);
         nErr++;
       }
       chnged = 1;
+    }else if( oldChnged>=2 ){
+      chnged = oldChnged;
+    }else if( rid==0 ){
+      chnged = 1;
     }
-    if( origSize!=currentSize ){
-      if( chnged==0 ){
+    if( chnged!=1 ){
+      i64 origSize = db_column_int64(&q, 6);
+      currentMtime = file_wd_mtime(0);
+      if( origSize!=file_wd_size(0) ){
         /* A file size change is definitive - the file has changed.  No
-        ** need to check the mtime or sha1sum */
+        ** need to check the sha1sum */
         chnged = 1;
       }
-    }else if( (chnged==1 || chnged==2) && rid!=0 && !isDeleted ){
-      /* File is believed to have changed but it is the same size.
-      ** Double check that it really has changed by looking at content. */
-      assert( origSize==currentSize );
-      db_ephemeral_blob(&q, 5, &origCksum);
-      if( sha1sum_file(zName, &fileCksum) ){
-        blob_zero(&fileCksum);
-      }
-      if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0;
-      blob_reset(&origCksum);
-      blob_reset(&fileCksum);
-    }else if( chnged==0 && (useMtime==0 || currentMtime!=oldMtime) ){
-      /* For files that were formerly believed to be unchanged, if their
-      ** mtime changes, or unconditionally if --sha1sum is used, check
-      ** to see if they have been edited by looking at their SHA1 sum */
-      assert( origSize==currentSize );
+    }
+    if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
       db_ephemeral_blob(&q, 5, &origCksum);
       if( sha1sum_file(zName, &fileCksum) ){
         blob_zero(&fileCksum);
       }
       if( blob_compare(&fileCksum, &origCksum) ){
         chnged = 1;
+      }else if( currentMtime!=oldMtime ){
+        db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
+                      currentMtime, id);
       }
       blob_reset(&origCksum);
       blob_reset(&fileCksum);
     }
-    if( currentMtime!=oldMtime || chnged!=oldChnged ){
-      db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
-                    currentMtime, chnged, id);
+    if( chnged!=oldChnged && (chnged || !checkMtime) ){
+      db_multi_exec("UPDATE vfile SET chnged=%d WHERE id=%d", chnged, id);
     }
   }
   db_finalize(&q);
   if( nErr ) fossil_fatal("abort due to prior errors");
   db_end_transaction(0);