Skip to content

Commit c2b2947

Browse files
committed
Add preference for disabling history on specific files
This change adds a new preference to org.eclipse.core.resources: disable_history_property The preference can be set to a session property name, e.g.: disable_history If the preference is set and a file has the respective session property, setting the contents of the file will result in no new history entry for the edit. Example preference for product customization: org.eclipse.core.resources/disble_history_property=disable_history The session property can be set with: file.setSessionProperty(new QualifiedName(null, "disable_history"), "true"); Fixes: #2588
1 parent 4d9d68a commit c2b2947

File tree

3 files changed

+221
-5
lines changed

3 files changed

+221
-5
lines changed

resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import org.eclipse.core.runtime.MultiStatus;
7474
import org.eclipse.core.runtime.OperationCanceledException;
7575
import org.eclipse.core.runtime.Platform;
76+
import org.eclipse.core.runtime.QualifiedName;
7677
import org.eclipse.core.runtime.SubMonitor;
7778
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
7879
import org.eclipse.core.runtime.preferences.InstanceScope;
@@ -84,18 +85,26 @@
8485
*/
8586
public class FileSystemResourceManager implements ICoreConstants, IManager {
8687

88+
private static final String DISABLE_HISTORY_PREFERENCE_NAME = "disable_history_property"; //$NON-NLS-1$
89+
8790
/**
8891
* The history store is initialized lazily - always use the accessor method
8992
*/
9093
protected IHistoryStore _historyStore;
9194
protected Workspace workspace;
9295

9396
private volatile boolean lightweightAutoRefreshEnabled;
97+
private volatile QualifiedName disableHistoryProperty;
9498

95-
private final IPreferenceChangeListener lightweightAutoRefreshPrefListener = event -> {
96-
if (ResourcesPlugin.PREF_LIGHTWEIGHT_AUTO_REFRESH.equals(event.getKey())) {
99+
private final IPreferenceChangeListener prefListener = event -> {
100+
String preferenceName = event.getKey();
101+
if (ResourcesPlugin.PREF_LIGHTWEIGHT_AUTO_REFRESH.equals(preferenceName)) {
97102
lightweightAutoRefreshEnabled = Platform.getPreferencesService().getBoolean(ResourcesPlugin.PI_RESOURCES,
98103
ResourcesPlugin.PREF_LIGHTWEIGHT_AUTO_REFRESH, false, null);
104+
} else if (DISABLE_HISTORY_PREFERENCE_NAME.equals(preferenceName)) {
105+
String propertyName = Platform.getPreferencesService().getString(ResourcesPlugin.PI_RESOURCES,
106+
DISABLE_HISTORY_PREFERENCE_NAME, "", null); //$NON-NLS-1$
107+
disableHistoryProperty = propertyName.isEmpty() ? null : new QualifiedName(null, propertyName);
99108
}
100109
};
101110

@@ -1203,13 +1212,13 @@ public void shutdown(IProgressMonitor monitor) throws CoreException {
12031212
_historyStore.shutdown(monitor);
12041213
}
12051214
InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES)
1206-
.removePreferenceChangeListener(lightweightAutoRefreshPrefListener);
1215+
.removePreferenceChangeListener(prefListener);
12071216
}
12081217

12091218
@Override
12101219
public void startup(IProgressMonitor monitor) {
12111220
InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES)
1212-
.addPreferenceChangeListener(lightweightAutoRefreshPrefListener);
1221+
.addPreferenceChangeListener(prefListener);
12131222
lightweightAutoRefreshEnabled = Platform.getPreferencesService().getBoolean(ResourcesPlugin.PI_RESOURCES,
12141223
ResourcesPlugin.PREF_LIGHTWEIGHT_AUTO_REFRESH, false, null);
12151224
}
@@ -1497,7 +1506,25 @@ public void writeSilently(IProject target) throws CoreException {
14971506

14981507
public boolean storeHistory(IResource file) {
14991508
WorkspaceDescription description = workspace.internalGetDescription();
1500-
return description.isKeepDerivedState() || !file.isDerived();
1509+
return (description.isKeepDerivedState() || !file.isDerived()) && !disableHistory(file);
15011510
}
15021511

1512+
private boolean disableHistory(IResource resource) {
1513+
if (resource.getType() == IResource.FILE) {
1514+
QualifiedName property = disableHistoryProperty;
1515+
if (property != null) {
1516+
try {
1517+
return resource.getSessionProperty(property) != null;
1518+
} catch (CoreException e) {
1519+
Policy.log(e);
1520+
/*
1521+
* Assume history is disabled for the file, since the preference for disabling
1522+
* is set but we cannot determine the set of properties for the file.
1523+
*/
1524+
return true;
1525+
}
1526+
}
1527+
}
1528+
return false;
1529+
}
15031530
}

resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/AllLocalStoreTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
SafeFileInputOutputStreamTest.class, //
3636
SymlinkResourceTest.class, //
3737
UnifiedTreeTest.class, //
38+
DisableHistoryTests.class, //
3839
})
3940
public class AllLocalStoreTests {
4041

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Simeon Andreev and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Simeon Andreev - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.core.tests.internal.localstore;
15+
16+
import static org.eclipse.core.resources.ResourcesPlugin.getWorkspace;
17+
import static org.eclipse.core.tests.resources.ResourceTestUtil.createInWorkspace;
18+
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
20+
import java.util.Arrays;
21+
import org.eclipse.core.resources.IFile;
22+
import org.eclipse.core.resources.IFileState;
23+
import org.eclipse.core.resources.IFolder;
24+
import org.eclipse.core.resources.IProject;
25+
import org.eclipse.core.resources.IResource;
26+
import org.eclipse.core.resources.ResourcesPlugin;
27+
import org.eclipse.core.runtime.CoreException;
28+
import org.eclipse.core.runtime.QualifiedName;
29+
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
30+
import org.eclipse.core.runtime.preferences.InstanceScope;
31+
import org.eclipse.core.tests.resources.util.WorkspaceResetExtension;
32+
import org.junit.jupiter.api.AfterEach;
33+
import org.junit.jupiter.api.BeforeEach;
34+
import org.junit.jupiter.api.Test;
35+
import org.junit.jupiter.api.extension.ExtendWith;
36+
import org.osgi.service.prefs.BackingStoreException;
37+
38+
/**
39+
* Test for disabling file history based on a preference. Sets the preference
40+
* {@code org.eclipse.core.resources/disable_history_property=disable_history},
41+
* adds the session property {@code disable_history} on some test file and
42+
* performs edits. After setting the preference and session property, no new
43+
* file history is expected.
44+
*/
45+
@ExtendWith(WorkspaceResetExtension.class)
46+
public class DisableHistoryTests {
47+
48+
private static final String DISABLE_PREFERENCE_NAME = "disable_history_property";
49+
50+
private static final QualifiedName SESSION_PROPERTY_QN = new QualifiedName(null, "disable_history");
51+
52+
private IProject project;
53+
54+
@BeforeEach
55+
public void createTestProject() throws Exception {
56+
project = getWorkspace().getRoot().getProject("Project");
57+
createInWorkspace(project);
58+
}
59+
60+
@AfterEach
61+
public void cleanUp() throws Exception {
62+
setHistoryDisablePreference(null);
63+
}
64+
65+
@Test
66+
public void testDisableHistoryBeforeEdit() throws Exception {
67+
IFile file = project.getFile("test.txt");
68+
file.create("initial".getBytes(), IResource.FORCE, null);
69+
setHistoryDisablePreference(SESSION_PROPERTY_QN.getLocalName());
70+
disableHistory(file);
71+
writeContents(file, "edit 1");
72+
writeContents(file, "edit 2");
73+
IFileState[] history = file.getHistory(null);
74+
assertEquals(0, history.length, "Unexpected history after disable: " + toString(history));
75+
}
76+
77+
@Test
78+
public void testDisableHistoryAfterEdit() throws Exception {
79+
IFile file = project.getFile("test.txt");
80+
file.create("initial".getBytes(), IResource.FORCE, null);
81+
writeContents(file, "edit 1");
82+
writeContents(file, "edit 2");
83+
IFileState[] history = file.getHistory(null);
84+
assertEquals(2, history.length, "Unexpected history before disable: " + toString(history));
85+
setHistoryDisablePreference(SESSION_PROPERTY_QN.getLocalName());
86+
disableHistory(file);
87+
writeContents(file, "edit 3");
88+
history = file.getHistory(null);
89+
assertEquals(2, history.length, "Unexpected history after disable: " + toString(history));
90+
}
91+
92+
@Test
93+
public void testDisableHistoryBeforeMove() throws Exception {
94+
IFile file = project.getFile("test.txt");
95+
file.create("initial".getBytes(), IResource.FORCE, null);
96+
writeContents(file, "edit 1");
97+
writeContents(file, "edit 2");
98+
IFileState[] history = file.getHistory(null);
99+
assertEquals(2, history.length, "Unexpected history before disable: " + toString(history));
100+
setHistoryDisablePreference(SESSION_PROPERTY_QN.getLocalName());
101+
disableHistory(file);
102+
IFile movedFile = project.getFile("test2.txt");
103+
file.move(movedFile.getFullPath(), IResource.FORCE, null);
104+
history = movedFile.getHistory(null);
105+
assertEquals(2, history.length, "Unexpected history after move: " + toString(history));
106+
writeContents(movedFile, "edit 3");
107+
history = movedFile.getHistory(null);
108+
assertEquals(2, history.length, "Unexpected history after edit: " + toString(history));
109+
}
110+
111+
@Test
112+
public void testDisableHistoryBeforeMovingParentFolder() throws Exception {
113+
IFolder folder = project.getFolder("test_folder");
114+
folder.create(true, true, null);
115+
IFile file = folder.getFile("test.txt");
116+
file.create("initial".getBytes(), IResource.FORCE, null);
117+
writeContents(file, "edit 1");
118+
writeContents(file, "edit 2");
119+
IFileState[] history = file.getHistory(null);
120+
assertEquals(2, history.length, "Unexpected history before disable: " + toString(history));
121+
setHistoryDisablePreference(SESSION_PROPERTY_QN.getLocalName());
122+
disableHistory(file);
123+
IFolder movedFolder = project.getFolder("test_folder2");
124+
folder.move(movedFolder.getFullPath(), true, null);
125+
IFile movedFile = movedFolder.getFile("test.txt");
126+
history = movedFile.getHistory(null);
127+
assertEquals(2, history.length, "Unexpected history after move: " + toString(history));
128+
writeContents(movedFile, "edit 3");
129+
history = movedFile.getHistory(null);
130+
assertEquals(2, history.length, "Unexpected history after edit: " + toString(history));
131+
}
132+
133+
@Test
134+
public void testDisableHistoryBeforeDelete() throws Exception {
135+
IFile file = project.getFile("test.txt");
136+
file.create("initial".getBytes(), IResource.FORCE, null);
137+
writeContents(file, "edit 1");
138+
writeContents(file, "edit 2");
139+
IFileState[] history = file.getHistory(null);
140+
assertEquals(2, history.length, "Unexpected history before disable: " + toString(history));
141+
setHistoryDisablePreference(SESSION_PROPERTY_QN.getLocalName());
142+
disableHistory(file);
143+
writeContents(file, "edit 3");
144+
file.delete(true, null);
145+
history = file.getHistory(null);
146+
assertEquals(2, history.length, "Unexpected history after delete: " + toString(history));
147+
}
148+
149+
@Test
150+
public void testDisableHistoryBeforeDeletingParentFolder() throws Exception {
151+
IFolder folder = project.getFolder("test_folder");
152+
folder.create(true, true, null);
153+
IFile file = folder.getFile("test.txt");
154+
file.create("initial".getBytes(), IResource.FORCE, null);
155+
writeContents(file, "edit 1");
156+
writeContents(file, "edit 2");
157+
IFileState[] history = file.getHistory(null);
158+
assertEquals(2, history.length, "Unexpected history before disable: " + toString(history));
159+
setHistoryDisablePreference(SESSION_PROPERTY_QN.getLocalName());
160+
disableHistory(file);
161+
writeContents(file, "edit 3");
162+
folder.delete(true, null);
163+
history = file.getHistory(null);
164+
assertEquals(2, history.length, "Unexpected history after delete: " + toString(history));
165+
}
166+
167+
private void writeContents(IFile file, String contents) throws CoreException {
168+
file.setContents(contents.getBytes(), IResource.KEEP_HISTORY, null);
169+
}
170+
171+
private static String toString(IFileState... states) {
172+
return Arrays.toString(states);
173+
}
174+
175+
private static void disableHistory(IFile file) throws CoreException {
176+
file.setSessionProperty(SESSION_PROPERTY_QN, "true");
177+
}
178+
179+
private static void setHistoryDisablePreference(String value) throws BackingStoreException {
180+
IEclipsePreferences node = InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES);
181+
if (value != null) {
182+
node.put(DISABLE_PREFERENCE_NAME, value);
183+
} else {
184+
node.remove(DISABLE_PREFERENCE_NAME);
185+
}
186+
node.flush();
187+
}
188+
}

0 commit comments

Comments
 (0)