Fossil SCM
Automatically update the VFILE and VMERGE tables when the fingerprinting detects that a repository has been replaced by clone.
Commit
b03652382a3277406e94d412e61e74683423e2042f1510f55277d6f27821261f
Parent
1a7cc2639c11436…
9 files changed
+2
-2
+12
-4
+3
-2
+56
-41
+2
-1
+10
-4
+2
-1
+2
-1
+130
-3
+2
-2
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -187,12 +187,12 @@ | ||
| 187 | 187 | zPath, filename_collation()); |
| 188 | 188 | }else{ |
| 189 | 189 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 190 | 190 | int isExe = file_isexe(zFullname, RepoFILE); |
| 191 | 191 | db_multi_exec( |
| 192 | - "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink)" | |
| 193 | - "VALUES(%d,0,0,0,%Q,%d,%d)", | |
| 192 | + "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" | |
| 193 | + "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", | |
| 194 | 194 | vid, zPath, isExe, file_islink(0)); |
| 195 | 195 | fossil_free(zFullname); |
| 196 | 196 | } |
| 197 | 197 | if( db_changes() ){ |
| 198 | 198 | fossil_print("ADDED %s\n", zPath); |
| 199 | 199 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -187,12 +187,12 @@ | |
| 187 | zPath, filename_collation()); |
| 188 | }else{ |
| 189 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 190 | int isExe = file_isexe(zFullname, RepoFILE); |
| 191 | db_multi_exec( |
| 192 | "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink)" |
| 193 | "VALUES(%d,0,0,0,%Q,%d,%d)", |
| 194 | vid, zPath, isExe, file_islink(0)); |
| 195 | fossil_free(zFullname); |
| 196 | } |
| 197 | if( db_changes() ){ |
| 198 | fossil_print("ADDED %s\n", zPath); |
| 199 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -187,12 +187,12 @@ | |
| 187 | zPath, filename_collation()); |
| 188 | }else{ |
| 189 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 190 | int isExe = file_isexe(zFullname, RepoFILE); |
| 191 | db_multi_exec( |
| 192 | "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" |
| 193 | "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", |
| 194 | vid, zPath, isExe, file_islink(0)); |
| 195 | fossil_free(zFullname); |
| 196 | } |
| 197 | if( db_changes() ){ |
| 198 | fossil_print("ADDED %s\n", zPath); |
| 199 |
+12
-4
| --- src/bisect.c | ||
| +++ src/bisect.c | ||
| @@ -286,10 +286,21 @@ | ||
| 286 | 286 | (db_column_int(&q, 4) && zGoodBad[0]!='C') ? " CURRENT" : ""); |
| 287 | 287 | } |
| 288 | 288 | db_finalize(&q); |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | + | |
| 292 | +/* | |
| 293 | +** Reset the bisect subsystem. | |
| 294 | +*/ | |
| 295 | +void bisect_reset(void){ | |
| 296 | + db_multi_exec( | |
| 297 | + "DELETE FROM vvar WHERE name IN " | |
| 298 | + " ('bisect-good', 'bisect-bad', 'bisect-log')" | |
| 299 | + ); | |
| 300 | +} | |
| 301 | + | |
| 291 | 302 | /* |
| 292 | 303 | ** COMMAND: bisect |
| 293 | 304 | ** |
| 294 | 305 | ** Usage: %fossil bisect SUBCOMMAND ... |
| 295 | 306 | ** |
| @@ -489,14 +500,11 @@ | ||
| 489 | 500 | } |
| 490 | 501 | }else{ |
| 491 | 502 | usage("options ?NAME? ?VALUE?"); |
| 492 | 503 | } |
| 493 | 504 | }else if( strncmp(zCmd, "reset", n)==0 ){ |
| 494 | - db_multi_exec( | |
| 495 | - "DELETE FROM vvar WHERE name IN " | |
| 496 | - " ('bisect-good', 'bisect-bad', 'bisect-log')" | |
| 497 | - ); | |
| 505 | + bisect_reset(); | |
| 498 | 506 | }else if( strcmp(zCmd, "ui")==0 ){ |
| 499 | 507 | char *newArgv[8]; |
| 500 | 508 | newArgv[0] = g.argv[0]; |
| 501 | 509 | newArgv[1] = "ui"; |
| 502 | 510 | newArgv[2] = "--page"; |
| 503 | 511 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -286,10 +286,21 @@ | |
| 286 | (db_column_int(&q, 4) && zGoodBad[0]!='C') ? " CURRENT" : ""); |
| 287 | } |
| 288 | db_finalize(&q); |
| 289 | } |
| 290 | |
| 291 | /* |
| 292 | ** COMMAND: bisect |
| 293 | ** |
| 294 | ** Usage: %fossil bisect SUBCOMMAND ... |
| 295 | ** |
| @@ -489,14 +500,11 @@ | |
| 489 | } |
| 490 | }else{ |
| 491 | usage("options ?NAME? ?VALUE?"); |
| 492 | } |
| 493 | }else if( strncmp(zCmd, "reset", n)==0 ){ |
| 494 | db_multi_exec( |
| 495 | "DELETE FROM vvar WHERE name IN " |
| 496 | " ('bisect-good', 'bisect-bad', 'bisect-log')" |
| 497 | ); |
| 498 | }else if( strcmp(zCmd, "ui")==0 ){ |
| 499 | char *newArgv[8]; |
| 500 | newArgv[0] = g.argv[0]; |
| 501 | newArgv[1] = "ui"; |
| 502 | newArgv[2] = "--page"; |
| 503 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -286,10 +286,21 @@ | |
| 286 | (db_column_int(&q, 4) && zGoodBad[0]!='C') ? " CURRENT" : ""); |
| 287 | } |
| 288 | db_finalize(&q); |
| 289 | } |
| 290 | |
| 291 | |
| 292 | /* |
| 293 | ** Reset the bisect subsystem. |
| 294 | */ |
| 295 | void bisect_reset(void){ |
| 296 | db_multi_exec( |
| 297 | "DELETE FROM vvar WHERE name IN " |
| 298 | " ('bisect-good', 'bisect-bad', 'bisect-log')" |
| 299 | ); |
| 300 | } |
| 301 | |
| 302 | /* |
| 303 | ** COMMAND: bisect |
| 304 | ** |
| 305 | ** Usage: %fossil bisect SUBCOMMAND ... |
| 306 | ** |
| @@ -489,14 +500,11 @@ | |
| 500 | } |
| 501 | }else{ |
| 502 | usage("options ?NAME? ?VALUE?"); |
| 503 | } |
| 504 | }else if( strncmp(zCmd, "reset", n)==0 ){ |
| 505 | bisect_reset(); |
| 506 | }else if( strcmp(zCmd, "ui")==0 ){ |
| 507 | char *newArgv[8]; |
| 508 | newArgv[0] = g.argv[0]; |
| 509 | newArgv[1] = "ui"; |
| 510 | newArgv[2] = "--page"; |
| 511 |
+3
-2
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -2398,11 +2398,12 @@ | ||
| 2398 | 2398 | nrid = content_put(&content); |
| 2399 | 2399 | blob_reset(&content); |
| 2400 | 2400 | if( rid>0 ){ |
| 2401 | 2401 | content_deltify(rid, &nrid, 1, 0); |
| 2402 | 2402 | } |
| 2403 | - db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id); | |
| 2403 | + db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d, mhash=NULL WHERE id=%d", | |
| 2404 | + nrid,nrid,id); | |
| 2404 | 2405 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); |
| 2405 | 2406 | } |
| 2406 | 2407 | db_finalize(&q); |
| 2407 | 2408 | if( nConflict && !allowConflict ){ |
| 2408 | 2409 | fossil_fatal("abort due to unresolved merge conflicts; " |
| @@ -2532,11 +2533,11 @@ | ||
| 2532 | 2533 | /* Update the vfile and vmerge tables */ |
| 2533 | 2534 | db_multi_exec( |
| 2534 | 2535 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 2535 | 2536 | "DELETE FROM vmerge;" |
| 2536 | 2537 | "UPDATE vfile SET vid=%d;" |
| 2537 | - "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL" | |
| 2538 | + "UPDATE vfile SET rid=mrid, mhash=NULL, chnged=0, deleted=0, origname=NULL" | |
| 2538 | 2539 | " WHERE is_selected(id);" |
| 2539 | 2540 | , vid, nvid |
| 2540 | 2541 | ); |
| 2541 | 2542 | db_set_checkout(nvid); |
| 2542 | 2543 | |
| 2543 | 2544 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -2398,11 +2398,12 @@ | |
| 2398 | nrid = content_put(&content); |
| 2399 | blob_reset(&content); |
| 2400 | if( rid>0 ){ |
| 2401 | content_deltify(rid, &nrid, 1, 0); |
| 2402 | } |
| 2403 | db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id); |
| 2404 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); |
| 2405 | } |
| 2406 | db_finalize(&q); |
| 2407 | if( nConflict && !allowConflict ){ |
| 2408 | fossil_fatal("abort due to unresolved merge conflicts; " |
| @@ -2532,11 +2533,11 @@ | |
| 2532 | /* Update the vfile and vmerge tables */ |
| 2533 | db_multi_exec( |
| 2534 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 2535 | "DELETE FROM vmerge;" |
| 2536 | "UPDATE vfile SET vid=%d;" |
| 2537 | "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL" |
| 2538 | " WHERE is_selected(id);" |
| 2539 | , vid, nvid |
| 2540 | ); |
| 2541 | db_set_checkout(nvid); |
| 2542 | |
| 2543 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -2398,11 +2398,12 @@ | |
| 2398 | nrid = content_put(&content); |
| 2399 | blob_reset(&content); |
| 2400 | if( rid>0 ){ |
| 2401 | content_deltify(rid, &nrid, 1, 0); |
| 2402 | } |
| 2403 | db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d, mhash=NULL WHERE id=%d", |
| 2404 | nrid,nrid,id); |
| 2405 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); |
| 2406 | } |
| 2407 | db_finalize(&q); |
| 2408 | if( nConflict && !allowConflict ){ |
| 2409 | fossil_fatal("abort due to unresolved merge conflicts; " |
| @@ -2532,11 +2533,11 @@ | |
| 2533 | /* Update the vfile and vmerge tables */ |
| 2534 | db_multi_exec( |
| 2535 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 2536 | "DELETE FROM vmerge;" |
| 2537 | "UPDATE vfile SET vid=%d;" |
| 2538 | "UPDATE vfile SET rid=mrid, mhash=NULL, chnged=0, deleted=0, origname=NULL" |
| 2539 | " WHERE is_selected(id);" |
| 2540 | , vid, nvid |
| 2541 | ); |
| 2542 | db_set_checkout(nvid); |
| 2543 | |
| 2544 |
M
src/db.c
+56
-41
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1674,55 +1674,70 @@ | ||
| 1674 | 1674 | rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */ |
| 1675 | 1675 | |
| 1676 | 1676 | /* Additional checks that occur when opening the checkout database */ |
| 1677 | 1677 | if( g.localOpen ){ |
| 1678 | 1678 | |
| 1679 | - /* Ensure that the repository database that was just opened has not | |
| 1680 | - ** be replaced by a clone of the same project, with different RID | |
| 1681 | - ** values. | |
| 1679 | + /* If the repository database that was just opened has been | |
| 1680 | + ** eplaced by a clone of the same project, with different RID | |
| 1681 | + ** values, then renumber the RID values stored in various tables | |
| 1682 | + ** of the checkout database, so that the repository and checkout | |
| 1683 | + ** databases align. | |
| 1682 | 1684 | */ |
| 1683 | 1685 | if( !db_fingerprint_ok() ){ |
| 1684 | - /* Uncomment the following when we are ready for automatic recovery: */ | |
| 1685 | -#if 0 | |
| 1686 | - stash_rid_renumbering_event(); | |
| 1687 | -#else | |
| 1688 | - fossil_print( | |
| 1689 | - "Oops. It looks like the repository database file located at\n" | |
| 1690 | - " \"%s\"\n", zDbName | |
| 1691 | - ); | |
| 1692 | - fossil_print( | |
| 1693 | - "has been swapped with a clone that may have different\n" | |
| 1694 | - "integer keys for the various artifacts. As of 2019-01-11,\n" | |
| 1695 | - "we are working on enhancing Fossil to be able to deal with\n" | |
| 1696 | - "that automatically, but we are not there yet. Sorry.\n\n" | |
| 1697 | - ); | |
| 1698 | - fossil_print( | |
| 1699 | - "As an interim workaround, try:\n" | |
| 1700 | - " %s close --force\n" | |
| 1701 | - " %s open \"%s\" --keep\n" | |
| 1702 | - "Noting that any STASH and UNDO information " | |
| 1703 | - "WILL BE IRREVOCABLY LOST.\n\n", | |
| 1704 | - g.argv[0], | |
| 1705 | - g.argv[0], zDbName | |
| 1706 | - ); | |
| 1707 | - fossil_fatal("bad fingerprint"); | |
| 1708 | -#endif | |
| 1709 | - }else | |
| 1710 | - | |
| 1711 | - /* Make sure the checkout database schema migration of 2019-01-19 | |
| 1712 | - ** (the addition of the vmerge.mhash column and making that columns | |
| 1713 | - ** part of the PRIMARY KEY) has occurred. | |
| 1686 | + if( find_option("no-rid-adjust",0,0)!=0 ){ | |
| 1687 | + /* The --no-rid-adjust command-line option bypasses the RID value | |
| 1688 | + ** updates. Intended for use during debugging, especially to be | |
| 1689 | + ** able to run "fossil sql" after a database swap. */ | |
| 1690 | + fossil_print( | |
| 1691 | + "WARNING: repository change detected, but no adjust made.\n" | |
| 1692 | + ); | |
| 1693 | + }else if( find_option("rid-renumber-dryrun",0,0)!=0 ){ | |
| 1694 | + /* the --rid-renumber-dryrun option shows how RID values would be | |
| 1695 | + ** renumbered, but does not actually perform the renumbering. | |
| 1696 | + ** This is a debugging-only option. */ | |
| 1697 | + vfile_rid_renumbering_event(1); | |
| 1698 | + exit(0); | |
| 1699 | + }else{ | |
| 1700 | + char *z; | |
| 1701 | + stash_rid_renumbering_event(); | |
| 1702 | + vfile_rid_renumbering_event(0); | |
| 1703 | + undo_reset(); | |
| 1704 | + bisect_reset(); | |
| 1705 | + z = db_fingerprint(0); | |
| 1706 | + db_lset("fingerprint", z); | |
| 1707 | + fossil_free(z); | |
| 1708 | + fossil_print( | |
| 1709 | + "WARNING: The repository database has been replaced by a clone.\n" | |
| 1710 | + "Bisect history and undo have been lost.\n" | |
| 1711 | + ); | |
| 1712 | + } | |
| 1713 | + } | |
| 1714 | + | |
| 1715 | + /* Make sure the checkout database schema migration of 2019-01-20 | |
| 1716 | + ** has occurred. | |
| 1717 | + ** | |
| 1718 | + ** The 2019-01-19 migration is the addition of the vmerge.mhash and | |
| 1719 | + ** vfile.mhash columns and making the vmerge.mhash column part of the | |
| 1720 | + ** PRIMARY KEY for vmerge. | |
| 1714 | 1721 | */ |
| 1715 | - if( !db_table_has_column("localdb", "vmerge", "mhash") ){ | |
| 1716 | - db_multi_exec("ALTER TABLE vmerge RENAME TO old_vmerge;"); | |
| 1717 | - db_multi_exec(zLocalSchemaVmerge /*works-like:""*/); | |
| 1718 | - db_multi_exec( | |
| 1719 | - "INSERT OR IGNORE INTO vmerge(id,merge,mhash)" | |
| 1720 | - " SELECT id, merge, blob.uuid FROM old_vmerge, blob" | |
| 1721 | - " WHERE old_vmerge.merge=blob.rid;" | |
| 1722 | - "DROP TABLE old_vmerge;" | |
| 1722 | + if( !db_table_has_column("localdb", "vfile", "mhash") ){ | |
| 1723 | + db_multi_exec("ALTER TABLE vfile ADD COLUMN mhash;"); | |
| 1724 | + db_multi_exec( | |
| 1725 | + "UPDATE vfile" | |
| 1726 | + " SET mhash=(SELECT uuid FROM blob WHERE blob.rid=vfile.mrid)" | |
| 1727 | + " WHERE mrid!=rid;" | |
| 1723 | 1728 | ); |
| 1729 | + if( !db_table_has_column("localdb", "vmerge", "mhash") ){ | |
| 1730 | + db_multi_exec("ALTER TABLE vmerge RENAME TO old_vmerge;"); | |
| 1731 | + db_multi_exec(zLocalSchemaVmerge /*works-like:""*/); | |
| 1732 | + db_multi_exec( | |
| 1733 | + "INSERT OR IGNORE INTO vmerge(id,merge,mhash)" | |
| 1734 | + " SELECT id, merge, blob.uuid FROM old_vmerge, blob" | |
| 1735 | + " WHERE old_vmerge.merge=blob.rid;" | |
| 1736 | + "DROP TABLE old_vmerge;" | |
| 1737 | + ); | |
| 1738 | + } | |
| 1724 | 1739 | } |
| 1725 | 1740 | } |
| 1726 | 1741 | } |
| 1727 | 1742 | |
| 1728 | 1743 | /* |
| 1729 | 1744 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1674,55 +1674,70 @@ | |
| 1674 | rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */ |
| 1675 | |
| 1676 | /* Additional checks that occur when opening the checkout database */ |
| 1677 | if( g.localOpen ){ |
| 1678 | |
| 1679 | /* Ensure that the repository database that was just opened has not |
| 1680 | ** be replaced by a clone of the same project, with different RID |
| 1681 | ** values. |
| 1682 | */ |
| 1683 | if( !db_fingerprint_ok() ){ |
| 1684 | /* Uncomment the following when we are ready for automatic recovery: */ |
| 1685 | #if 0 |
| 1686 | stash_rid_renumbering_event(); |
| 1687 | #else |
| 1688 | fossil_print( |
| 1689 | "Oops. It looks like the repository database file located at\n" |
| 1690 | " \"%s\"\n", zDbName |
| 1691 | ); |
| 1692 | fossil_print( |
| 1693 | "has been swapped with a clone that may have different\n" |
| 1694 | "integer keys for the various artifacts. As of 2019-01-11,\n" |
| 1695 | "we are working on enhancing Fossil to be able to deal with\n" |
| 1696 | "that automatically, but we are not there yet. Sorry.\n\n" |
| 1697 | ); |
| 1698 | fossil_print( |
| 1699 | "As an interim workaround, try:\n" |
| 1700 | " %s close --force\n" |
| 1701 | " %s open \"%s\" --keep\n" |
| 1702 | "Noting that any STASH and UNDO information " |
| 1703 | "WILL BE IRREVOCABLY LOST.\n\n", |
| 1704 | g.argv[0], |
| 1705 | g.argv[0], zDbName |
| 1706 | ); |
| 1707 | fossil_fatal("bad fingerprint"); |
| 1708 | #endif |
| 1709 | }else |
| 1710 | |
| 1711 | /* Make sure the checkout database schema migration of 2019-01-19 |
| 1712 | ** (the addition of the vmerge.mhash column and making that columns |
| 1713 | ** part of the PRIMARY KEY) has occurred. |
| 1714 | */ |
| 1715 | if( !db_table_has_column("localdb", "vmerge", "mhash") ){ |
| 1716 | db_multi_exec("ALTER TABLE vmerge RENAME TO old_vmerge;"); |
| 1717 | db_multi_exec(zLocalSchemaVmerge /*works-like:""*/); |
| 1718 | db_multi_exec( |
| 1719 | "INSERT OR IGNORE INTO vmerge(id,merge,mhash)" |
| 1720 | " SELECT id, merge, blob.uuid FROM old_vmerge, blob" |
| 1721 | " WHERE old_vmerge.merge=blob.rid;" |
| 1722 | "DROP TABLE old_vmerge;" |
| 1723 | ); |
| 1724 | } |
| 1725 | } |
| 1726 | } |
| 1727 | |
| 1728 | /* |
| 1729 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1674,55 +1674,70 @@ | |
| 1674 | rebuild_schema_update_2_0(); /* Do the Fossil-2.0 schema updates */ |
| 1675 | |
| 1676 | /* Additional checks that occur when opening the checkout database */ |
| 1677 | if( g.localOpen ){ |
| 1678 | |
| 1679 | /* If the repository database that was just opened has been |
| 1680 | ** eplaced by a clone of the same project, with different RID |
| 1681 | ** values, then renumber the RID values stored in various tables |
| 1682 | ** of the checkout database, so that the repository and checkout |
| 1683 | ** databases align. |
| 1684 | */ |
| 1685 | if( !db_fingerprint_ok() ){ |
| 1686 | if( find_option("no-rid-adjust",0,0)!=0 ){ |
| 1687 | /* The --no-rid-adjust command-line option bypasses the RID value |
| 1688 | ** updates. Intended for use during debugging, especially to be |
| 1689 | ** able to run "fossil sql" after a database swap. */ |
| 1690 | fossil_print( |
| 1691 | "WARNING: repository change detected, but no adjust made.\n" |
| 1692 | ); |
| 1693 | }else if( find_option("rid-renumber-dryrun",0,0)!=0 ){ |
| 1694 | /* the --rid-renumber-dryrun option shows how RID values would be |
| 1695 | ** renumbered, but does not actually perform the renumbering. |
| 1696 | ** This is a debugging-only option. */ |
| 1697 | vfile_rid_renumbering_event(1); |
| 1698 | exit(0); |
| 1699 | }else{ |
| 1700 | char *z; |
| 1701 | stash_rid_renumbering_event(); |
| 1702 | vfile_rid_renumbering_event(0); |
| 1703 | undo_reset(); |
| 1704 | bisect_reset(); |
| 1705 | z = db_fingerprint(0); |
| 1706 | db_lset("fingerprint", z); |
| 1707 | fossil_free(z); |
| 1708 | fossil_print( |
| 1709 | "WARNING: The repository database has been replaced by a clone.\n" |
| 1710 | "Bisect history and undo have been lost.\n" |
| 1711 | ); |
| 1712 | } |
| 1713 | } |
| 1714 | |
| 1715 | /* Make sure the checkout database schema migration of 2019-01-20 |
| 1716 | ** has occurred. |
| 1717 | ** |
| 1718 | ** The 2019-01-19 migration is the addition of the vmerge.mhash and |
| 1719 | ** vfile.mhash columns and making the vmerge.mhash column part of the |
| 1720 | ** PRIMARY KEY for vmerge. |
| 1721 | */ |
| 1722 | if( !db_table_has_column("localdb", "vfile", "mhash") ){ |
| 1723 | db_multi_exec("ALTER TABLE vfile ADD COLUMN mhash;"); |
| 1724 | db_multi_exec( |
| 1725 | "UPDATE vfile" |
| 1726 | " SET mhash=(SELECT uuid FROM blob WHERE blob.rid=vfile.mrid)" |
| 1727 | " WHERE mrid!=rid;" |
| 1728 | ); |
| 1729 | if( !db_table_has_column("localdb", "vmerge", "mhash") ){ |
| 1730 | db_multi_exec("ALTER TABLE vmerge RENAME TO old_vmerge;"); |
| 1731 | db_multi_exec(zLocalSchemaVmerge /*works-like:""*/); |
| 1732 | db_multi_exec( |
| 1733 | "INSERT OR IGNORE INTO vmerge(id,merge,mhash)" |
| 1734 | " SELECT id, merge, blob.uuid FROM old_vmerge, blob" |
| 1735 | " WHERE old_vmerge.merge=blob.rid;" |
| 1736 | "DROP TABLE old_vmerge;" |
| 1737 | ); |
| 1738 | } |
| 1739 | } |
| 1740 | } |
| 1741 | } |
| 1742 | |
| 1743 | /* |
| 1744 |
+2
-1
| --- src/foci.c | ||
| +++ src/foci.c | ||
| @@ -121,12 +121,13 @@ | ||
| 121 | 121 | ** (1) checkinID=?. visit only the single manifest specified. |
| 122 | 122 | ** (2) symName=? visit only the single manifest specified. |
| 123 | 123 | */ |
| 124 | 124 | static int fociBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ |
| 125 | 125 | int i; |
| 126 | - pIdxInfo->estimatedCost = 10000.0; | |
| 126 | + pIdxInfo->estimatedCost = 1000000000.0; | |
| 127 | 127 | for(i=0; i<pIdxInfo->nConstraint; i++){ |
| 128 | + if( !pIdxInfo->aConstraint[i].usable ) continue; | |
| 128 | 129 | if( pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ |
| 129 | 130 | && (pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID |
| 130 | 131 | || pIdxInfo->aConstraint[i].iColumn==FOCI_SYMNAME) |
| 131 | 132 | ){ |
| 132 | 133 | if( pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID ){ |
| 133 | 134 |
| --- src/foci.c | |
| +++ src/foci.c | |
| @@ -121,12 +121,13 @@ | |
| 121 | ** (1) checkinID=?. visit only the single manifest specified. |
| 122 | ** (2) symName=? visit only the single manifest specified. |
| 123 | */ |
| 124 | static int fociBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ |
| 125 | int i; |
| 126 | pIdxInfo->estimatedCost = 10000.0; |
| 127 | for(i=0; i<pIdxInfo->nConstraint; i++){ |
| 128 | if( pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ |
| 129 | && (pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID |
| 130 | || pIdxInfo->aConstraint[i].iColumn==FOCI_SYMNAME) |
| 131 | ){ |
| 132 | if( pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID ){ |
| 133 |
| --- src/foci.c | |
| +++ src/foci.c | |
| @@ -121,12 +121,13 @@ | |
| 121 | ** (1) checkinID=?. visit only the single manifest specified. |
| 122 | ** (2) symName=? visit only the single manifest specified. |
| 123 | */ |
| 124 | static int fociBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ |
| 125 | int i; |
| 126 | pIdxInfo->estimatedCost = 1000000000.0; |
| 127 | for(i=0; i<pIdxInfo->nConstraint; i++){ |
| 128 | if( !pIdxInfo->aConstraint[i].usable ) continue; |
| 129 | if( pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ |
| 130 | && (pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID |
| 131 | || pIdxInfo->aConstraint[i].iColumn==FOCI_SYMNAME) |
| 132 | ){ |
| 133 | if( pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID ){ |
| 134 |
+10
-4
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -604,12 +604,14 @@ | ||
| 604 | 604 | /* Copy content from idm over into idv. Overwrite idv. */ |
| 605 | 605 | fossil_print("UPDATE %s\n", zName); |
| 606 | 606 | if( !dryRunFlag ){ |
| 607 | 607 | undo_save(zName); |
| 608 | 608 | db_multi_exec( |
| 609 | - "UPDATE vfile SET mtime=0, mrid=%d, chnged=%d, islink=%d " | |
| 610 | - " WHERE id=%d", ridm, integrateFlag?4:2, islinkm, idv | |
| 609 | + "UPDATE vfile SET mtime=0, mrid=%d, chnged=%d, islink=%d," | |
| 610 | + " mhash=CASE WHEN rid<>%d" | |
| 611 | + " THEN (SELECT uuid FROM blob WHERE blob.rid=%d) END" | |
| 612 | + " WHERE id=%d", ridm, integrateFlag?4:2, islinkm, ridm, ridm, idv | |
| 611 | 613 | ); |
| 612 | 614 | vfile_to_disk(0, idv, 0, 0); |
| 613 | 615 | } |
| 614 | 616 | } |
| 615 | 617 | db_finalize(&q); |
| @@ -795,12 +797,16 @@ | ||
| 795 | 797 | while( db_step(&q)==SQLITE_ROW ){ |
| 796 | 798 | int idm = db_column_int(&q, 0); |
| 797 | 799 | const char *zName; |
| 798 | 800 | char *zFullName; |
| 799 | 801 | db_multi_exec( |
| 800 | - "REPLACE INTO vfile(vid,chnged,deleted,rid,mrid,isexe,islink,pathname)" | |
| 801 | - " SELECT %d,%d,0,rid,mrid,isexe,islink,pathname FROM vfile WHERE id=%d", | |
| 802 | + "REPLACE INTO vfile(vid,chnged,deleted,rid,mrid," | |
| 803 | + "isexe,islink,pathname,mhash)" | |
| 804 | + " SELECT %d,%d,0,rid,mrid,isexe,islink,pathname," | |
| 805 | + "CASE WHEN rid<>mrid" | |
| 806 | + " THEN (SELECT uuid FROM blob WHERE blob.rid=vfile.mrid) END " | |
| 807 | + "FROM vfile WHERE id=%d", | |
| 802 | 808 | vid, integrateFlag?5:3, idm |
| 803 | 809 | ); |
| 804 | 810 | zName = db_column_text(&q, 1); |
| 805 | 811 | zFullName = mprintf("%s%s", g.zLocalRoot, zName); |
| 806 | 812 | if( file_isfile_or_link(zFullName) |
| 807 | 813 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -604,12 +604,14 @@ | |
| 604 | /* Copy content from idm over into idv. Overwrite idv. */ |
| 605 | fossil_print("UPDATE %s\n", zName); |
| 606 | if( !dryRunFlag ){ |
| 607 | undo_save(zName); |
| 608 | db_multi_exec( |
| 609 | "UPDATE vfile SET mtime=0, mrid=%d, chnged=%d, islink=%d " |
| 610 | " WHERE id=%d", ridm, integrateFlag?4:2, islinkm, idv |
| 611 | ); |
| 612 | vfile_to_disk(0, idv, 0, 0); |
| 613 | } |
| 614 | } |
| 615 | db_finalize(&q); |
| @@ -795,12 +797,16 @@ | |
| 795 | while( db_step(&q)==SQLITE_ROW ){ |
| 796 | int idm = db_column_int(&q, 0); |
| 797 | const char *zName; |
| 798 | char *zFullName; |
| 799 | db_multi_exec( |
| 800 | "REPLACE INTO vfile(vid,chnged,deleted,rid,mrid,isexe,islink,pathname)" |
| 801 | " SELECT %d,%d,0,rid,mrid,isexe,islink,pathname FROM vfile WHERE id=%d", |
| 802 | vid, integrateFlag?5:3, idm |
| 803 | ); |
| 804 | zName = db_column_text(&q, 1); |
| 805 | zFullName = mprintf("%s%s", g.zLocalRoot, zName); |
| 806 | if( file_isfile_or_link(zFullName) |
| 807 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -604,12 +604,14 @@ | |
| 604 | /* Copy content from idm over into idv. Overwrite idv. */ |
| 605 | fossil_print("UPDATE %s\n", zName); |
| 606 | if( !dryRunFlag ){ |
| 607 | undo_save(zName); |
| 608 | db_multi_exec( |
| 609 | "UPDATE vfile SET mtime=0, mrid=%d, chnged=%d, islink=%d," |
| 610 | " mhash=CASE WHEN rid<>%d" |
| 611 | " THEN (SELECT uuid FROM blob WHERE blob.rid=%d) END" |
| 612 | " WHERE id=%d", ridm, integrateFlag?4:2, islinkm, ridm, ridm, idv |
| 613 | ); |
| 614 | vfile_to_disk(0, idv, 0, 0); |
| 615 | } |
| 616 | } |
| 617 | db_finalize(&q); |
| @@ -795,12 +797,16 @@ | |
| 797 | while( db_step(&q)==SQLITE_ROW ){ |
| 798 | int idm = db_column_int(&q, 0); |
| 799 | const char *zName; |
| 800 | char *zFullName; |
| 801 | db_multi_exec( |
| 802 | "REPLACE INTO vfile(vid,chnged,deleted,rid,mrid," |
| 803 | "isexe,islink,pathname,mhash)" |
| 804 | " SELECT %d,%d,0,rid,mrid,isexe,islink,pathname," |
| 805 | "CASE WHEN rid<>mrid" |
| 806 | " THEN (SELECT uuid FROM blob WHERE blob.rid=vfile.mrid) END " |
| 807 | "FROM vfile WHERE id=%d", |
| 808 | vid, integrateFlag?5:3, idm |
| 809 | ); |
| 810 | zName = db_column_text(&q, 1); |
| 811 | zFullName = mprintf("%s%s", g.zLocalRoot, zName); |
| 812 | if( file_isfile_or_link(zFullName) |
| 813 |
+2
-1
| --- src/schema.c | ||
| +++ src/schema.c | ||
| @@ -534,10 +534,11 @@ | ||
| 534 | 534 | @ rid INTEGER, -- Originally from this repository record |
| 535 | 535 | @ mrid INTEGER, -- Based on this record due to a merge |
| 536 | 536 | @ mtime INTEGER, -- Mtime of file on disk. sec since 1970 |
| 537 | 537 | @ pathname TEXT, -- Full pathname relative to root |
| 538 | 538 | @ origname TEXT, -- Original pathname. NULL if unchanged |
| 539 | +@ mhash TEXT, -- Hash of mrid iff mrid!=rid | |
| 539 | 540 | @ UNIQUE(pathname,vid) |
| 540 | 541 | @ ); |
| 541 | 542 | @ |
| 542 | 543 | @ -- Identifier for this file type. |
| 543 | 544 | @ -- The integer is the same as 'FSLC'. |
| @@ -544,11 +545,11 @@ | ||
| 544 | 545 | @ PRAGMA application_id=252006674; |
| 545 | 546 | ; |
| 546 | 547 | |
| 547 | 548 | /* Additional local database initialization following the schema |
| 548 | 549 | ** enhancement of 2019-01-19, in which the mhash column was added |
| 549 | -** to vmerge. | |
| 550 | +** to vmerge and vfile. | |
| 550 | 551 | */ |
| 551 | 552 | const char zLocalSchemaVmerge[] = |
| 552 | 553 | @ -- This table holds a record of uncommitted merges in the local |
| 553 | 554 | @ -- file tree. If a VFILE entry with id has merged with another |
| 554 | 555 | @ -- record, there is an entry in this table with (id,merge) where |
| 555 | 556 |
| --- src/schema.c | |
| +++ src/schema.c | |
| @@ -534,10 +534,11 @@ | |
| 534 | @ rid INTEGER, -- Originally from this repository record |
| 535 | @ mrid INTEGER, -- Based on this record due to a merge |
| 536 | @ mtime INTEGER, -- Mtime of file on disk. sec since 1970 |
| 537 | @ pathname TEXT, -- Full pathname relative to root |
| 538 | @ origname TEXT, -- Original pathname. NULL if unchanged |
| 539 | @ UNIQUE(pathname,vid) |
| 540 | @ ); |
| 541 | @ |
| 542 | @ -- Identifier for this file type. |
| 543 | @ -- The integer is the same as 'FSLC'. |
| @@ -544,11 +545,11 @@ | |
| 544 | @ PRAGMA application_id=252006674; |
| 545 | ; |
| 546 | |
| 547 | /* Additional local database initialization following the schema |
| 548 | ** enhancement of 2019-01-19, in which the mhash column was added |
| 549 | ** to vmerge. |
| 550 | */ |
| 551 | const char zLocalSchemaVmerge[] = |
| 552 | @ -- This table holds a record of uncommitted merges in the local |
| 553 | @ -- file tree. If a VFILE entry with id has merged with another |
| 554 | @ -- record, there is an entry in this table with (id,merge) where |
| 555 |
| --- src/schema.c | |
| +++ src/schema.c | |
| @@ -534,10 +534,11 @@ | |
| 534 | @ rid INTEGER, -- Originally from this repository record |
| 535 | @ mrid INTEGER, -- Based on this record due to a merge |
| 536 | @ mtime INTEGER, -- Mtime of file on disk. sec since 1970 |
| 537 | @ pathname TEXT, -- Full pathname relative to root |
| 538 | @ origname TEXT, -- Original pathname. NULL if unchanged |
| 539 | @ mhash TEXT, -- Hash of mrid iff mrid!=rid |
| 540 | @ UNIQUE(pathname,vid) |
| 541 | @ ); |
| 542 | @ |
| 543 | @ -- Identifier for this file type. |
| 544 | @ -- The integer is the same as 'FSLC'. |
| @@ -544,11 +545,11 @@ | |
| 545 | @ PRAGMA application_id=252006674; |
| 546 | ; |
| 547 | |
| 548 | /* Additional local database initialization following the schema |
| 549 | ** enhancement of 2019-01-19, in which the mhash column was added |
| 550 | ** to vmerge and vfile. |
| 551 | */ |
| 552 | const char zLocalSchemaVmerge[] = |
| 553 | @ -- This table holds a record of uncommitted merges in the local |
| 554 | @ -- file tree. If a VFILE entry with id has merged with another |
| 555 | @ -- record, there is an entry in this table with (id,merge) where |
| 556 |
+2
-1
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -864,11 +864,12 @@ | ||
| 864 | 864 | file_setexe(zFull, rvPerm==PERM_EXE); |
| 865 | 865 | fossil_print("REVERT %s\n", zFile); |
| 866 | 866 | mtime = file_mtime(zFull, RepoFILE); |
| 867 | 867 | db_multi_exec( |
| 868 | 868 | "UPDATE vfile" |
| 869 | - " SET mtime=%lld, chnged=%d, deleted=0, isexe=%d, islink=%d,mrid=rid" | |
| 869 | + " SET mtime=%lld, chnged=%d, deleted=0, isexe=%d, islink=%d," | |
| 870 | + " mrid=rid, mhash=NULL" | |
| 870 | 871 | " WHERE pathname=%Q OR origname=%Q", |
| 871 | 872 | mtime, rvChnged, rvPerm==PERM_EXE, rvPerm==PERM_LNK, zFile, zFile |
| 872 | 873 | ); |
| 873 | 874 | } |
| 874 | 875 | blob_reset(&record); |
| 875 | 876 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -864,11 +864,12 @@ | |
| 864 | file_setexe(zFull, rvPerm==PERM_EXE); |
| 865 | fossil_print("REVERT %s\n", zFile); |
| 866 | mtime = file_mtime(zFull, RepoFILE); |
| 867 | db_multi_exec( |
| 868 | "UPDATE vfile" |
| 869 | " SET mtime=%lld, chnged=%d, deleted=0, isexe=%d, islink=%d,mrid=rid" |
| 870 | " WHERE pathname=%Q OR origname=%Q", |
| 871 | mtime, rvChnged, rvPerm==PERM_EXE, rvPerm==PERM_LNK, zFile, zFile |
| 872 | ); |
| 873 | } |
| 874 | blob_reset(&record); |
| 875 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -864,11 +864,12 @@ | |
| 864 | file_setexe(zFull, rvPerm==PERM_EXE); |
| 865 | fossil_print("REVERT %s\n", zFile); |
| 866 | mtime = file_mtime(zFull, RepoFILE); |
| 867 | db_multi_exec( |
| 868 | "UPDATE vfile" |
| 869 | " SET mtime=%lld, chnged=%d, deleted=0, isexe=%d, islink=%d," |
| 870 | " mrid=rid, mhash=NULL" |
| 871 | " WHERE pathname=%Q OR origname=%Q", |
| 872 | mtime, rvChnged, rvPerm==PERM_EXE, rvPerm==PERM_LNK, zFile, zFile |
| 873 | ); |
| 874 | } |
| 875 | blob_reset(&record); |
| 876 |
+130
-3
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -88,12 +88,12 @@ | ||
| 88 | 88 | if( p==0 ) { |
| 89 | 89 | db_end_transaction(1); |
| 90 | 90 | return 0; |
| 91 | 91 | } |
| 92 | 92 | db_prepare(&ins, |
| 93 | - "INSERT INTO vfile(vid,isexe,islink,rid,mrid,pathname) " | |
| 94 | - " VALUES(:vid,:isexe,:islink,:id,:id,:name)"); | |
| 93 | + "INSERT INTO vfile(vid,isexe,islink,rid,mrid,pathname,mhash) " | |
| 94 | + " VALUES(:vid,:isexe,:islink,:id,:id,:name,NULL)"); | |
| 95 | 95 | db_prepare(&ridq, "SELECT rid,size FROM blob WHERE uuid=:uuid"); |
| 96 | 96 | db_bind_int(&ins, ":vid", vid); |
| 97 | 97 | manifest_file_rewind(p); |
| 98 | 98 | nMissing = 0; |
| 99 | 99 | while( (pFile = manifest_file_next(p,0))!=0 ){ |
| @@ -242,11 +242,11 @@ | ||
| 242 | 242 | const char *zUuid = db_column_text(&q, 5); |
| 243 | 243 | int nUuid = db_column_bytes(&q, 5); |
| 244 | 244 | assert( origSize==currentSize ); |
| 245 | 245 | if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1; |
| 246 | 246 | } |
| 247 | - if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4) ){ | |
| 247 | + if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4)){ | |
| 248 | 248 | i64 desiredMtime; |
| 249 | 249 | if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){ |
| 250 | 250 | if( currentMtime!=desiredMtime ){ |
| 251 | 251 | file_set_mtime(zName, desiredMtime); |
| 252 | 252 | currentMtime = file_mtime(zName, RepoFILE); |
| @@ -966,5 +966,132 @@ | ||
| 966 | 966 | blob_reset(&hash); |
| 967 | 967 | vfile_aggregate_checksum_manifest(vid, &hash, &hash2); |
| 968 | 968 | printf("manifest: %s\n", blob_str(&hash)); |
| 969 | 969 | printf("recorded: %s\n", blob_str(&hash2)); |
| 970 | 970 | } |
| 971 | + | |
| 972 | +/* | |
| 973 | +** This routine recomputes certain columns of the vfile and vmerge tables | |
| 974 | +** when the associated repository is swapped out for a clone of the same | |
| 975 | +** project, and the blob.rid value change. The following columns are | |
| 976 | +** updated: | |
| 977 | +** | |
| 978 | +** vmerge.merge | |
| 979 | +** vfile.vid | |
| 980 | +** vfile.rid | |
| 981 | +** vfile.mrid | |
| 982 | +** | |
| 983 | +** Also: | |
| 984 | +** | |
| 985 | +** vvar.value WHERE name='checkout' | |
| 986 | +*/ | |
| 987 | +void vfile_rid_renumbering_event(int dryRun){ | |
| 988 | + int oldVid; | |
| 989 | + int newVid; | |
| 990 | + char *zUnresolved; | |
| 991 | + | |
| 992 | + oldVid = db_lget_int("checkout", 0); | |
| 993 | + newVid = db_int(0, "SELECT blob.rid FROM blob, vvar" | |
| 994 | + " WHERE blob.uuid=vvar.value" | |
| 995 | + " AND vvar.name='checkout-hash'"); | |
| 996 | + | |
| 997 | + /* The idMap table will make old RID values into new ones */ | |
| 998 | + db_multi_exec( | |
| 999 | + "CREATE TEMP TABLE idMap(oldrid INTEGER PRIMARY KEY, newrid INT);\n" | |
| 1000 | + ); | |
| 1001 | + | |
| 1002 | + /* Add the RID value for the current check-out */ | |
| 1003 | + db_multi_exec( | |
| 1004 | + "INSERT INTO idMap(oldrid, newrid) VALUES(%d,%d)", | |
| 1005 | + oldVid, newVid | |
| 1006 | + ); | |
| 1007 | + | |
| 1008 | + /* Add the RID values for any other check-ins that have been merged into | |
| 1009 | + ** the current check-out. */ | |
| 1010 | + db_multi_exec( | |
| 1011 | + "INSERT OR IGNORE INTO idMap(oldrid, newrid)" | |
| 1012 | + " SELECT vmerge.merge, blob.rid FROM vmerge, blob" | |
| 1013 | + " WHERE blob.uuid=vmerge.mhash;" | |
| 1014 | + ); | |
| 1015 | + | |
| 1016 | + /* Add RID values for files in the current check-out */ | |
| 1017 | + db_multi_exec( | |
| 1018 | + "CREATE TEMP TABLE hashoffile(name TEXT PRIMARY KEY, hash TEXT)" | |
| 1019 | + "WITHOUT ROWID;" | |
| 1020 | + | |
| 1021 | + "INSERT INTO hashoffile(name,hash)" | |
| 1022 | + " SELECT filename, uuid FROM vvar, files_of_checkin(vvar.value)" | |
| 1023 | + " WHERE vvar.name='checkout-hash';" | |
| 1024 | + | |
| 1025 | + "INSERT OR IGNORE INTO idMap(oldrid, newrid)" | |
| 1026 | + " SELECT vfile.rid, blob.rid FROM vfile, hashoffile, blob" | |
| 1027 | + " WHERE hashoffile.name=coalesce(vfile.origname,vfile.pathname)" | |
| 1028 | + " AND blob.uuid=hashoffile.hash;" | |
| 1029 | + ); | |
| 1030 | + | |
| 1031 | + /* Add RID values for merged-in files */ | |
| 1032 | + db_multi_exec( | |
| 1033 | + "INSERT OR IGNORE INTO idMap(oldrid, newrid)" | |
| 1034 | + " SELECT vfile.mrid, blob.rid FROM vfile, blob" | |
| 1035 | + " WHERE blob.uuid=vfile.mhash;" | |
| 1036 | + ); | |
| 1037 | + | |
| 1038 | + if( dryRun ){ | |
| 1039 | + Stmt q; | |
| 1040 | + db_prepare(&q, "SELECT oldrid, newrid, blob.uuid" | |
| 1041 | + " FROM idMap, blob WHERE blob.rid=idMap.newrid"); | |
| 1042 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 1043 | + fossil_print("%8d -> %8d %.25s\n", | |
| 1044 | + db_column_int(&q,0), | |
| 1045 | + db_column_int(&q,1), | |
| 1046 | + db_column_text(&q,2)); | |
| 1047 | + } | |
| 1048 | + db_finalize(&q); | |
| 1049 | + } | |
| 1050 | + | |
| 1051 | + /* Verify that all RID values in the VFILE table and VMERGE table have | |
| 1052 | + ** been resolved. */ | |
| 1053 | + zUnresolved = db_text("", | |
| 1054 | + "WITH allrid(x) AS (" | |
| 1055 | + " SELECT rid FROM vfile" | |
| 1056 | + " UNION SELECT mrid FROM vfile" | |
| 1057 | + " UNION SELECT merge FROM vmerge" | |
| 1058 | + " UNION SELECT %d" | |
| 1059 | + ")" | |
| 1060 | + "SELECT group_concat(x,' ') FROM allrid" | |
| 1061 | + " WHERE x NOT IN (SELECT oldrid FROM idMap);", | |
| 1062 | + oldVid | |
| 1063 | + ); | |
| 1064 | + if( zUnresolved[0] ){ | |
| 1065 | + fossil_fatal("Unresolved RID values: %s\n", zUnresolved); | |
| 1066 | + } | |
| 1067 | + | |
| 1068 | + /* Make the changes to the VFILE and VMERGE tables */ | |
| 1069 | + if( !dryRun ){ | |
| 1070 | + db_multi_exec( | |
| 1071 | + "UPDATE vfile" | |
| 1072 | + " SET rid=(SELECT newrid FROM idMap WHERE oldrid=vfile.rid)" | |
| 1073 | + " WHERE vid=%d AND rid>0;", oldVid); | |
| 1074 | + | |
| 1075 | + db_multi_exec( | |
| 1076 | + "UPDATE vfile" | |
| 1077 | + " SET mrid=(SELECT newrid FROM idMap WHERE oldrid=vfile.mrid)" | |
| 1078 | + " WHERE vid=%d AND mrid>0;", oldVid); | |
| 1079 | + | |
| 1080 | + db_multi_exec( | |
| 1081 | + "UPDATE vfile" | |
| 1082 | + " SET vid=%d" | |
| 1083 | + " WHERE vid=%d", newVid, oldVid); | |
| 1084 | + | |
| 1085 | + db_multi_exec( | |
| 1086 | + "UPDATE vmerge" | |
| 1087 | + " SET merge=(SELECT newrid FROM idMap WHERE oldrid=vmerge.merge);"); | |
| 1088 | + | |
| 1089 | + db_lset_int("checkout",newVid); | |
| 1090 | + } | |
| 1091 | + | |
| 1092 | + /* Clear out the TEMP tables we constructed */ | |
| 1093 | + db_multi_exec( | |
| 1094 | + "DROP TABLE idMap;" | |
| 1095 | + "DROP TABLE hashoffile;" | |
| 1096 | + ); | |
| 1097 | +} | |
| 971 | 1098 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -88,12 +88,12 @@ | |
| 88 | if( p==0 ) { |
| 89 | db_end_transaction(1); |
| 90 | return 0; |
| 91 | } |
| 92 | db_prepare(&ins, |
| 93 | "INSERT INTO vfile(vid,isexe,islink,rid,mrid,pathname) " |
| 94 | " VALUES(:vid,:isexe,:islink,:id,:id,:name)"); |
| 95 | db_prepare(&ridq, "SELECT rid,size FROM blob WHERE uuid=:uuid"); |
| 96 | db_bind_int(&ins, ":vid", vid); |
| 97 | manifest_file_rewind(p); |
| 98 | nMissing = 0; |
| 99 | while( (pFile = manifest_file_next(p,0))!=0 ){ |
| @@ -242,11 +242,11 @@ | |
| 242 | const char *zUuid = db_column_text(&q, 5); |
| 243 | int nUuid = db_column_bytes(&q, 5); |
| 244 | assert( origSize==currentSize ); |
| 245 | if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1; |
| 246 | } |
| 247 | if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4) ){ |
| 248 | i64 desiredMtime; |
| 249 | if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){ |
| 250 | if( currentMtime!=desiredMtime ){ |
| 251 | file_set_mtime(zName, desiredMtime); |
| 252 | currentMtime = file_mtime(zName, RepoFILE); |
| @@ -966,5 +966,132 @@ | |
| 966 | blob_reset(&hash); |
| 967 | vfile_aggregate_checksum_manifest(vid, &hash, &hash2); |
| 968 | printf("manifest: %s\n", blob_str(&hash)); |
| 969 | printf("recorded: %s\n", blob_str(&hash2)); |
| 970 | } |
| 971 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -88,12 +88,12 @@ | |
| 88 | if( p==0 ) { |
| 89 | db_end_transaction(1); |
| 90 | return 0; |
| 91 | } |
| 92 | db_prepare(&ins, |
| 93 | "INSERT INTO vfile(vid,isexe,islink,rid,mrid,pathname,mhash) " |
| 94 | " VALUES(:vid,:isexe,:islink,:id,:id,:name,NULL)"); |
| 95 | db_prepare(&ridq, "SELECT rid,size FROM blob WHERE uuid=:uuid"); |
| 96 | db_bind_int(&ins, ":vid", vid); |
| 97 | manifest_file_rewind(p); |
| 98 | nMissing = 0; |
| 99 | while( (pFile = manifest_file_next(p,0))!=0 ){ |
| @@ -242,11 +242,11 @@ | |
| 242 | const char *zUuid = db_column_text(&q, 5); |
| 243 | int nUuid = db_column_bytes(&q, 5); |
| 244 | assert( origSize==currentSize ); |
| 245 | if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1; |
| 246 | } |
| 247 | if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4)){ |
| 248 | i64 desiredMtime; |
| 249 | if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){ |
| 250 | if( currentMtime!=desiredMtime ){ |
| 251 | file_set_mtime(zName, desiredMtime); |
| 252 | currentMtime = file_mtime(zName, RepoFILE); |
| @@ -966,5 +966,132 @@ | |
| 966 | blob_reset(&hash); |
| 967 | vfile_aggregate_checksum_manifest(vid, &hash, &hash2); |
| 968 | printf("manifest: %s\n", blob_str(&hash)); |
| 969 | printf("recorded: %s\n", blob_str(&hash2)); |
| 970 | } |
| 971 | |
| 972 | /* |
| 973 | ** This routine recomputes certain columns of the vfile and vmerge tables |
| 974 | ** when the associated repository is swapped out for a clone of the same |
| 975 | ** project, and the blob.rid value change. The following columns are |
| 976 | ** updated: |
| 977 | ** |
| 978 | ** vmerge.merge |
| 979 | ** vfile.vid |
| 980 | ** vfile.rid |
| 981 | ** vfile.mrid |
| 982 | ** |
| 983 | ** Also: |
| 984 | ** |
| 985 | ** vvar.value WHERE name='checkout' |
| 986 | */ |
| 987 | void vfile_rid_renumbering_event(int dryRun){ |
| 988 | int oldVid; |
| 989 | int newVid; |
| 990 | char *zUnresolved; |
| 991 | |
| 992 | oldVid = db_lget_int("checkout", 0); |
| 993 | newVid = db_int(0, "SELECT blob.rid FROM blob, vvar" |
| 994 | " WHERE blob.uuid=vvar.value" |
| 995 | " AND vvar.name='checkout-hash'"); |
| 996 | |
| 997 | /* The idMap table will make old RID values into new ones */ |
| 998 | db_multi_exec( |
| 999 | "CREATE TEMP TABLE idMap(oldrid INTEGER PRIMARY KEY, newrid INT);\n" |
| 1000 | ); |
| 1001 | |
| 1002 | /* Add the RID value for the current check-out */ |
| 1003 | db_multi_exec( |
| 1004 | "INSERT INTO idMap(oldrid, newrid) VALUES(%d,%d)", |
| 1005 | oldVid, newVid |
| 1006 | ); |
| 1007 | |
| 1008 | /* Add the RID values for any other check-ins that have been merged into |
| 1009 | ** the current check-out. */ |
| 1010 | db_multi_exec( |
| 1011 | "INSERT OR IGNORE INTO idMap(oldrid, newrid)" |
| 1012 | " SELECT vmerge.merge, blob.rid FROM vmerge, blob" |
| 1013 | " WHERE blob.uuid=vmerge.mhash;" |
| 1014 | ); |
| 1015 | |
| 1016 | /* Add RID values for files in the current check-out */ |
| 1017 | db_multi_exec( |
| 1018 | "CREATE TEMP TABLE hashoffile(name TEXT PRIMARY KEY, hash TEXT)" |
| 1019 | "WITHOUT ROWID;" |
| 1020 | |
| 1021 | "INSERT INTO hashoffile(name,hash)" |
| 1022 | " SELECT filename, uuid FROM vvar, files_of_checkin(vvar.value)" |
| 1023 | " WHERE vvar.name='checkout-hash';" |
| 1024 | |
| 1025 | "INSERT OR IGNORE INTO idMap(oldrid, newrid)" |
| 1026 | " SELECT vfile.rid, blob.rid FROM vfile, hashoffile, blob" |
| 1027 | " WHERE hashoffile.name=coalesce(vfile.origname,vfile.pathname)" |
| 1028 | " AND blob.uuid=hashoffile.hash;" |
| 1029 | ); |
| 1030 | |
| 1031 | /* Add RID values for merged-in files */ |
| 1032 | db_multi_exec( |
| 1033 | "INSERT OR IGNORE INTO idMap(oldrid, newrid)" |
| 1034 | " SELECT vfile.mrid, blob.rid FROM vfile, blob" |
| 1035 | " WHERE blob.uuid=vfile.mhash;" |
| 1036 | ); |
| 1037 | |
| 1038 | if( dryRun ){ |
| 1039 | Stmt q; |
| 1040 | db_prepare(&q, "SELECT oldrid, newrid, blob.uuid" |
| 1041 | " FROM idMap, blob WHERE blob.rid=idMap.newrid"); |
| 1042 | while( db_step(&q)==SQLITE_ROW ){ |
| 1043 | fossil_print("%8d -> %8d %.25s\n", |
| 1044 | db_column_int(&q,0), |
| 1045 | db_column_int(&q,1), |
| 1046 | db_column_text(&q,2)); |
| 1047 | } |
| 1048 | db_finalize(&q); |
| 1049 | } |
| 1050 | |
| 1051 | /* Verify that all RID values in the VFILE table and VMERGE table have |
| 1052 | ** been resolved. */ |
| 1053 | zUnresolved = db_text("", |
| 1054 | "WITH allrid(x) AS (" |
| 1055 | " SELECT rid FROM vfile" |
| 1056 | " UNION SELECT mrid FROM vfile" |
| 1057 | " UNION SELECT merge FROM vmerge" |
| 1058 | " UNION SELECT %d" |
| 1059 | ")" |
| 1060 | "SELECT group_concat(x,' ') FROM allrid" |
| 1061 | " WHERE x NOT IN (SELECT oldrid FROM idMap);", |
| 1062 | oldVid |
| 1063 | ); |
| 1064 | if( zUnresolved[0] ){ |
| 1065 | fossil_fatal("Unresolved RID values: %s\n", zUnresolved); |
| 1066 | } |
| 1067 | |
| 1068 | /* Make the changes to the VFILE and VMERGE tables */ |
| 1069 | if( !dryRun ){ |
| 1070 | db_multi_exec( |
| 1071 | "UPDATE vfile" |
| 1072 | " SET rid=(SELECT newrid FROM idMap WHERE oldrid=vfile.rid)" |
| 1073 | " WHERE vid=%d AND rid>0;", oldVid); |
| 1074 | |
| 1075 | db_multi_exec( |
| 1076 | "UPDATE vfile" |
| 1077 | " SET mrid=(SELECT newrid FROM idMap WHERE oldrid=vfile.mrid)" |
| 1078 | " WHERE vid=%d AND mrid>0;", oldVid); |
| 1079 | |
| 1080 | db_multi_exec( |
| 1081 | "UPDATE vfile" |
| 1082 | " SET vid=%d" |
| 1083 | " WHERE vid=%d", newVid, oldVid); |
| 1084 | |
| 1085 | db_multi_exec( |
| 1086 | "UPDATE vmerge" |
| 1087 | " SET merge=(SELECT newrid FROM idMap WHERE oldrid=vmerge.merge);"); |
| 1088 | |
| 1089 | db_lset_int("checkout",newVid); |
| 1090 | } |
| 1091 | |
| 1092 | /* Clear out the TEMP tables we constructed */ |
| 1093 | db_multi_exec( |
| 1094 | "DROP TABLE idMap;" |
| 1095 | "DROP TABLE hashoffile;" |
| 1096 | ); |
| 1097 | } |
| 1098 |