mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-01 14:15:23 +02:00
Bug 295436 changes to the environment in org.eclipse.cdt.core.prefs file on disk are not noticed by existing Project Descriptions.
This commit is contained in:
parent
6ce54bb401
commit
2a859b384c
2 changed files with 113 additions and 16 deletions
|
@ -333,6 +333,60 @@ public class IEnvironmentVariableManagerTests extends TestCase {
|
|||
assertEquals(var, envManager.getVariable(var.getName(), prjDesc.getConfigurationById(id1), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests file system change of the settings file without recreating the project description
|
||||
*/
|
||||
public void testSettingsOverwriteBug295436() throws Exception {
|
||||
final IProject project = ResourceHelper.createCDTProjectWithConfig("envProject");
|
||||
|
||||
// Add another, derived configuration
|
||||
ICProjectDescription prjDesc = CoreModel.getDefault().getProjectDescription(project);
|
||||
ICConfigurationDescription desc = prjDesc.getActiveConfiguration();
|
||||
final String id1 = desc.getId(); // Config 1's ID
|
||||
final String id2 = CDataUtil.genId(id1); // Config 2's ID
|
||||
prjDesc.createConfiguration(id2, "config2", desc);
|
||||
CoreModel.getDefault().setProjectDescription(project, prjDesc);
|
||||
|
||||
// Get all the configurations
|
||||
prjDesc = CoreModel.getDefault().getProjectDescription(project);
|
||||
ICConfigurationDescription[] descs = prjDesc.getConfigurations();
|
||||
assertTrue(descs.length == 2);
|
||||
|
||||
IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager();
|
||||
IContributedEnvironment contribEnv = envManager.getContributedEnvironment();
|
||||
|
||||
assertFalse(descs[0].isModified());
|
||||
assertFalse(descs[1].isModified());
|
||||
|
||||
// Try setting an environment variable
|
||||
final IEnvironmentVariable var = new EnvironmentVariable("FOO", "BAR");
|
||||
contribEnv.addVariable(var, prjDesc.getConfigurationById(id1));
|
||||
assertTrue(prjDesc.getConfigurationById(id1).isModified());
|
||||
assertFalse(prjDesc.getConfigurationById(id2).isModified());
|
||||
CoreModel.getDefault().setProjectDescription(project, prjDesc);
|
||||
|
||||
// Backup the settings file
|
||||
project.getFile(".settings/org.eclipse.cdt.core.prefs.bak").create(
|
||||
project.getFile(".settings/org.eclipse.cdt.core.prefs").getContents(), true, null);
|
||||
|
||||
// Change the environment variable
|
||||
final IEnvironmentVariable var2 = new EnvironmentVariable("FOO", "BOO");
|
||||
contribEnv.addVariable(var2, prjDesc.getConfigurationById(id1));
|
||||
assertEquals(var2, envManager.getVariable(var2.getName(), prjDesc.getConfigurationById(id1), true));
|
||||
CoreModel.getDefault().setProjectDescription(project, prjDesc);
|
||||
|
||||
// clean desc should be updated when the preference file is overwritten
|
||||
final ICProjectDescription cleanDesc = CoreModel.getDefault().getProjectDescription(project);
|
||||
assertEquals(contribEnv.getVariable(var.getName(), cleanDesc.getConfigurationById(id1)).getValue(), var2.getValue());
|
||||
|
||||
// Replace the settings with it's backup
|
||||
project.getFile(".settings/org.eclipse.cdt.core.prefs").setContents(
|
||||
project.getFile(".settings/org.eclipse.cdt.core.prefs.bak").getContents(), true, false, null);
|
||||
// check that cleanDesc has been updated
|
||||
assertEquals(contribEnv.getVariable(var.getName(), cleanDesc.getConfigurationById(id1)).getValue(), var.getValue());
|
||||
assertEquals(var, envManager.getVariable(var.getName(), cleanDesc.getConfigurationById(id1), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that on deleting and recreating the project variables haven't persisted
|
||||
* @throws Exception
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.utils.envvar;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
@ -21,6 +24,7 @@ import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
|||
import org.eclipse.cdt.core.settings.model.ICStorageElement;
|
||||
import org.eclipse.cdt.utils.envvar.StorableEnvironmentLoader.ISerializeInfo;
|
||||
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
|
||||
import org.eclipse.core.runtime.preferences.IPreferenceNodeVisitor;
|
||||
import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener;
|
||||
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
|
||||
import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent;
|
||||
|
@ -74,10 +78,15 @@ public class PrefsStorableEnvironment extends StorableEnvironment {
|
|||
/** boolean indicating whether preferences have changed */
|
||||
private volatile boolean prefsChanged = true;
|
||||
|
||||
/** The node we're registered on */
|
||||
volatile IEclipsePreferences prefs;
|
||||
private Set<IEclipsePreferences> registeredOn = Collections.synchronizedSet(new HashSet<IEclipsePreferences>());
|
||||
|
||||
public PrefListener(ISerializeInfo info) {
|
||||
/** The node we're registered on */
|
||||
volatile IEclipsePreferences root;
|
||||
|
||||
Reference<PrefsStorableEnvironment> parentRef;
|
||||
|
||||
public PrefListener(PrefsStorableEnvironment parent, ISerializeInfo info) {
|
||||
this.parentRef = new WeakReference<PrefsStorableEnvironment>(parent);
|
||||
register (info);
|
||||
}
|
||||
|
||||
|
@ -85,15 +94,15 @@ public class PrefsStorableEnvironment extends StorableEnvironment {
|
|||
* Remove the listener
|
||||
*/
|
||||
public void remove() {
|
||||
if (prefs != null) {
|
||||
if (root != null) {
|
||||
try {
|
||||
prefs.removePreferenceChangeListener(this);
|
||||
prefs.removeNodeChangeListener(this);
|
||||
removeListener();
|
||||
} catch (Exception e) {
|
||||
CCorePlugin.log(e);
|
||||
// Catch all exceptions, this is called during parent finalization which we don't want to prevent...
|
||||
// e.g. IllegalStateException may occur during de-register
|
||||
}
|
||||
prefs = null;
|
||||
root = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,36 +110,70 @@ public class PrefsStorableEnvironment extends StorableEnvironment {
|
|||
* Register the Prefs change listener
|
||||
*/
|
||||
private void register(ISerializeInfo info) {
|
||||
if (prefs != null)
|
||||
if (root != null)
|
||||
return;
|
||||
prefs = (IEclipsePreferences)info.getNode();
|
||||
if (prefs != null) {
|
||||
prefs.addPreferenceChangeListener(this);
|
||||
prefs.addNodeChangeListener(this);
|
||||
}
|
||||
root = (IEclipsePreferences)info.getNode();
|
||||
if (root != null)
|
||||
addListener(root);
|
||||
prefsChanged = true;
|
||||
}
|
||||
|
||||
private void addListener(IEclipsePreferences node) {
|
||||
try {
|
||||
node.accept(new IPreferenceNodeVisitor() {
|
||||
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
|
||||
// {environment/{project|workspace/}config_name/variable/...
|
||||
node.addPreferenceChangeListener(PrefListener.this);
|
||||
node.addNodeChangeListener(PrefListener.this);
|
||||
registeredOn.add(node);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} catch (BackingStoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
private void removeListener() {
|
||||
synchronized(registeredOn) {
|
||||
for (IEclipsePreferences pref : registeredOn) {
|
||||
try {
|
||||
// {environment/{project|workspace/}config_name/variable/...
|
||||
pref.removePreferenceChangeListener(PrefListener.this);
|
||||
pref.removeNodeChangeListener(PrefListener.this);
|
||||
} catch (IllegalStateException e) {
|
||||
// Catch all exceptions, this is called during parent finalization which we don't want to prevent...
|
||||
// e.g. IllegalStateException may occur during de-register
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return & unset flag indicating if there has been a change in the backing store
|
||||
* @return whether there's been a change in the backing store
|
||||
*/
|
||||
public boolean preferencesChanged(ISerializeInfo info) {
|
||||
if (prefs == null)
|
||||
if (root == null)
|
||||
register(info);
|
||||
|
||||
boolean retVal = prefsChanged;
|
||||
// If we're registered for change, then unset
|
||||
if (prefs != null)
|
||||
if (root != null)
|
||||
prefsChanged = false;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void preferenceChange(PreferenceChangeEvent event) {
|
||||
prefsChanged = true;
|
||||
if (parentRef.get() == null)
|
||||
removeListener();
|
||||
}
|
||||
public void added(NodeChangeEvent event) {
|
||||
prefsChanged = true;
|
||||
if (parentRef.get() == null)
|
||||
removeListener();
|
||||
else
|
||||
addListener((IEclipsePreferences)event.getChild());
|
||||
}
|
||||
public void removed(NodeChangeEvent event) {
|
||||
prefsChanged = true;
|
||||
|
@ -219,7 +262,7 @@ public class PrefsStorableEnvironment extends StorableEnvironment {
|
|||
if (fPrefsChangedListener != null)
|
||||
fPrefsChangedListener.remove();
|
||||
fSerialEnv = serializeInfo;
|
||||
fPrefsChangedListener = new PrefListener(fSerialEnv);
|
||||
fPrefsChangedListener = new PrefListener(this, fSerialEnv);
|
||||
|
||||
// Update the cached state
|
||||
checkBackingSerializeInfo();
|
||||
|
|
Loading…
Add table
Reference in a new issue