### Eclipse Workspace Patch 1.0
#P org.eclipse.core.resources
Index: src/org/eclipse/core/internal/resources/Project.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Project.java,v
retrieving revision 1.165
diff -u -r1.165 Project.java
--- src/org/eclipse/core/internal/resources/Project.java 25 Jan 2010 14:08:43 -0000 1.165
+++ src/org/eclipse/core/internal/resources/Project.java 20 Feb 2010 22:54:02 -0000
@@ -921,14 +921,25 @@
}
startup();
//request a refresh if the project is new and has unknown members on disk
- // or restore of the project is not fully succesfull
+ // or restore of the project is not fully successful
if ((!used && unknownChildren) || !minorIssuesDuringRestore) {
- //refresh either in background or foreground
- if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
- workspace.refreshManager.refresh(this);
- monitor.worked(Policy.opWork * 80 / 100);
- } else {
- refreshLocal(IResource.DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 80 / 100));
+ boolean refreshed = false;
+ if (!used) {
+ // if a new project and refresh snapshot is present, load it and skip the refresh
+ refreshed = workspace.getSaveManager().restoreFromRefreshSnapshot(
+ this, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100));
+ if (refreshed) { // account for the refresh work
+ monitor.worked(Policy.opWork * 60 / 100);
+ }
+ }
+ if (!refreshed) {
+ //refresh either in background or foreground
+ if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
+ workspace.refreshManager.refresh(this);
+ monitor.worked(Policy.opWork * 60 / 100);
+ } else {
+ refreshLocal(IResource.DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 60 / 100));
+ }
}
}
//creation of this project may affect overlapping resources
@@ -1199,6 +1210,26 @@
}
}
+ /**
+ * Writes a snapshot of the project's refresh information to disk.
+ */
+ public void writeRefreshSnapshot(IProgressMonitor monitor) throws CoreException {
+ monitor = Policy.monitorFor(monitor);
+ try {
+ String msg = NLS.bind(Messages.resources_copying, getName());
+ monitor.beginTask(msg, Policy.totalWork);
+ try {
+ IProgressMonitor sub = Policy.subMonitorFor(monitor, Policy.opWork / 2, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
+ workspace.getSaveManager().writeRefreshSnapshot(this, sub);
+ monitor.worked(Policy.opWork / 2);
+ } catch (OperationCanceledException e) {
+ workspace.getWorkManager().operationCanceled();
+ throw e;
+ }
+ } finally {
+ monitor.done();
+ }
+ }
/*
* (non-Javadoc)
*
Index: src/org/eclipse/core/internal/resources/SaveManager.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/SaveManager.java,v
retrieving revision 1.102
diff -u -r1.102 SaveManager.java
--- src/org/eclipse/core/internal/resources/SaveManager.java 2 Nov 2009 10:12:59 -0000 1.102
+++ src/org/eclipse/core/internal/resources/SaveManager.java 20 Feb 2010 22:54:04 -0000
@@ -12,6 +12,7 @@
import java.io.*;
import java.util.*;
+import java.util.zip.*;
import org.eclipse.core.internal.events.*;
import org.eclipse.core.internal.localstore.*;
import org.eclipse.core.internal.utils.*;
@@ -708,6 +709,35 @@
}
/**
+ * Restores the contents of this project from a refresh snapshot. Throw an exception
+ * if the snapshot is found but an error occurs when reading the file.
+ * @return true
if the project data was restored successfully,
+ * and false
if the refresh snapshot was not found or could not be opened.
+ * @exception CoreException if an error occurred reading the snapshot file.
+ */
+ protected boolean restoreFromRefreshSnapshot(Project project, IProgressMonitor monitor) throws CoreException {
+ boolean status = true;
+ if (Policy.DEBUG_RESTORE)
+ System.out.println("Restore project " + project.getFullPath() + ": starting..."); //$NON-NLS-1$ //$NON-NLS-2$
+ long start = System.currentTimeMillis();
+ monitor = Policy.monitorFor(monitor);
+ try {
+ monitor.beginTask("", 40); //$NON-NLS-1$
+ status = restoreTreeFromRefreshSnapshot(project, Policy.subMonitorFor(monitor, 40));
+ if (status) {
+ // load the project description and set internal description
+ ProjectDescription description = workspace.getFileSystemManager().read(project, true);
+ project.internalSetDescription(description, false);
+ }
+ } finally {
+ monitor.done();
+ }
+ if (Policy.DEBUG_RESTORE)
+ System.out.println("Restore project " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return status;
+ }
+
+ /**
* Reads the markers which were originally saved
* for the tree rooted by the given resource.
*/
@@ -970,6 +1000,53 @@
return true;
}
+ /**
+ * Restores a tree saved as a refresh snapshot to a local file.
+ * @return true
if the snapshot exists, false
otherwise.
+ * @exception CoreException if the project could not be restored.
+ */
+ protected boolean restoreTreeFromRefreshSnapshot(Project project, IProgressMonitor monitor) throws CoreException {
+ long start = System.currentTimeMillis();
+ monitor = Policy.monitorFor(monitor);
+ String message;
+ try {
+ monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
+ IPath projectLocation = project.getLocation();
+ if (projectLocation == null){
+ //TODO handle case where project is on remote store
+ return false;
+ }
+ IPath snapshotLocation = projectLocation.append(IProject.REFRESH_SNAPSHOT_FILE_LOCATION);
+ java.io.File zipFile = snapshotLocation.toFile();
+ if (!zipFile.exists())
+ return false;
+ ZipFile zip = new ZipFile(zipFile);
+ ZipEntry treeEntry = zip.getEntry("resource-index.tree"); //$NON-NLS-1$
+ if (treeEntry == null) {
+ zip.close();
+ return false;
+ }
+ InputStream is = zip.getInputStream(treeEntry);
+ DataInputStream input = new DataInputStream(is);
+ try {
+ WorkspaceTreeReader reader = WorkspaceTreeReader.getReader(workspace, input.readInt());
+ reader.readTree(project, input, Policy.subMonitorFor(monitor, Policy.totalWork));
+ } finally {
+ input.close();
+ zip.close();
+ }
+ } catch (IOException e) {
+ message = NLS.bind(Messages.resources_readMeta, project.getFullPath());
+ throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, project.getFullPath(), message, e);
+ } finally {
+ monitor.done();
+ }
+ if (Policy.DEBUG_RESTORE_TREE) {
+ System.out.println("Restore Tree for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ return true;
+ }
+
class InternalMonitorWrapper extends ProgressMonitorWrapper{
private boolean ignoreCancel;
@@ -1640,6 +1717,51 @@
info.writeTo(output);
}
+ public void writeRefreshSnapshot(Project project, IProgressMonitor monitor) throws CoreException {
+ String snapshotPath = IProject.REFRESH_SNAPSHOT_FILE_LOCATION;
+ IPath snapshotLocation = project.getLocation().append(snapshotPath);
+ java.io.File tmpTree = null;
+ try {
+ tmpTree = java.io.File.createTempFile("tmp", ".tree"); //$NON-NLS-1$//$NON-NLS-2$
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL, snapshotLocation, Messages.resources_copyProblem, e);
+ }
+ java.io.File snapshotLocationFile = snapshotLocation.toFile();
+ snapshotLocationFile.delete();
+ ZipOutputStream out = null;
+ try {
+ FileOutputStream fis = new FileOutputStream(tmpTree);
+ DataOutputStream output = new DataOutputStream(fis);
+ try {
+ output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2);
+ writeTree(project, output, null);
+ } finally {
+ output.close();
+ }
+ snapshotLocationFile.getParentFile().mkdirs();
+ out = new ZipOutputStream(new FileOutputStream(snapshotLocationFile));
+ out.setLevel(Deflater.BEST_COMPRESSION);
+ ZipEntry e = new ZipEntry("resource-index.tree"); //$NON-NLS-1$
+ out.putNextEntry(e);
+ int read = 0;
+ byte[] buffer = new byte[4096];
+ InputStream in = new FileInputStream(tmpTree);
+ try {
+ while ((read = in.read(buffer)) >= 0) {
+ out.write(buffer, 0, read);
+ }
+ out.closeEntry();
+ } finally {
+ in.close();
+ }
+ out.close();
+ tmpTree.delete();
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL, snapshotLocation, Messages.resources_copyProblem, e);
+ }
+ monitor.worked(1);
+ }
+
protected void writeTree(Map statesToSave, DataOutputStream output, IProgressMonitor monitor) throws IOException, CoreException {
monitor = Policy.monitorFor(monitor);
try {
Index: src/org/eclipse/core/resources/IProject.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/resources/IProject.java,v
retrieving revision 1.47
diff -u -r1.47 IProject.java
--- src/org/eclipse/core/resources/IProject.java 25 Jan 2010 14:08:44 -0000 1.47
+++ src/org/eclipse/core/resources/IProject.java 20 Feb 2010 22:54:05 -0000
@@ -42,6 +42,13 @@
*/
public interface IProject extends IContainer, IAdaptable {
/**
+ * The location of the refresh snapshot used when opening a new
+ * project to skip the normal refresh of resources.
+ * @since 3.6
+ */
+ public static final String REFRESH_SNAPSHOT_FILE_LOCATION =
+ ".settings/resource-index.zip"; //$NON-NLS-1$
+ /**
* Invokes the build
method of the specified builder
* for this project. Does nothing if this project is closed. If this project
* has multiple builders on its build spec matching the given name, only
@@ -621,13 +628,15 @@
* of its resources from information stored on disk.
*
- * The BACKGROUND_REFRESH
update flag controls how
- * this method behaves when a project is opened for the first time on a location
- * that has existing resources on disk. If this flag is specified, resources on disk
- * will be added to the project in the background after this method returns.
- * Child resources of the project may not be available until this background
- * refresh completes. If this flag is not specified, resources on disk are added
- * to the project in the foreground before this method returns.
+ * When a project is opened for the first time, initial information about the
+ * project's existing resources can be obtained in the following ways:
+ *
null
if progress
+ * reporting is not desired
+ * @exception CoreException if this method fails. Reasons include:
+ *