Fossil SCM
Improvements to "fossil status" processing. Automatically detect when a file has undergone a null-edit - when the mtime has changed but the content of the file is unchanged - and mark such files as unchanged.
Commit
b9227b85cbd78f333e183f370acead94a47a6669
Parent
aa55cf3aa6d4c74…
1 file changed
+60
-38
+60
-38
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -124,30 +124,40 @@ | ||
| 124 | 124 | manifest_destroy(p); |
| 125 | 125 | db_end_transaction(0); |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | 128 | /* |
| 129 | -** Check the file signature of the disk image for every VFILE of vid. | |
| 130 | -** | |
| 131 | -** Set the VFILE.CHNGED field on every file that has changed. Also | |
| 132 | -** set VFILE.CHNGED on every folder that contains a file or folder | |
| 133 | -** that has changed. | |
| 134 | -** | |
| 135 | -** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume | |
| 136 | -** the file has changed without having the check the on-disk image. | |
| 137 | -** | |
| 138 | -** If the size of the file has changed, then we assume that it has | |
| 139 | -** changed. If the mtime of the file has not changed and useSha1sum is false | |
| 140 | -** and the mtime-changes setting is true (the default) then we assume that | |
| 141 | -** the file has not changed. If the mtime has changed, we go ahead and | |
| 142 | -** double-check that the file has changed by looking at its SHA1 sum. | |
| 129 | +** Look at every VFILE entry with the given vid and set update | |
| 130 | +** VFILE.CHNGED field on every file according to whether or not | |
| 131 | +** the file has changes. 0 means no change. 1 means edited. 2 means | |
| 132 | +** the file has changed due to a merge. 3 means the file was added | |
| 133 | +** by a merge. | |
| 134 | +** | |
| 135 | +** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was | |
| 136 | +** either removed from managemented via "fossil rm" or added via | |
| 137 | +** "fossil add", respectively, and in both cases we always know that | |
| 138 | +** the file has changed without having the check the size, mtime, | |
| 139 | +** or on-disk content. | |
| 140 | +** | |
| 141 | +** If the size of the file has changed, then we always know that the file | |
| 142 | +** changed without having to look at the mtime or on-disk content. | |
| 143 | +** | |
| 144 | +** The mtime of the file is only a factor if the mtime-changes setting | |
| 145 | +** is false and the useSha1sum flag is false. If the mtime-changes | |
| 146 | +** setting is true (or undefined - it defaults to true) or if useSha1sum | |
| 147 | +** is true, then we do not trust the mtime and will examine the on-disk | |
| 148 | +** content to determine if a file really is the same. | |
| 149 | +** | |
| 150 | +** If the mtime is used, it is used only to determine if files are the same. | |
| 151 | +** If the mtime of a file has changed, we still examine the on-disk content | |
| 152 | +** to see whether or not the edit was a null-edit. | |
| 143 | 153 | */ |
| 144 | 154 | void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){ |
| 145 | 155 | int nErr = 0; |
| 146 | 156 | Stmt q; |
| 147 | 157 | Blob fileCksum, origCksum; |
| 148 | - int checkMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1); | |
| 158 | + int useMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1); | |
| 149 | 159 | |
| 150 | 160 | db_begin_transaction(); |
| 151 | 161 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 152 | 162 | " vfile.mrid, deleted, chnged, uuid, size, mtime" |
| 153 | 163 | " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" |
| @@ -157,55 +167,67 @@ | ||
| 157 | 167 | const char *zName; |
| 158 | 168 | int chnged = 0; |
| 159 | 169 | int oldChnged; |
| 160 | 170 | i64 oldMtime; |
| 161 | 171 | i64 currentMtime; |
| 172 | + i64 origSize; | |
| 173 | + i64 currentSize; | |
| 162 | 174 | |
| 163 | 175 | id = db_column_int(&q, 0); |
| 164 | 176 | zName = db_column_text(&q, 1); |
| 165 | 177 | rid = db_column_int(&q, 2); |
| 166 | 178 | isDeleted = db_column_int(&q, 3); |
| 167 | - oldChnged = db_column_int(&q, 4); | |
| 179 | + oldChnged = chnged = db_column_int(&q, 4); | |
| 168 | 180 | oldMtime = db_column_int64(&q, 7); |
| 169 | - if( isDeleted ){ | |
| 181 | + currentSize = file_wd_size(zName); | |
| 182 | + origSize = db_column_int64(&q, 6); | |
| 183 | + currentMtime = file_wd_mtime(0); | |
| 184 | + if( chnged==0 && (isDeleted || rid==0) ){ | |
| 185 | + /* "fossil rm" or "fossil add" always change the file */ | |
| 170 | 186 | chnged = 1; |
| 171 | - }else if( !file_wd_isfile_or_link(zName) && file_wd_size(0)>=0 ){ | |
| 187 | + }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){ | |
| 172 | 188 | if( notFileIsFatal ){ |
| 173 | 189 | fossil_warning("not an ordinary file: %s", zName); |
| 174 | 190 | nErr++; |
| 175 | 191 | } |
| 176 | 192 | chnged = 1; |
| 177 | - }else if( oldChnged>=2 ){ | |
| 178 | - chnged = oldChnged; | |
| 179 | - }else if( rid==0 ){ | |
| 180 | - chnged = 1; | |
| 181 | - } | |
| 182 | - if( chnged!=1 ){ | |
| 183 | - i64 origSize = db_column_int64(&q, 6); | |
| 184 | - currentMtime = file_wd_mtime(0); | |
| 185 | - if( origSize!=file_wd_size(0) ){ | |
| 186 | - /* A file size change is definitive - the file has changed. No | |
| 187 | - ** need to check the sha1sum */ | |
| 188 | - chnged = 1; | |
| 189 | - } | |
| 190 | - } | |
| 191 | - if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){ | |
| 193 | + } | |
| 194 | + if( origSize!=currentSize ){ | |
| 195 | + if( chnged==0 ){ | |
| 196 | + /* A file size change is definitive - the file has changed. No | |
| 197 | + ** need to check the mtime or sha1sum */ | |
| 198 | + chnged = 1; | |
| 199 | + } | |
| 200 | + }else if( (chnged==1 || chnged==2) && rid!=0 && !isDeleted ){ | |
| 201 | + /* File is believed to have changed but it is the same size. | |
| 202 | + ** Double check that it really has changed by looking at content. */ | |
| 203 | + assert( origSize==currentSize ); | |
| 204 | + db_ephemeral_blob(&q, 5, &origCksum); | |
| 205 | + if( sha1sum_file(zName, &fileCksum) ){ | |
| 206 | + blob_zero(&fileCksum); | |
| 207 | + } | |
| 208 | + if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0; | |
| 209 | + blob_reset(&origCksum); | |
| 210 | + blob_reset(&fileCksum); | |
| 211 | + }else if( chnged==0 && (useMtime==0 || currentMtime!=oldMtime) ){ | |
| 212 | + /* For files that were formerly believed to be unchanged, if their | |
| 213 | + ** mtime changes, or unconditionally if --sha1sum is used, check | |
| 214 | + ** to see if they have been edited by looking at their SHA1 sum */ | |
| 215 | + assert( origSize==currentSize ); | |
| 192 | 216 | db_ephemeral_blob(&q, 5, &origCksum); |
| 193 | 217 | if( sha1sum_file(zName, &fileCksum) ){ |
| 194 | 218 | blob_zero(&fileCksum); |
| 195 | 219 | } |
| 196 | 220 | if( blob_compare(&fileCksum, &origCksum) ){ |
| 197 | 221 | chnged = 1; |
| 198 | - }else if( currentMtime!=oldMtime ){ | |
| 199 | - db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", | |
| 200 | - currentMtime, id); | |
| 201 | 222 | } |
| 202 | 223 | blob_reset(&origCksum); |
| 203 | 224 | blob_reset(&fileCksum); |
| 204 | 225 | } |
| 205 | - if( chnged!=oldChnged && (chnged || !checkMtime) ){ | |
| 206 | - db_multi_exec("UPDATE vfile SET chnged=%d WHERE id=%d", chnged, id); | |
| 226 | + if( currentMtime!=oldMtime || chnged!=oldChnged ){ | |
| 227 | + db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d", | |
| 228 | + currentMtime, chnged, id); | |
| 207 | 229 | } |
| 208 | 230 | } |
| 209 | 231 | db_finalize(&q); |
| 210 | 232 | if( nErr ) fossil_fatal("abort due to prior errors"); |
| 211 | 233 | db_end_transaction(0); |
| 212 | 234 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -124,30 +124,40 @@ | |
| 124 | manifest_destroy(p); |
| 125 | db_end_transaction(0); |
| 126 | } |
| 127 | |
| 128 | /* |
| 129 | ** Check the file signature of the disk image for every VFILE of vid. |
| 130 | ** |
| 131 | ** Set the VFILE.CHNGED field on every file that has changed. Also |
| 132 | ** set VFILE.CHNGED on every folder that contains a file or folder |
| 133 | ** that has changed. |
| 134 | ** |
| 135 | ** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume |
| 136 | ** the file has changed without having the check the on-disk image. |
| 137 | ** |
| 138 | ** If the size of the file has changed, then we assume that it has |
| 139 | ** changed. If the mtime of the file has not changed and useSha1sum is false |
| 140 | ** and the mtime-changes setting is true (the default) then we assume that |
| 141 | ** the file has not changed. If the mtime has changed, we go ahead and |
| 142 | ** double-check that the file has changed by looking at its SHA1 sum. |
| 143 | */ |
| 144 | void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){ |
| 145 | int nErr = 0; |
| 146 | Stmt q; |
| 147 | Blob fileCksum, origCksum; |
| 148 | int checkMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1); |
| 149 | |
| 150 | db_begin_transaction(); |
| 151 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 152 | " vfile.mrid, deleted, chnged, uuid, size, mtime" |
| 153 | " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" |
| @@ -157,55 +167,67 @@ | |
| 157 | const char *zName; |
| 158 | int chnged = 0; |
| 159 | int oldChnged; |
| 160 | i64 oldMtime; |
| 161 | i64 currentMtime; |
| 162 | |
| 163 | id = db_column_int(&q, 0); |
| 164 | zName = db_column_text(&q, 1); |
| 165 | rid = db_column_int(&q, 2); |
| 166 | isDeleted = db_column_int(&q, 3); |
| 167 | oldChnged = db_column_int(&q, 4); |
| 168 | oldMtime = db_column_int64(&q, 7); |
| 169 | if( isDeleted ){ |
| 170 | chnged = 1; |
| 171 | }else if( !file_wd_isfile_or_link(zName) && file_wd_size(0)>=0 ){ |
| 172 | if( notFileIsFatal ){ |
| 173 | fossil_warning("not an ordinary file: %s", zName); |
| 174 | nErr++; |
| 175 | } |
| 176 | chnged = 1; |
| 177 | }else if( oldChnged>=2 ){ |
| 178 | chnged = oldChnged; |
| 179 | }else if( rid==0 ){ |
| 180 | chnged = 1; |
| 181 | } |
| 182 | if( chnged!=1 ){ |
| 183 | i64 origSize = db_column_int64(&q, 6); |
| 184 | currentMtime = file_wd_mtime(0); |
| 185 | if( origSize!=file_wd_size(0) ){ |
| 186 | /* A file size change is definitive - the file has changed. No |
| 187 | ** need to check the sha1sum */ |
| 188 | chnged = 1; |
| 189 | } |
| 190 | } |
| 191 | if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){ |
| 192 | db_ephemeral_blob(&q, 5, &origCksum); |
| 193 | if( sha1sum_file(zName, &fileCksum) ){ |
| 194 | blob_zero(&fileCksum); |
| 195 | } |
| 196 | if( blob_compare(&fileCksum, &origCksum) ){ |
| 197 | chnged = 1; |
| 198 | }else if( currentMtime!=oldMtime ){ |
| 199 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| 200 | currentMtime, id); |
| 201 | } |
| 202 | blob_reset(&origCksum); |
| 203 | blob_reset(&fileCksum); |
| 204 | } |
| 205 | if( chnged!=oldChnged && (chnged || !checkMtime) ){ |
| 206 | db_multi_exec("UPDATE vfile SET chnged=%d WHERE id=%d", chnged, id); |
| 207 | } |
| 208 | } |
| 209 | db_finalize(&q); |
| 210 | if( nErr ) fossil_fatal("abort due to prior errors"); |
| 211 | db_end_transaction(0); |
| 212 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -124,30 +124,40 @@ | |
| 124 | manifest_destroy(p); |
| 125 | db_end_transaction(0); |
| 126 | } |
| 127 | |
| 128 | /* |
| 129 | ** Look at every VFILE entry with the given vid and set update |
| 130 | ** VFILE.CHNGED field on every file according to whether or not |
| 131 | ** the file has changes. 0 means no change. 1 means edited. 2 means |
| 132 | ** the file has changed due to a merge. 3 means the file was added |
| 133 | ** by a merge. |
| 134 | ** |
| 135 | ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was |
| 136 | ** either removed from managemented via "fossil rm" or added via |
| 137 | ** "fossil add", respectively, and in both cases we always know that |
| 138 | ** the file has changed without having the check the size, mtime, |
| 139 | ** or on-disk content. |
| 140 | ** |
| 141 | ** If the size of the file has changed, then we always know that the file |
| 142 | ** changed without having to look at the mtime or on-disk content. |
| 143 | ** |
| 144 | ** The mtime of the file is only a factor if the mtime-changes setting |
| 145 | ** is false and the useSha1sum flag is false. If the mtime-changes |
| 146 | ** setting is true (or undefined - it defaults to true) or if useSha1sum |
| 147 | ** is true, then we do not trust the mtime and will examine the on-disk |
| 148 | ** content to determine if a file really is the same. |
| 149 | ** |
| 150 | ** If the mtime is used, it is used only to determine if files are the same. |
| 151 | ** If the mtime of a file has changed, we still examine the on-disk content |
| 152 | ** to see whether or not the edit was a null-edit. |
| 153 | */ |
| 154 | void vfile_check_signature(int vid, int notFileIsFatal, int useSha1sum){ |
| 155 | int nErr = 0; |
| 156 | Stmt q; |
| 157 | Blob fileCksum, origCksum; |
| 158 | int useMtime = useSha1sum==0 && db_get_boolean("mtime-changes", 1); |
| 159 | |
| 160 | db_begin_transaction(); |
| 161 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 162 | " vfile.mrid, deleted, chnged, uuid, size, mtime" |
| 163 | " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" |
| @@ -157,55 +167,67 @@ | |
| 167 | const char *zName; |
| 168 | int chnged = 0; |
| 169 | int oldChnged; |
| 170 | i64 oldMtime; |
| 171 | i64 currentMtime; |
| 172 | i64 origSize; |
| 173 | i64 currentSize; |
| 174 | |
| 175 | id = db_column_int(&q, 0); |
| 176 | zName = db_column_text(&q, 1); |
| 177 | rid = db_column_int(&q, 2); |
| 178 | isDeleted = db_column_int(&q, 3); |
| 179 | oldChnged = chnged = db_column_int(&q, 4); |
| 180 | oldMtime = db_column_int64(&q, 7); |
| 181 | currentSize = file_wd_size(zName); |
| 182 | origSize = db_column_int64(&q, 6); |
| 183 | currentMtime = file_wd_mtime(0); |
| 184 | if( chnged==0 && (isDeleted || rid==0) ){ |
| 185 | /* "fossil rm" or "fossil add" always change the file */ |
| 186 | chnged = 1; |
| 187 | }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){ |
| 188 | if( notFileIsFatal ){ |
| 189 | fossil_warning("not an ordinary file: %s", zName); |
| 190 | nErr++; |
| 191 | } |
| 192 | chnged = 1; |
| 193 | } |
| 194 | if( origSize!=currentSize ){ |
| 195 | if( chnged==0 ){ |
| 196 | /* A file size change is definitive - the file has changed. No |
| 197 | ** need to check the mtime or sha1sum */ |
| 198 | chnged = 1; |
| 199 | } |
| 200 | }else if( (chnged==1 || chnged==2) && rid!=0 && !isDeleted ){ |
| 201 | /* File is believed to have changed but it is the same size. |
| 202 | ** Double check that it really has changed by looking at content. */ |
| 203 | assert( origSize==currentSize ); |
| 204 | db_ephemeral_blob(&q, 5, &origCksum); |
| 205 | if( sha1sum_file(zName, &fileCksum) ){ |
| 206 | blob_zero(&fileCksum); |
| 207 | } |
| 208 | if( blob_compare(&fileCksum, &origCksum)==0 ) chnged = 0; |
| 209 | blob_reset(&origCksum); |
| 210 | blob_reset(&fileCksum); |
| 211 | }else if( chnged==0 && (useMtime==0 || currentMtime!=oldMtime) ){ |
| 212 | /* For files that were formerly believed to be unchanged, if their |
| 213 | ** mtime changes, or unconditionally if --sha1sum is used, check |
| 214 | ** to see if they have been edited by looking at their SHA1 sum */ |
| 215 | assert( origSize==currentSize ); |
| 216 | db_ephemeral_blob(&q, 5, &origCksum); |
| 217 | if( sha1sum_file(zName, &fileCksum) ){ |
| 218 | blob_zero(&fileCksum); |
| 219 | } |
| 220 | if( blob_compare(&fileCksum, &origCksum) ){ |
| 221 | chnged = 1; |
| 222 | } |
| 223 | blob_reset(&origCksum); |
| 224 | blob_reset(&fileCksum); |
| 225 | } |
| 226 | if( currentMtime!=oldMtime || chnged!=oldChnged ){ |
| 227 | db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d", |
| 228 | currentMtime, chnged, id); |
| 229 | } |
| 230 | } |
| 231 | db_finalize(&q); |
| 232 | if( nErr ) fossil_fatal("abort due to prior errors"); |
| 233 | db_end_transaction(0); |
| 234 |