Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.InstanceScope;
Expand Down Expand Up @@ -1007,11 +1008,27 @@ public ProjectDescription read(IProject target, boolean creation) throws CoreExc
return description;
}
if (!descriptionStore.fetchInfo().exists()) {
String msg = NLS.bind(Messages.resources_missingProjectMeta, target.getName());
throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, target.getFullPath(), msg, null);
// .project file is missing, try to restore from private metadata
ProjectDescription restoredDescription = new ProjectDescription();
restoredDescription.setName(target.getName());
getWorkspace().getMetaArea().readPrivateDescription(target, restoredDescription);

// Check if we have useful data to restore (natures or build spec)
if (restoredDescription.getNatureIds().length > 0 || restoredDescription.getBuildSpec(false).length > 0) {
// We can restore useful data - use this description and log a warning
description = restoredDescription;
String msg = NLS.bind(Messages.resources_missingProjectMetaRepaired, target.getName());
Policy.log(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, msg));
// The description will be returned and should be written by the caller
} else {
// No useful data to restore - throw the original error
String msg = NLS.bind(Messages.resources_missingProjectMeta, target.getName());
throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, target.getFullPath(), msg, null);
}
} else {
String msg = NLS.bind(Messages.resources_readProjectMeta, target.getName());
error = new ResourceException(IResourceStatus.FAILED_READ_METADATA, target.getFullPath(), msg, e);
}
String msg = NLS.bind(Messages.resources_readProjectMeta, target.getName());
error = new ResourceException(IResourceStatus.FAILED_READ_METADATA, target.getFullPath(), msg, e);
} catch (IOException ex) {
Policy.log(ex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2572,4 +2572,68 @@ public void testProjectDeletion_Bug347220() throws CoreException {
monitor.assertUsedUp();
}

/**
* Tests that a project with a missing .project file can be opened
* if it has natures and buildspec saved in the private metadata area.
* See https://github.com/eclipse-platform/eclipse.platform/issues/2272
*/
@Test
public void testOpenProjectWithMissingDotProjectButPrivateMetadata() throws CoreException {
IProject project = getWorkspace().getRoot().getProject(createUniqueString());
monitor.prepare();
IProjectDescription description = getWorkspace().newProjectDescription(project.getName());
description.setNatureIds(new String[] { NATURE_SIMPLE });
project.create(description, monitor);
monitor.assertUsedUp();

monitor.prepare();
project.open(monitor);
monitor.assertUsedUp();
assertTrue("1.0", project.isOpen());
assertTrue("1.1", project.hasNature(NATURE_SIMPLE));

// Close the project
monitor.prepare();
project.close(monitor);
monitor.assertUsedUp();
assertFalse("2.0", project.isOpen());

// Delete the .project file from disk
IFile dotProjectFile = project.getFile(IProjectDescription.DESCRIPTION_FILE_NAME);
java.io.File dotProjectOnDisk = dotProjectFile.getLocation().toFile();
assertTrue("3.0", dotProjectOnDisk.exists());
assertTrue("3.1", dotProjectOnDisk.delete());
assertFalse("3.2", dotProjectOnDisk.exists());

// Refresh the project to detect the missing .project file
monitor.prepare();
project.refreshLocal(IResource.DEPTH_ONE, monitor);
monitor.assertUsedUp();

// Now try to open the project - it should succeed because private metadata exists
monitor.prepare();
project.open(monitor);
monitor.assertUsedUp();
assertTrue("4.0", project.isOpen());

// Verify that the nature was restored from private metadata
assertTrue("5.0", project.hasNature(NATURE_SIMPLE));

// Trigger a workspace save to write the restored .project file
monitor.prepare();
getWorkspace().save(true, monitor);
monitor.assertUsedUp();

// Verify that the .project file was recreated
monitor.prepare();
project.refreshLocal(IResource.DEPTH_ONE, monitor);
monitor.assertUsedUp();
assertTrue("6.0", dotProjectFile.exists());

// Clean up
monitor.prepare();
project.delete(true, monitor);
monitor.assertUsedUp();
}

}