From 277eb2a3def02ce67aa64bc7f172779453d43333 Mon Sep 17 00:00:00 2001 From: Lars Vogel Date: Fri, 28 Aug 2026 05:07:58 +0200 Subject: [PATCH] Stop one project's tree file name from protecting another's stale file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit removeUnusedTreeFiles shared one exclude list across all projects. removeFiles drops a name from it once it sees the matching file, but when a project had no tree file on disk its name stayed in the list. Tree files are named by a per resource sequence number, so that leftover name can match an outdated tree file of a later project and keep it from being deleted. Build the exclude list per resource instead. Contributes to https://github.com/eclipse-platform/eclipse.platform/issues/2887 Assisted-by: multiple AI agents and layers of automated tooling 🤖 --- .../core/internal/resources/SaveManager.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java index 199e3a1cbbc..7057e89a13c 100644 --- a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java +++ b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java @@ -708,30 +708,33 @@ protected void removeUnusedSafeTables() { } protected void removeUnusedTreeFiles() { + FilenameFilter filter = (dir, name) -> name.endsWith(LocalMetaArea.F_TREE); // root resource - List valuables = new ArrayList<>(10); IPath location = workspace.getMetaArea().getTreeLocationFor(workspace.getRoot(), false); - valuables.add(location.lastSegment()); - java.io.File target = location.toFile().getParentFile(); - FilenameFilter filter = (dir, name) -> name.endsWith(LocalMetaArea.F_TREE); - String[] candidates = target.list(filter); - if (candidates != null) { - removeFiles(target, candidates, valuables); - } + removeUnusedTreeFiles(location, filter); // projects IProject[] projects = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN); for (IProject project : projects) { - location = workspace.getMetaArea().getTreeLocationFor(project, false); - valuables.add(location.lastSegment()); - target = location.toFile().getParentFile(); - candidates = target.list(filter); - if (candidates != null) { - removeFiles(target, candidates, valuables); - } + removeUnusedTreeFiles(workspace.getMetaArea().getTreeLocationFor(project, false), filter); } } + /** + * Deletes every tree file next to the given one, which is the tree file still in + * use for that resource. + */ + private void removeUnusedTreeFiles(IPath treeLocation, FilenameFilter filter) { + java.io.File target = treeLocation.toFile().getParentFile(); + String[] candidates = target.list(filter); + if (candidates == null) { + return; + } + List valuables = new ArrayList<>(1); + valuables.add(treeLocation.lastSegment()); + removeFiles(target, candidates, valuables); + } + protected void reportSnapshotRequestor() { if (snapshotRequestor != null) { Policy.log(snapshotRequestor);