Fossil SCM
On a "tree checksum does not match repository" error on a commit, go back and do a file-by-file comparison of the repository and the working checkout to try to discover what the problem is. Ticket [a483f0ab3f0d4da0].
Commit
64459dd091f4913dda561700b892938b11124556
Parent
f7cf6dd7ba8ad2f…
2 files changed
+1
+47
+1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -1059,10 +1059,11 @@ | ||
| 1059 | 1059 | ** calculated before the checkin started (and stored as the R record |
| 1060 | 1060 | ** of the manifest file). |
| 1061 | 1061 | */ |
| 1062 | 1062 | vfile_aggregate_checksum_repository(nvid, &cksum2); |
| 1063 | 1063 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1064 | + vfile_compare_repository_to_disk(nvid); | |
| 1064 | 1065 | fossil_panic("tree checksum does not match repository after commit"); |
| 1065 | 1066 | } |
| 1066 | 1067 | |
| 1067 | 1068 | /* Verify that the manifest checksum matches the expected checksum */ |
| 1068 | 1069 | vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); |
| 1069 | 1070 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1059,10 +1059,11 @@ | |
| 1059 | ** calculated before the checkin started (and stored as the R record |
| 1060 | ** of the manifest file). |
| 1061 | */ |
| 1062 | vfile_aggregate_checksum_repository(nvid, &cksum2); |
| 1063 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1064 | fossil_panic("tree checksum does not match repository after commit"); |
| 1065 | } |
| 1066 | |
| 1067 | /* Verify that the manifest checksum matches the expected checksum */ |
| 1068 | vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); |
| 1069 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1059,10 +1059,11 @@ | |
| 1059 | ** calculated before the checkin started (and stored as the R record |
| 1060 | ** of the manifest file). |
| 1061 | */ |
| 1062 | vfile_aggregate_checksum_repository(nvid, &cksum2); |
| 1063 | if( blob_compare(&cksum1, &cksum2) ){ |
| 1064 | vfile_compare_repository_to_disk(nvid); |
| 1065 | fossil_panic("tree checksum does not match repository after commit"); |
| 1066 | } |
| 1067 | |
| 1068 | /* Verify that the manifest checksum matches the expected checksum */ |
| 1069 | vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); |
| 1070 |
+47
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -387,10 +387,57 @@ | ||
| 387 | 387 | } |
| 388 | 388 | } |
| 389 | 389 | db_finalize(&q); |
| 390 | 390 | md5sum_finish(pOut); |
| 391 | 391 | } |
| 392 | + | |
| 393 | +/* | |
| 394 | +** Do a file-by-file comparison of the content of the repository and | |
| 395 | +** the working check-out on disk. Report any errors. | |
| 396 | +*/ | |
| 397 | +void vfile_compare_repository_to_disk(int vid){ | |
| 398 | + int rc; | |
| 399 | + Stmt q; | |
| 400 | + Blob disk, repo; | |
| 401 | + | |
| 402 | + db_must_be_within_tree(); | |
| 403 | + db_prepare(&q, | |
| 404 | + "SELECT %Q || pathname, pathname, rid FROM vfile" | |
| 405 | + " WHERE NOT deleted AND vid=%d AND file_is_selected(id)", | |
| 406 | + g.zLocalRoot, vid | |
| 407 | + ); | |
| 408 | + md5sum_init(); | |
| 409 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 410 | + const char *zFullpath = db_column_text(&q, 0); | |
| 411 | + const char *zName = db_column_text(&q, 1); | |
| 412 | + int rid = db_column_int(&q, 2); | |
| 413 | + | |
| 414 | + blob_zero(&disk); | |
| 415 | + rc = blob_read_from_file(&disk, zFullpath); | |
| 416 | + if( rc<0 ){ | |
| 417 | + printf("ERROR: cannot read file [%s]\n", zFullpath); | |
| 418 | + blob_reset(&disk); | |
| 419 | + continue; | |
| 420 | + } | |
| 421 | + blob_zero(&repo); | |
| 422 | + content_get(rid, &repo); | |
| 423 | + if( blob_size(&repo)!=blob_size(&disk) ){ | |
| 424 | + printf("ERROR: [%s] is %d bytes on disk but %d in the repository\n", | |
| 425 | + zName, blob_size(&disk), blob_size(&repo)); | |
| 426 | + blob_reset(&disk); | |
| 427 | + blob_reset(&repo); | |
| 428 | + continue; | |
| 429 | + } | |
| 430 | + if( blob_compare(&repo, &disk) ){ | |
| 431 | + printf("ERROR: [%s] is different on disk compared to the repository\n", | |
| 432 | + zName); | |
| 433 | + } | |
| 434 | + blob_reset(&disk); | |
| 435 | + blob_reset(&repo); | |
| 436 | + } | |
| 437 | + db_finalize(&q); | |
| 438 | +} | |
| 392 | 439 | |
| 393 | 440 | /* |
| 394 | 441 | ** Compute an aggregate MD5 checksum over the repository image of every |
| 395 | 442 | ** file in vid. The file names are part of the checksum. |
| 396 | 443 | ** |
| 397 | 444 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -387,10 +387,57 @@ | |
| 387 | } |
| 388 | } |
| 389 | db_finalize(&q); |
| 390 | md5sum_finish(pOut); |
| 391 | } |
| 392 | |
| 393 | /* |
| 394 | ** Compute an aggregate MD5 checksum over the repository image of every |
| 395 | ** file in vid. The file names are part of the checksum. |
| 396 | ** |
| 397 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -387,10 +387,57 @@ | |
| 387 | } |
| 388 | } |
| 389 | db_finalize(&q); |
| 390 | md5sum_finish(pOut); |
| 391 | } |
| 392 | |
| 393 | /* |
| 394 | ** Do a file-by-file comparison of the content of the repository and |
| 395 | ** the working check-out on disk. Report any errors. |
| 396 | */ |
| 397 | void vfile_compare_repository_to_disk(int vid){ |
| 398 | int rc; |
| 399 | Stmt q; |
| 400 | Blob disk, repo; |
| 401 | |
| 402 | db_must_be_within_tree(); |
| 403 | db_prepare(&q, |
| 404 | "SELECT %Q || pathname, pathname, rid FROM vfile" |
| 405 | " WHERE NOT deleted AND vid=%d AND file_is_selected(id)", |
| 406 | g.zLocalRoot, vid |
| 407 | ); |
| 408 | md5sum_init(); |
| 409 | while( db_step(&q)==SQLITE_ROW ){ |
| 410 | const char *zFullpath = db_column_text(&q, 0); |
| 411 | const char *zName = db_column_text(&q, 1); |
| 412 | int rid = db_column_int(&q, 2); |
| 413 | |
| 414 | blob_zero(&disk); |
| 415 | rc = blob_read_from_file(&disk, zFullpath); |
| 416 | if( rc<0 ){ |
| 417 | printf("ERROR: cannot read file [%s]\n", zFullpath); |
| 418 | blob_reset(&disk); |
| 419 | continue; |
| 420 | } |
| 421 | blob_zero(&repo); |
| 422 | content_get(rid, &repo); |
| 423 | if( blob_size(&repo)!=blob_size(&disk) ){ |
| 424 | printf("ERROR: [%s] is %d bytes on disk but %d in the repository\n", |
| 425 | zName, blob_size(&disk), blob_size(&repo)); |
| 426 | blob_reset(&disk); |
| 427 | blob_reset(&repo); |
| 428 | continue; |
| 429 | } |
| 430 | if( blob_compare(&repo, &disk) ){ |
| 431 | printf("ERROR: [%s] is different on disk compared to the repository\n", |
| 432 | zName); |
| 433 | } |
| 434 | blob_reset(&disk); |
| 435 | blob_reset(&repo); |
| 436 | } |
| 437 | db_finalize(&q); |
| 438 | } |
| 439 | |
| 440 | /* |
| 441 | ** Compute an aggregate MD5 checksum over the repository image of every |
| 442 | ** file in vid. The file names are part of the checksum. |
| 443 | ** |
| 444 |