Fix #6828: 隐藏父实例缺失的实例 (#6832)

This commit is contained in:
Glavo
2026-09-07 21:15:16 +08:00
committed by GitHub
parent 3742be0aa8
commit 1a258a2554
3 changed files with 48 additions and 0 deletions
@@ -293,6 +293,8 @@ public abstract class DefaultGameRepository implements GameRepository {
LOG.warning("Failed to load instance", e);
}
}
newSnapshot.removeInvalidInstances();
} catch (IOException e) {
LOG.warning("Failed to load instance from " + instancesDir, e);
}
@@ -361,6 +361,7 @@ public final class DefaultGameRepositoryDraft implements GameRepositoryDraft {
: repository.createInstance(committedSnapshot, manifest.id(), manifest);
committedSnapshot.put(updated);
}
committedSnapshot.removeInvalidInstances();
committedSnapshot.seal();
return committedSnapshot;
}
@@ -160,6 +160,51 @@ public class DefaultGameRepositorySnapshot implements GameRepositorySnapshot {
instances.remove(id);
}
/// Remove invalid instances.
/// TODO: In the future we could retain these instances and show their status in the UI.
void removeInvalidInstances() {
checkMutable();
HashSet<GameInstanceID> visited = null;
loop:
for (DefaultGameInstance instance : List.copyOf(instances.values())) {
if (instance.getManifest().inheritsFrom() == null) {
continue;
}
if (visited != null)
visited.clear();
else
visited = new HashSet<>();
DefaultGameInstance current = instance;
visited.add(current.getId());
while (current.getManifest().inheritsFrom() != null) {
GameInstanceID parentId = current.getManifest().inheritsFrom();
if (!visited.add(parentId)) {
// DefaultGameRepositorySnapshot.resolve can handle circular references
continue loop;
}
DefaultGameInstance parent = instances.get(parentId);
if (parent == null) {
LOG.warning("Instance " + current.getId() + " inherits from missing instance " + parentId);
for (DefaultGameInstance toRemoved = instance; toRemoved != null; ) {
instances.remove(toRemoved.getId());
toRemoved = toRemoved.getManifest().inheritsFrom() != null
? instances.get(toRemoved.getManifest().inheritsFrom())
: null;
}
break;
}
current = parent;
}
}
}
/// Creates an unpublished mutable copy with instances rebound to the copy.
///
/// The caller must call [#seal()] before retaining or publishing the result as a snapshot.