diff options
author | Sybren A. Stüvel <sybren@blender.org> | 2021-10-12 12:28:16 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@blender.org> | 2021-10-12 12:28:16 +0300 |
commit | ad1735f8ede966b7d49423928ad05cca25119949 (patch) | |
tree | 27c351114b6f66ef50418445fb35e16c9edbf6e1 /source | |
parent | ac657bee0142f96fcd3fa5d56455658834a19b19 (diff) |
Asset Catalogs: recursive deletion of catalogs & children
Recursively delete asset catalogs with `AssetCatalogService:prune_...`
functions. This deletes the catalog and all of its children.
The old `delete_catalog` function has been renamed to
`delete_catalog_by_id()`, and is now a lower-level function (no deletion
of children, no rebuilding of the tree). The `prune_catalogs_by_path()`
and `prune_catalogs_by_id()` do delete children and do rebuild the
catalog tree.
Manifest task: T91634
Diffstat (limited to 'source')
4 files changed, 100 insertions, 9 deletions
diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh index bd18fdf1d6e..4ea6abd65e0 100644 --- a/source/blender/blenkernel/BKE_asset_catalog.hh +++ b/source/blender/blenkernel/BKE_asset_catalog.hh @@ -117,9 +117,21 @@ class AssetCatalogService { AssetCatalog *create_catalog(const AssetCatalogPath &catalog_path); /** - * Soft-delete the catalog, ensuring it actually gets deleted when the catalog definition file is - * written. */ - void delete_catalog(CatalogID catalog_id); + * Delete all catalogs with the given path, and their children. + */ + void prune_catalogs_by_path(const AssetCatalogPath &path); + + /** + * Delete all catalogs with the same path as the identified catalog, and their children. + * This call is the same as calling `prune_catalogs_by_path(find_catalog(catalog_id)->path)`. + */ + void prune_catalogs_by_id(CatalogID catalog_id); + + /** + * Delete a catalog, without deleting any of its children and without rebuilding the catalog + * tree. This is a lower-level function than #prune_catalogs_by_path. + */ + void delete_catalog_by_id(CatalogID catalog_id); /** * Update the catalog path, also updating the catalog path of all sub-catalogs. diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc index ab7d8eafb8b..4531dabf0cf 100644 --- a/source/blender/blenkernel/intern/asset_catalog.cc +++ b/source/blender/blenkernel/intern/asset_catalog.cc @@ -112,7 +112,7 @@ AssetCatalogFilter AssetCatalogService::create_catalog_filter( return AssetCatalogFilter(std::move(matching_catalog_ids)); } -void AssetCatalogService::delete_catalog(CatalogID catalog_id) +void AssetCatalogService::delete_catalog_by_id(const CatalogID catalog_id) { std::unique_ptr<AssetCatalog> *catalog_uptr_ptr = this->catalogs_.lookup_ptr(catalog_id); if (catalog_uptr_ptr == nullptr) { @@ -129,11 +129,38 @@ void AssetCatalogService::delete_catalog(CatalogID catalog_id) /* The catalog can now be removed from the map without freeing the actual AssetCatalog. */ this->catalogs_.remove(catalog_id); +} + +void AssetCatalogService::prune_catalogs_by_path(const AssetCatalogPath &path) +{ + /* Build a collection of catalog IDs to delete. */ + Set<CatalogID> catalogs_to_delete; + for (const auto &catalog_uptr : this->catalogs_.values()) { + const AssetCatalog *cat = catalog_uptr.get(); + if (cat->path.is_contained_in(path)) { + catalogs_to_delete.add(cat->catalog_id); + } + } + + /* Delete the catalogs. */ + for (const CatalogID cat_id : catalogs_to_delete) { + this->delete_catalog_by_id(cat_id); + } this->rebuild_tree(); } -void AssetCatalogService::update_catalog_path(CatalogID catalog_id, +void AssetCatalogService::prune_catalogs_by_id(const CatalogID catalog_id) +{ + const AssetCatalog *catalog = find_catalog(catalog_id); + BLI_assert_msg(catalog, "trying to prune asset catalogs by the path of a non-existent catalog"); + if (!catalog) { + return; + } + this->prune_catalogs_by_path(catalog->path); +} + +void AssetCatalogService::update_catalog_path(const CatalogID catalog_id, const AssetCatalogPath &new_catalog_path) { AssetCatalog *renamed_cat = this->find_catalog(catalog_id); diff --git a/source/blender/blenkernel/intern/asset_catalog_test.cc b/source/blender/blenkernel/intern/asset_catalog_test.cc index 69efab76b43..cf06638bcdd 100644 --- a/source/blender/blenkernel/intern/asset_catalog_test.cc +++ b/source/blender/blenkernel/intern/asset_catalog_test.cc @@ -719,7 +719,7 @@ TEST_F(AssetCatalogTest, delete_catalog_leaf) /* Delete a leaf catalog, i.e. one that is not a parent of another catalog. * This keeps this particular test easy. */ - service.delete_catalog(UUID_POSES_RUZENA_HAND); + service.prune_catalogs_by_id(UUID_POSES_RUZENA_HAND); EXPECT_EQ(nullptr, service.find_catalog(UUID_POSES_RUZENA_HAND)); /* Contains not only paths from the CDF but also the missing parents (implicitly defined @@ -743,13 +743,65 @@ TEST_F(AssetCatalogTest, delete_catalog_leaf) assert_expected_tree_items(tree, expected_paths); } +TEST_F(AssetCatalogTest, delete_catalog_parent_by_id) +{ + AssetCatalogService service(asset_library_root_); + service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + + /* Delete a parent catalog. */ + service.delete_catalog_by_id(UUID_POSES_RUZENA); + + /* The catalog should have been deleted, but its children should still be there. */ + EXPECT_EQ(nullptr, service.find_catalog(UUID_POSES_RUZENA)); + EXPECT_NE(nullptr, service.find_catalog(UUID_POSES_RUZENA_FACE)); + EXPECT_NE(nullptr, service.find_catalog(UUID_POSES_RUZENA_HAND)); +} + +TEST_F(AssetCatalogTest, delete_catalog_parent_by_path) +{ + AssetCatalogService service(asset_library_root_); + service.load_from_disk(asset_library_root_ + "/" + "blender_assets.cats.txt"); + + /* Create an extra catalog with the to-be-deleted path, and one with a child of that. + * This creates some duplicates that are bound to occur in production asset libraries as well. */ + const bUUID cat1_uuid = service.create_catalog("character/Ružena/poselib")->catalog_id; + const bUUID cat2_uuid = service.create_catalog("character/Ružena/poselib/body")->catalog_id; + + /* Delete a parent catalog. */ + service.prune_catalogs_by_path("character/Ružena/poselib"); + + /* The catalogs and their children should have been deleted. */ + EXPECT_EQ(nullptr, service.find_catalog(UUID_POSES_RUZENA)); + EXPECT_EQ(nullptr, service.find_catalog(UUID_POSES_RUZENA_FACE)); + EXPECT_EQ(nullptr, service.find_catalog(UUID_POSES_RUZENA_HAND)); + EXPECT_EQ(nullptr, service.find_catalog(cat1_uuid)); + EXPECT_EQ(nullptr, service.find_catalog(cat2_uuid)); + + /* Contains not only paths from the CDF but also the missing parents (implicitly defined + * catalogs). This is why a leaf catalog was deleted. */ + std::vector<AssetCatalogPath> expected_paths{ + "character", + "character/Ellie", + "character/Ellie/poselib", + "character/Ellie/poselib/tailslash", + "character/Ellie/poselib/white space", + "character/Ružena", + "path", + "path/without", + "path/without/simplename", + }; + + AssetCatalogTree *tree = service.get_catalog_tree(); + assert_expected_tree_items(tree, expected_paths); +} + TEST_F(AssetCatalogTest, delete_catalog_write_to_disk) { TestableAssetCatalogService service(asset_library_root_); service.load_from_disk(asset_library_root_ + "/" + AssetCatalogService::DEFAULT_CATALOG_FILENAME); - service.delete_catalog(UUID_POSES_ELLIE); + service.delete_catalog_by_id(UUID_POSES_ELLIE); const CatalogFilePath save_to_path = use_temp_path(); AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file(); @@ -844,7 +896,7 @@ TEST_F(AssetCatalogTest, backups) /* Read a CDF, modify, and write it. */ AssetCatalogService service(cdf_dir); service.load_from_disk(); - service.delete_catalog(UUID_POSES_ELLIE); + service.delete_catalog_by_id(UUID_POSES_ELLIE); service.write_to_disk_on_blendfile_save(cdf_dir + "phony.blend"); const CatalogFilePath backup_path = writable_cdf_file + "~"; diff --git a/source/blender/editors/asset/intern/asset_catalog.cc b/source/blender/editors/asset/intern/asset_catalog.cc index 6e49ca2dd5c..eb1865ee9cc 100644 --- a/source/blender/editors/asset/intern/asset_catalog.cc +++ b/source/blender/editors/asset/intern/asset_catalog.cc @@ -77,5 +77,5 @@ void ED_asset_catalog_remove(::AssetLibrary *library, const CatalogID &catalog_i return; } - catalog_service->delete_catalog(catalog_id); + catalog_service->prune_catalogs_by_id(catalog_id); } |