mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 18:26:01 +02:00
Bug 311189 sometimes we don't notice external .cproject changes after team remove and replace. Fix + test
This commit is contained in:
parent
91561be4ae
commit
bc7368e9cf
3 changed files with 116 additions and 14 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008 Broadcom Corporation and others.
|
* Copyright (c) 2008, 2010 Broadcom Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -26,11 +26,14 @@ import org.eclipse.cdt.core.model.CoreModel;
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IFolder;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.resources.IResource;
|
import org.eclipse.core.resources.IResource;
|
||||||
import org.eclipse.core.resources.IResourceChangeEvent;
|
import org.eclipse.core.resources.IResourceChangeEvent;
|
||||||
import org.eclipse.core.resources.IResourceChangeListener;
|
import org.eclipse.core.resources.IResourceChangeListener;
|
||||||
import org.eclipse.core.resources.IResourceDelta;
|
import org.eclipse.core.resources.IResourceDelta;
|
||||||
|
import org.eclipse.core.resources.IResourceVisitor;
|
||||||
import org.eclipse.core.resources.ResourcesPlugin;
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
@ -166,6 +169,74 @@ public class CProjectDescriptionStorageTests extends BaseTestCase {
|
||||||
refreshJob.cancel();
|
refreshJob.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that external create and replace of CProjectDescription is picked up
|
||||||
|
* (Bug 311189)
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void testExternalCProjDescRemoveAndReplace() throws Exception {
|
||||||
|
// Create auto-refresh Thread
|
||||||
|
Job refreshJob = new Job("Auto-Refresh") {
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
return Status.CANCEL_STATUS;
|
||||||
|
try {
|
||||||
|
ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
fail("Error during refresh: " + e.getMessage());
|
||||||
|
}
|
||||||
|
schedule(500);
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
refreshJob.schedule();
|
||||||
|
|
||||||
|
// Backup the CProjectFile
|
||||||
|
final String initial = "initial";
|
||||||
|
final String testingStorage = "testingStorage";
|
||||||
|
final String testChildInStorage = "testChildInStorage";
|
||||||
|
|
||||||
|
// Backup the original storage file
|
||||||
|
backUpCProjectFile(initial);
|
||||||
|
|
||||||
|
IProject project = cProj.getProject();
|
||||||
|
ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project, true);
|
||||||
|
projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, true).createChild(testChildInStorage);
|
||||||
|
CoreModel.getDefault().setProjectDescription(project, projDesc);
|
||||||
|
// backup this project_desc
|
||||||
|
backUpCProjectFile(testingStorage);
|
||||||
|
|
||||||
|
// Close and open project
|
||||||
|
project.close(null);
|
||||||
|
project.open(null);
|
||||||
|
|
||||||
|
// verify changes are in read-only description
|
||||||
|
projDesc = CoreModel.getDefault().getProjectDescription(project, false);
|
||||||
|
assertNotNull(projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, false));
|
||||||
|
project.refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Lock the workspace
|
||||||
|
Job.getJobManager().beginRule(ResourcesPlugin.getWorkspace().getRoot(), null);
|
||||||
|
|
||||||
|
// Restore from backup
|
||||||
|
resListener.reset();
|
||||||
|
resListener.addFileToWatch(cProj.getProject().getFile(".cproject").getFullPath());
|
||||||
|
restoreCProjectUsingIResource(initial);
|
||||||
|
} finally {
|
||||||
|
Job.getJobManager().endRule(ResourcesPlugin.getWorkspace().getRoot());
|
||||||
|
}
|
||||||
|
|
||||||
|
resListener.waitForChange();
|
||||||
|
// Fetch what should be the initial project description
|
||||||
|
projDesc = CoreModel.getDefault().getProjectDescription(project, false);
|
||||||
|
assertNull(projDesc.getDefaultSettingConfiguration().getStorage(testingStorage, false));
|
||||||
|
|
||||||
|
refreshJob.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that a read-only project description file is picked up
|
* Tests that a read-only project description file is picked up
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
|
@ -239,6 +310,40 @@ public class CProjectDescriptionStorageTests extends BaseTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use IResource API to remove and replace the .cproject file (rather than just modifying
|
||||||
|
* it atomically exteranlly)
|
||||||
|
* This tests the team provider remove and replace behaviour when holding a higher-leve resource lock
|
||||||
|
*/
|
||||||
|
private void restoreCProjectUsingIResource(String uniqueKey) throws CoreException {
|
||||||
|
// delete the .cproject
|
||||||
|
IFile cproject = cProj.getProject().getFile(".cproject");
|
||||||
|
IFile cproject_back = cProj.getProject().getFile(".cproject_" + uniqueKey);
|
||||||
|
cproject.delete(true, null);
|
||||||
|
cproject.create(cproject_back.getContents(true), true, null);
|
||||||
|
|
||||||
|
final IFolder csettings = cProj.getProject().getFolder(".csettings");
|
||||||
|
IFolder csettings_back = cProj.getProject().getFolder(".csettings_" + uniqueKey);
|
||||||
|
csettings.refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||||
|
csettings_back.refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||||
|
|
||||||
|
// Nothing to do if these directories don't exist
|
||||||
|
if (!csettings.exists() && !csettings_back.exists())
|
||||||
|
return;
|
||||||
|
|
||||||
|
csettings.delete(false, null);
|
||||||
|
csettings.create(true, false, null);
|
||||||
|
|
||||||
|
csettings_back.accept(new IResourceVisitor() {
|
||||||
|
public boolean visit(IResource resource) throws CoreException {
|
||||||
|
assertTrue(resource instanceof IFile);
|
||||||
|
csettings.getFile(resource.getName()).create(((IFile)resource).getContents(), false, null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void backUpCProjectFile(String uniqueKey) {
|
private void backUpCProjectFile(String uniqueKey) {
|
||||||
File cproj = cProj.getProject().getFile(".cproject").getLocation().toFile();
|
File cproj = cProj.getProject().getFile(".cproject").getLocation().toFile();
|
||||||
File cprojback = cProj.getProject().getFile(".cproject_" + uniqueKey).getLocation().toFile();
|
File cprojback = cProj.getProject().getFile(".cproject_" + uniqueKey).getLocation().toFile();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2007 2008 Intel Corporation and others.
|
* Copyright (c) 2007, 2010 Intel Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -48,9 +48,9 @@ import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
|
||||||
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionStorageManager;
|
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionStorageManager;
|
||||||
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
|
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
|
||||||
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType;
|
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType;
|
||||||
|
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType.CProjectDescriptionStorageTypeProxy;
|
||||||
import org.eclipse.cdt.internal.core.settings.model.SettingsContext;
|
import org.eclipse.cdt.internal.core.settings.model.SettingsContext;
|
||||||
import org.eclipse.cdt.internal.core.settings.model.SettingsModelMessages;
|
import org.eclipse.cdt.internal.core.settings.model.SettingsModelMessages;
|
||||||
import org.eclipse.cdt.internal.core.settings.model.ICProjectDescriptionStorageType.CProjectDescriptionStorageTypeProxy;
|
|
||||||
import org.eclipse.core.filesystem.EFS;
|
import org.eclipse.core.filesystem.EFS;
|
||||||
import org.eclipse.core.filesystem.IFileInfo;
|
import org.eclipse.core.filesystem.IFileInfo;
|
||||||
import org.eclipse.core.filesystem.IFileStore;
|
import org.eclipse.core.filesystem.IFileStore;
|
||||||
|
@ -144,7 +144,7 @@ public class XmlProjectDescriptionStorage extends AbstractCProjectDescriptionSto
|
||||||
@Override
|
@Override
|
||||||
public void aboutToRun(IJobChangeEvent event) {
|
public void aboutToRun(IJobChangeEvent event) {
|
||||||
final Job job = event.getJob();
|
final Job job = event.getJob();
|
||||||
if ("org.eclipse.core.internal.events.NotificationManager$NotifyJob".equals(job.getClass().getName())) {
|
if ("org.eclipse.core.internal.events.NotificationManager$NotifyJob".equals(job.getClass().getName())) { //$NON-NLS-1$
|
||||||
job.cancel();
|
job.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,15 +289,12 @@ public class XmlProjectDescriptionStorage extends AbstractCProjectDescriptionSto
|
||||||
* @return boolean indicating whether reload is needed
|
* @return boolean indicating whether reload is needed
|
||||||
*/
|
*/
|
||||||
protected synchronized boolean checkExternalModification() {
|
protected synchronized boolean checkExternalModification() {
|
||||||
ICProjectDescription desc = getLoadedDescription();
|
|
||||||
// If loaded, and we have cached the modification stamp, reload
|
// If loaded, and we have cached the modification stamp, reload
|
||||||
if (desc != null && projectModificaitonStamp != IResource.NULL_STAMP) {
|
long currentModificationStamp = project.getFile(ICProjectDescriptionStorageType.STORAGE_FILE_NAME).getModificationStamp();
|
||||||
long currentModificationStamp = project.getFile(ICProjectDescriptionStorageType.STORAGE_FILE_NAME).getModificationStamp();
|
if (projectModificaitonStamp != currentModificationStamp) {
|
||||||
if (projectModificaitonStamp < currentModificationStamp) {
|
setCurrentDescription(null, true);
|
||||||
setCurrentDescription(null, true);
|
projectModificaitonStamp = currentModificationStamp;
|
||||||
projectModificaitonStamp = currentModificationStamp;
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008 Broadcom Corporation and others.
|
* Copyright (c) 2008, 2010 Broadcom Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -91,7 +91,7 @@ public class XmlProjectDescriptionStorage2 extends XmlProjectDescriptionStorage
|
||||||
project.getFolder(STORAGE_FOLDER_NAME).accept(new IResourceProxyVisitor() {
|
project.getFolder(STORAGE_FOLDER_NAME).accept(new IResourceProxyVisitor() {
|
||||||
public boolean visit(IResourceProxy proxy) throws CoreException {
|
public boolean visit(IResourceProxy proxy) throws CoreException {
|
||||||
if (modificationMap.containsKey(proxy.getName()))
|
if (modificationMap.containsKey(proxy.getName()))
|
||||||
if (modificationMap.get(proxy.getName()) < proxy.getModificationStamp()) {
|
if (modificationMap.get(proxy.getName()) != proxy.getModificationStamp()) {
|
||||||
// There may be old storages in here, ensure we don't infinite reload...
|
// There may be old storages in here, ensure we don't infinite reload...
|
||||||
modificationMap.put(proxy.getName(), proxy.getModificationStamp());
|
modificationMap.put(proxy.getName(), proxy.getModificationStamp());
|
||||||
setCurrentDescription(null, true);
|
setCurrentDescription(null, true);
|
||||||
|
|
Loading…
Add table
Reference in a new issue