Fix (unreported) potential missing deletion of some linked liboverrides during resync.

The code checking whether old liboverrides which have been resynced into
new ones should be deleted was still assuming it was only working on
local liboverrides.

However, since recursive resync was implemented, this is not true
anymore, it can also handle resynced linked liboverrides.

This could have lead to missing deletion of some old linked liboverrides
after resyncing them.
This commit is contained in:
Bastien Montagne
2023-04-25 15:18:01 +02:00
parent 5f67b25c28
commit cbcf9058cd

View File

@@ -2076,6 +2076,7 @@ static bool lib_override_library_resync(Main *bmain,
}
BKE_id_remapper_free(id_remapper);
BLI_linklist_free(id_override_old_list, nullptr);
id_override_old_list = nullptr;
/* Delete old override IDs.
* Note that we have to use tagged group deletion here, since ID deletion also uses
@@ -2083,18 +2084,25 @@ static bool lib_override_library_resync(Main *bmain,
int user_edited_overrides_deletion_count = 0;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (id->tag & LIB_TAG_DOIT) {
/* Note that this works because linked IDs are always after local ones (including
* overrides), so we will only ever tag an old override ID after we have already checked it
* in this loop, hence we cannot untag it later. */
/* Since this code can also be called on linked liboverride now (during recursive resync),
* order of processing cannot guarantee anymore that the old liboverride won't be tagged for
* deletion before being processed by this loop (which would then untag it again).
*
* So instead store old liboverrides in Main into a temp list again, and do the tagging
* separately once this loop over all IDs in main is done. */
if (id->newid != nullptr && id->lib == id_root_reference->lib) {
ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id));
if (id_override_old != nullptr) {
id->newid->tag &= ~LIB_TAG_DOIT;
id_override_old->tag |= LIB_TAG_DOIT;
if (id_override_old->tag & LIB_TAG_NO_MAIN) {
id_override_old->tag |= LIB_TAG_DOIT;
BLI_assert(BLI_findindex(no_main_ids_list, id_override_old) != -1);
}
else {
/* Defer tagging. */
BLI_linklist_prepend(&id_override_old_list, id_override_old);
}
}
}
id->tag &= ~LIB_TAG_DOIT;
@@ -2147,6 +2155,13 @@ static bool lib_override_library_resync(Main *bmain,
}
FOREACH_MAIN_ID_END;
/* Finalize tagging old liboverrides for deletion. */
for (LinkNode *ln_iter = id_override_old_list; ln_iter != nullptr; ln_iter = ln_iter->next) {
ID *id_override_old = static_cast<ID *>(ln_iter->link);
id_override_old->tag |= LIB_TAG_DOIT;
}
BLI_linklist_free(id_override_old_list, nullptr);
/* Cleanup, many pointers in this GHash are already invalid now. */
BLI_ghash_free(linkedref_to_old_override, nullptr, nullptr);
@@ -2704,6 +2719,9 @@ static int lib_override_libraries_index_define(Main *bmain)
do_continue = false;
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
/* NOTE: In theory all non-liboverride IDs could be skipped here. This does not gives any
* performances boost though, so for now keep it as is (i.e. also consider non-liboverride
* relationships to establish libraries hierarchy). */
BKE_library_foreach_ID_link(
bmain, id, lib_override_sort_libraries_func, &do_continue, IDWALK_READONLY);
}