LibOverride: Fix recursive resync incorrectly clearing hierarchy info.
Recursive resync would validate hierarchy info of all IDs in Main, when it should only handle the ones in its currently processed 'library level'. Otherwise, it could incorrectly clear hierarchy info from 'more local' liboverrides that were still to be resynced, leading to issues like left-over 'orphaned'/unused liboverrides, needless renames, etc. Also contains a few 'logical mistakes' fixes in the resync code, though these did not seem to have any known practical effect.
This commit is contained in:
committed by
Bastien Montagne
parent
f3aeb71ea5
commit
00375abc38
@@ -1815,7 +1815,7 @@ static bool lib_override_root_is_valid(Main *bmain, ID *id)
|
||||
return false;
|
||||
}
|
||||
ID *id_root = id->override_library->hierarchy_root;
|
||||
if (!id_root || !ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
if (!id_root || !ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
|
||||
BLI_assert_unreachable();
|
||||
return false;
|
||||
}
|
||||
@@ -1901,7 +1901,7 @@ static void lib_override_root_hierarchy_set(
|
||||
for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != nullptr;
|
||||
from_id_entry = from_id_entry->next)
|
||||
{
|
||||
if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
|
||||
if (lib_override_hierarchy_dependencies_relationship_skip_check(from_id_entry)) {
|
||||
/* Never consider non-overridable relationships as actual dependencies. */
|
||||
continue;
|
||||
}
|
||||
@@ -1964,6 +1964,77 @@ static void lib_override_root_hierarchy_set(
|
||||
}
|
||||
}
|
||||
|
||||
static void lib_override_library_main_hierarchy_id_root_ensure(Main *bmain,
|
||||
ID *id,
|
||||
blender::Set<ID *> &processed_ids)
|
||||
{
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id));
|
||||
|
||||
if (id->override_library->hierarchy_root != nullptr) {
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id->override_library->hierarchy_root) ||
|
||||
id->override_library->hierarchy_root->lib != id->lib)
|
||||
{
|
||||
CLOG_ERROR(
|
||||
&LOG,
|
||||
"Existing override hierarchy root ('%s') for ID '%s' is invalid, will try to find a "
|
||||
"new valid one",
|
||||
id->override_library->hierarchy_root != nullptr ?
|
||||
id->override_library->hierarchy_root->name :
|
||||
"<NONE>",
|
||||
id->name);
|
||||
id->override_library->hierarchy_root = nullptr;
|
||||
}
|
||||
else if (!lib_override_root_is_valid(bmain, id)) {
|
||||
/* Serious invalid cases (likely resulting from bugs or invalid operations) should have
|
||||
* been caught by the first check above. Invalid hierarchy roots detected here can happen
|
||||
* in normal situations, e.g. when breaking a hierarchy by making one of its components
|
||||
* local. See also #137412. */
|
||||
CLOG_DEBUG(
|
||||
&LOG,
|
||||
"Existing override hierarchy root ('%s') for ID '%s' is invalid, will try to find a "
|
||||
"new valid one",
|
||||
id->override_library->hierarchy_root != nullptr ?
|
||||
id->override_library->hierarchy_root->name :
|
||||
"<NONE>",
|
||||
id->name);
|
||||
id->override_library->hierarchy_root = nullptr;
|
||||
}
|
||||
else {
|
||||
/* This ID is considered as having a valid hierarchy root. */
|
||||
processed_ids.add(id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
|
||||
BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS, false);
|
||||
|
||||
int best_level = 0;
|
||||
ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level);
|
||||
|
||||
if (!ELEM(id->override_library->hierarchy_root, id_root, nullptr)) {
|
||||
/* In case the detected hierarchy root does not match with the currently defined one, this is
|
||||
* likely an issue and is worth a warning. */
|
||||
CLOG_WARN(&LOG,
|
||||
"Potential inconsistency in library override hierarchy of ID '%s' (current root "
|
||||
"%s), detected as part of the hierarchy of '%s' (current root '%s')",
|
||||
id->name,
|
||||
id->override_library->hierarchy_root != nullptr ?
|
||||
id->override_library->hierarchy_root->name :
|
||||
"<NONE>",
|
||||
id_root->name,
|
||||
id_root->override_library->hierarchy_root != nullptr ?
|
||||
id_root->override_library->hierarchy_root->name :
|
||||
"<NONE>");
|
||||
processed_ids.add(id);
|
||||
return;
|
||||
}
|
||||
|
||||
lib_override_root_hierarchy_set(bmain, id_root, id, nullptr, processed_ids);
|
||||
|
||||
BLI_assert(id->override_library->hierarchy_root != nullptr);
|
||||
}
|
||||
|
||||
void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
|
||||
{
|
||||
ID *id;
|
||||
@@ -1976,69 +2047,8 @@ void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
|
||||
processed_ids.add(id);
|
||||
continue;
|
||||
}
|
||||
if (id->override_library->hierarchy_root != nullptr) {
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id->override_library->hierarchy_root) ||
|
||||
id->override_library->hierarchy_root->lib != id->lib)
|
||||
{
|
||||
CLOG_ERROR(
|
||||
&LOG,
|
||||
"Existing override hierarchy root ('%s') for ID '%s' is invalid, will try to find a "
|
||||
"new valid one",
|
||||
id->override_library->hierarchy_root != nullptr ?
|
||||
id->override_library->hierarchy_root->name :
|
||||
"<NONE>",
|
||||
id->name);
|
||||
id->override_library->hierarchy_root = nullptr;
|
||||
}
|
||||
else if (!lib_override_root_is_valid(bmain, id)) {
|
||||
/* Serious invalid cases (likely resulting from bugs or invalid operations) should have
|
||||
* been caught by the first check above. Invalid hierarchy roots detected here can happen
|
||||
* in normal situations, e.g. when breaking a hierarchy by making one of its components
|
||||
* local. See also #137412. */
|
||||
CLOG_DEBUG(
|
||||
&LOG,
|
||||
"Existing override hierarchy root ('%s') for ID '%s' is invalid, will try to find a "
|
||||
"new valid one",
|
||||
id->override_library->hierarchy_root != nullptr ?
|
||||
id->override_library->hierarchy_root->name :
|
||||
"<NONE>",
|
||||
id->name);
|
||||
id->override_library->hierarchy_root = nullptr;
|
||||
}
|
||||
else {
|
||||
/* This ID is considered as having a valid hierarchy root. */
|
||||
processed_ids.add(id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
|
||||
BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS, false);
|
||||
|
||||
int best_level = 0;
|
||||
ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level);
|
||||
|
||||
if (!ELEM(id->override_library->hierarchy_root, id_root, nullptr)) {
|
||||
/* In case the detected hierarchy root does not match with the currently defined one, this is
|
||||
* likely an issue and is worth a warning. */
|
||||
CLOG_WARN(&LOG,
|
||||
"Potential inconsistency in library override hierarchy of ID '%s' (current root "
|
||||
"%s), detected as part of the hierarchy of '%s' (current root '%s')",
|
||||
id->name,
|
||||
id->override_library->hierarchy_root != nullptr ?
|
||||
id->override_library->hierarchy_root->name :
|
||||
"<NONE>",
|
||||
id_root->name,
|
||||
id_root->override_library->hierarchy_root != nullptr ?
|
||||
id_root->override_library->hierarchy_root->name :
|
||||
"<NONE>");
|
||||
processed_ids.add(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
lib_override_root_hierarchy_set(bmain, id_root, id, nullptr, processed_ids);
|
||||
|
||||
BLI_assert(id->override_library->hierarchy_root != nullptr);
|
||||
lib_override_library_main_hierarchy_id_root_ensure(bmain, id, processed_ids);
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
@@ -3694,7 +3704,25 @@ static bool lib_override_library_main_resync_on_library_indirect_level(
|
||||
|
||||
/* In some fairly rare (and degenerate) cases, some root ID from other liboverrides may have been
|
||||
* freed, and therefore set to nullptr. Attempt to fix this as best as possible. */
|
||||
BKE_lib_override_library_main_hierarchy_root_ensure(bmain);
|
||||
/* WARNING: Cannot use directly #BKE_lib_override_library_main_hierarchy_root_ensure here, as it
|
||||
* processes the whole Main content - only the IDs matching current resync scope should be
|
||||
* checked here. */
|
||||
{
|
||||
BKE_main_relations_create(bmain, 0);
|
||||
blender::Set<ID *> processed_ids;
|
||||
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (lib_override_library_main_resync_id_skip_check(id, library_indirect_level)) {
|
||||
processed_ids.add(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
lib_override_library_main_hierarchy_id_root_ensure(bmain, id, processed_ids);
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
BKE_main_relations_free(bmain);
|
||||
}
|
||||
|
||||
if (do_reports_recursive_resync_timing) {
|
||||
reports->duration.lib_overrides_recursive_resync += BLI_time_now_seconds() - init_time;
|
||||
|
||||
Reference in New Issue
Block a user