Fossil SCM
Enhance the "fossil rebuild" command so that it looks at "private" --raw tags and rebuilds the PRIVATE table to contain (at least) the content that is tagged "private".
Commit
2f98f6603143a32547a4b9c238478f7d49d0e8f4
Parent
fe99188e60b4b82…
2 files changed
+17
-9
+22
-15
+17
-9
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -20,18 +20,20 @@ | ||
| 20 | 20 | #include "config.h" |
| 21 | 21 | #include "clone.h" |
| 22 | 22 | #include <assert.h> |
| 23 | 23 | |
| 24 | 24 | /* |
| 25 | -** Delete all private content from a repository. | |
| 25 | +** If there are public BLOBs that deltas from private BLOBs, then | |
| 26 | +** undeltify the public BLOBs so that the private BLOBs may be safely | |
| 27 | +** deleted. | |
| 26 | 28 | */ |
| 27 | -void delete_private_content(void){ | |
| 29 | +void fix_private_blob_dependencies(int showWarning){ | |
| 28 | 30 | Bag toUndelta; |
| 29 | 31 | Stmt q; |
| 30 | 32 | int rid; |
| 31 | 33 | |
| 32 | - /* Carefule: We are about to delete all BLOB entries that are private. | |
| 34 | + /* Careful: We are about to delete all BLOB entries that are private. | |
| 33 | 35 | ** So make sure that any no public BLOBs are deltas from a private BLOB. |
| 34 | 36 | ** Otherwise after the deletion, we won't be able to recreate the public |
| 35 | 37 | ** BLOBs. |
| 36 | 38 | */ |
| 37 | 39 | db_prepare(&q, |
| @@ -45,25 +47,31 @@ | ||
| 45 | 47 | while( db_step(&q)==SQLITE_ROW ){ |
| 46 | 48 | int rid = db_column_int(&q, 0); |
| 47 | 49 | const char *zId = db_column_text(&q, 1); |
| 48 | 50 | int srcid = db_column_int(&q, 2); |
| 49 | 51 | const char *zSrc = db_column_text(&q, 3); |
| 50 | - fossil_warning( | |
| 51 | - "public artifact %S (%d) is a delta from private artifact %S (%d)\n", | |
| 52 | - zId, rid, zSrc, srcid | |
| 53 | - ); | |
| 52 | + if( showWarning ){ | |
| 53 | + fossil_warning( | |
| 54 | + "public artifact %S (%d) is a delta from private artifact %S (%d)", | |
| 55 | + zId, rid, zSrc, srcid | |
| 56 | + ); | |
| 57 | + } | |
| 54 | 58 | bag_insert(&toUndelta, rid); |
| 55 | 59 | } |
| 56 | 60 | db_finalize(&q); |
| 57 | 61 | while( (rid = bag_first(&toUndelta))>0 ){ |
| 58 | 62 | content_undelta(rid); |
| 59 | 63 | bag_remove(&toUndelta, rid); |
| 60 | 64 | } |
| 61 | 65 | bag_clear(&toUndelta); |
| 66 | +} | |
| 62 | 67 | |
| 63 | - /* Now it is safe to remove all private content | |
| 64 | - */ | |
| 68 | +/* | |
| 69 | +** Delete all private content from a repository. | |
| 70 | +*/ | |
| 71 | +void delete_private_content(void){ | |
| 72 | + fix_private_blob_dependencies(1); | |
| 65 | 73 | db_multi_exec( |
| 66 | 74 | "DELETE FROM blob WHERE rid IN private;" |
| 67 | 75 | "DELETE FROM delta wHERE rid IN private;" |
| 68 | 76 | "DELETE FROM private;" |
| 69 | 77 | ); |
| 70 | 78 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -20,18 +20,20 @@ | |
| 20 | #include "config.h" |
| 21 | #include "clone.h" |
| 22 | #include <assert.h> |
| 23 | |
| 24 | /* |
| 25 | ** Delete all private content from a repository. |
| 26 | */ |
| 27 | void delete_private_content(void){ |
| 28 | Bag toUndelta; |
| 29 | Stmt q; |
| 30 | int rid; |
| 31 | |
| 32 | /* Carefule: We are about to delete all BLOB entries that are private. |
| 33 | ** So make sure that any no public BLOBs are deltas from a private BLOB. |
| 34 | ** Otherwise after the deletion, we won't be able to recreate the public |
| 35 | ** BLOBs. |
| 36 | */ |
| 37 | db_prepare(&q, |
| @@ -45,25 +47,31 @@ | |
| 45 | while( db_step(&q)==SQLITE_ROW ){ |
| 46 | int rid = db_column_int(&q, 0); |
| 47 | const char *zId = db_column_text(&q, 1); |
| 48 | int srcid = db_column_int(&q, 2); |
| 49 | const char *zSrc = db_column_text(&q, 3); |
| 50 | fossil_warning( |
| 51 | "public artifact %S (%d) is a delta from private artifact %S (%d)\n", |
| 52 | zId, rid, zSrc, srcid |
| 53 | ); |
| 54 | bag_insert(&toUndelta, rid); |
| 55 | } |
| 56 | db_finalize(&q); |
| 57 | while( (rid = bag_first(&toUndelta))>0 ){ |
| 58 | content_undelta(rid); |
| 59 | bag_remove(&toUndelta, rid); |
| 60 | } |
| 61 | bag_clear(&toUndelta); |
| 62 | |
| 63 | /* Now it is safe to remove all private content |
| 64 | */ |
| 65 | db_multi_exec( |
| 66 | "DELETE FROM blob WHERE rid IN private;" |
| 67 | "DELETE FROM delta wHERE rid IN private;" |
| 68 | "DELETE FROM private;" |
| 69 | ); |
| 70 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -20,18 +20,20 @@ | |
| 20 | #include "config.h" |
| 21 | #include "clone.h" |
| 22 | #include <assert.h> |
| 23 | |
| 24 | /* |
| 25 | ** If there are public BLOBs that deltas from private BLOBs, then |
| 26 | ** undeltify the public BLOBs so that the private BLOBs may be safely |
| 27 | ** deleted. |
| 28 | */ |
| 29 | void fix_private_blob_dependencies(int showWarning){ |
| 30 | Bag toUndelta; |
| 31 | Stmt q; |
| 32 | int rid; |
| 33 | |
| 34 | /* Careful: We are about to delete all BLOB entries that are private. |
| 35 | ** So make sure that any no public BLOBs are deltas from a private BLOB. |
| 36 | ** Otherwise after the deletion, we won't be able to recreate the public |
| 37 | ** BLOBs. |
| 38 | */ |
| 39 | db_prepare(&q, |
| @@ -45,25 +47,31 @@ | |
| 47 | while( db_step(&q)==SQLITE_ROW ){ |
| 48 | int rid = db_column_int(&q, 0); |
| 49 | const char *zId = db_column_text(&q, 1); |
| 50 | int srcid = db_column_int(&q, 2); |
| 51 | const char *zSrc = db_column_text(&q, 3); |
| 52 | if( showWarning ){ |
| 53 | fossil_warning( |
| 54 | "public artifact %S (%d) is a delta from private artifact %S (%d)", |
| 55 | zId, rid, zSrc, srcid |
| 56 | ); |
| 57 | } |
| 58 | bag_insert(&toUndelta, rid); |
| 59 | } |
| 60 | db_finalize(&q); |
| 61 | while( (rid = bag_first(&toUndelta))>0 ){ |
| 62 | content_undelta(rid); |
| 63 | bag_remove(&toUndelta, rid); |
| 64 | } |
| 65 | bag_clear(&toUndelta); |
| 66 | } |
| 67 | |
| 68 | /* |
| 69 | ** Delete all private content from a repository. |
| 70 | */ |
| 71 | void delete_private_content(void){ |
| 72 | fix_private_blob_dependencies(1); |
| 73 | db_multi_exec( |
| 74 | "DELETE FROM blob WHERE rid IN private;" |
| 75 | "DELETE FROM delta wHERE rid IN private;" |
| 76 | "DELETE FROM private;" |
| 77 | ); |
| 78 |
+22
-15
| --- src/rebuild.c | ||
| +++ src/rebuild.c | ||
| @@ -485,10 +485,30 @@ | ||
| 485 | 485 | } |
| 486 | 486 | db_finalize(&q); |
| 487 | 487 | |
| 488 | 488 | db_end_transaction(0); |
| 489 | 489 | } |
| 490 | + | |
| 491 | + | |
| 492 | +/* Reconstruct the private table. The private table contains the rid | |
| 493 | +** of every manifest that is tagged with "private" and every file that | |
| 494 | +** is not used by a manifest that is not private. | |
| 495 | +*/ | |
| 496 | +static void reconstruct_private_table(void){ | |
| 497 | + db_multi_exec( | |
| 498 | + "CREATE TEMP TABLE private_ckin(rid INTEGER PRIMARY KEY);" | |
| 499 | + "INSERT INTO private_ckin " | |
| 500 | + " SELECT rid FROM tagxref WHERE tagid=%d AND tagtype>0;" | |
| 501 | + "INSERT OR IGNORE INTO private" | |
| 502 | + " SELECT fid FROM mlink" | |
| 503 | + " EXCEPT SELECT fid FROM mlink WHERE mid NOT IN private_ckin;" | |
| 504 | + "INSERT OR IGNORE INTO private SELECT rid FROM private_ckin;" | |
| 505 | + "DROP TABLE private_ckin;", TAG_PRIVATE | |
| 506 | + ); | |
| 507 | + fix_private_blob_dependencies(0); | |
| 508 | +} | |
| 509 | + | |
| 490 | 510 | |
| 491 | 511 | /* |
| 492 | 512 | ** COMMAND: rebuild |
| 493 | 513 | ** |
| 494 | 514 | ** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS? |
| @@ -551,10 +571,11 @@ | ||
| 551 | 571 | db_open_repository(g.zRepositoryName); |
| 552 | 572 | } |
| 553 | 573 | db_begin_transaction(); |
| 554 | 574 | ttyOutput = 1; |
| 555 | 575 | errCnt = rebuild_db(randomizeFlag, 1, doClustering); |
| 576 | + reconstruct_private_table(); | |
| 556 | 577 | db_multi_exec( |
| 557 | 578 | "REPLACE INTO config(name,value,mtime) VALUES('content-schema','%s',now());" |
| 558 | 579 | "REPLACE INTO config(name,value,mtime) VALUES('aux-schema','%s',now());", |
| 559 | 580 | CONTENT_SCHEMA, AUX_SCHEMA |
| 560 | 581 | ); |
| @@ -881,25 +902,11 @@ | ||
| 881 | 902 | fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]); |
| 882 | 903 | recon_read_dir(g.argv[3]); |
| 883 | 904 | fossil_print("\nBuilding the Fossil repository...\n"); |
| 884 | 905 | |
| 885 | 906 | rebuild_db(0, 1, 1); |
| 886 | - | |
| 887 | - /* Reconstruct the private table. The private table contains the rid | |
| 888 | - ** of every manifest that is tagged with "private" and every file that | |
| 889 | - ** is not used by a manifest that is not private. | |
| 890 | - */ | |
| 891 | - db_multi_exec( | |
| 892 | - "CREATE TEMP TABLE private_ckin(rid INTEGER PRIMARY KEY);" | |
| 893 | - "INSERT INTO private_ckin " | |
| 894 | - " SELECT rid FROM tagxref WHERE tagid=%d AND tagtype>0;" | |
| 895 | - "INSERT OR IGNORE INTO private" | |
| 896 | - " SELECT fid FROM mlink" | |
| 897 | - " EXCEPT SELECT fid FROM mlink WHERE mid NOT IN private_ckin;" | |
| 898 | - "INSERT OR IGNORE INTO private SELECT rid FROM private_ckin;" | |
| 899 | - "DROP TABLE private_ckin;" | |
| 900 | - ); | |
| 907 | + reconstruct_private_table(); | |
| 901 | 908 | |
| 902 | 909 | /* Skip the verify_before_commit() step on a reconstruct. Most artifacts |
| 903 | 910 | ** will have been changed and verification therefore takes a really, really |
| 904 | 911 | ** long time. |
| 905 | 912 | */ |
| 906 | 913 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -485,10 +485,30 @@ | |
| 485 | } |
| 486 | db_finalize(&q); |
| 487 | |
| 488 | db_end_transaction(0); |
| 489 | } |
| 490 | |
| 491 | /* |
| 492 | ** COMMAND: rebuild |
| 493 | ** |
| 494 | ** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS? |
| @@ -551,10 +571,11 @@ | |
| 551 | db_open_repository(g.zRepositoryName); |
| 552 | } |
| 553 | db_begin_transaction(); |
| 554 | ttyOutput = 1; |
| 555 | errCnt = rebuild_db(randomizeFlag, 1, doClustering); |
| 556 | db_multi_exec( |
| 557 | "REPLACE INTO config(name,value,mtime) VALUES('content-schema','%s',now());" |
| 558 | "REPLACE INTO config(name,value,mtime) VALUES('aux-schema','%s',now());", |
| 559 | CONTENT_SCHEMA, AUX_SCHEMA |
| 560 | ); |
| @@ -881,25 +902,11 @@ | |
| 881 | fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]); |
| 882 | recon_read_dir(g.argv[3]); |
| 883 | fossil_print("\nBuilding the Fossil repository...\n"); |
| 884 | |
| 885 | rebuild_db(0, 1, 1); |
| 886 | |
| 887 | /* Reconstruct the private table. The private table contains the rid |
| 888 | ** of every manifest that is tagged with "private" and every file that |
| 889 | ** is not used by a manifest that is not private. |
| 890 | */ |
| 891 | db_multi_exec( |
| 892 | "CREATE TEMP TABLE private_ckin(rid INTEGER PRIMARY KEY);" |
| 893 | "INSERT INTO private_ckin " |
| 894 | " SELECT rid FROM tagxref WHERE tagid=%d AND tagtype>0;" |
| 895 | "INSERT OR IGNORE INTO private" |
| 896 | " SELECT fid FROM mlink" |
| 897 | " EXCEPT SELECT fid FROM mlink WHERE mid NOT IN private_ckin;" |
| 898 | "INSERT OR IGNORE INTO private SELECT rid FROM private_ckin;" |
| 899 | "DROP TABLE private_ckin;" |
| 900 | ); |
| 901 | |
| 902 | /* Skip the verify_before_commit() step on a reconstruct. Most artifacts |
| 903 | ** will have been changed and verification therefore takes a really, really |
| 904 | ** long time. |
| 905 | */ |
| 906 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -485,10 +485,30 @@ | |
| 485 | } |
| 486 | db_finalize(&q); |
| 487 | |
| 488 | db_end_transaction(0); |
| 489 | } |
| 490 | |
| 491 | |
| 492 | /* Reconstruct the private table. The private table contains the rid |
| 493 | ** of every manifest that is tagged with "private" and every file that |
| 494 | ** is not used by a manifest that is not private. |
| 495 | */ |
| 496 | static void reconstruct_private_table(void){ |
| 497 | db_multi_exec( |
| 498 | "CREATE TEMP TABLE private_ckin(rid INTEGER PRIMARY KEY);" |
| 499 | "INSERT INTO private_ckin " |
| 500 | " SELECT rid FROM tagxref WHERE tagid=%d AND tagtype>0;" |
| 501 | "INSERT OR IGNORE INTO private" |
| 502 | " SELECT fid FROM mlink" |
| 503 | " EXCEPT SELECT fid FROM mlink WHERE mid NOT IN private_ckin;" |
| 504 | "INSERT OR IGNORE INTO private SELECT rid FROM private_ckin;" |
| 505 | "DROP TABLE private_ckin;", TAG_PRIVATE |
| 506 | ); |
| 507 | fix_private_blob_dependencies(0); |
| 508 | } |
| 509 | |
| 510 | |
| 511 | /* |
| 512 | ** COMMAND: rebuild |
| 513 | ** |
| 514 | ** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS? |
| @@ -551,10 +571,11 @@ | |
| 571 | db_open_repository(g.zRepositoryName); |
| 572 | } |
| 573 | db_begin_transaction(); |
| 574 | ttyOutput = 1; |
| 575 | errCnt = rebuild_db(randomizeFlag, 1, doClustering); |
| 576 | reconstruct_private_table(); |
| 577 | db_multi_exec( |
| 578 | "REPLACE INTO config(name,value,mtime) VALUES('content-schema','%s',now());" |
| 579 | "REPLACE INTO config(name,value,mtime) VALUES('aux-schema','%s',now());", |
| 580 | CONTENT_SCHEMA, AUX_SCHEMA |
| 581 | ); |
| @@ -881,25 +902,11 @@ | |
| 902 | fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]); |
| 903 | recon_read_dir(g.argv[3]); |
| 904 | fossil_print("\nBuilding the Fossil repository...\n"); |
| 905 | |
| 906 | rebuild_db(0, 1, 1); |
| 907 | reconstruct_private_table(); |
| 908 | |
| 909 | /* Skip the verify_before_commit() step on a reconstruct. Most artifacts |
| 910 | ** will have been changed and verification therefore takes a really, really |
| 911 | ** long time. |
| 912 | */ |
| 913 |