Index: plugin.xml =================================================================== RCS file: /home/eclipse/org.eclipse.compare/plugin.xml,v retrieving revision 1.47 diff -u -r1.47 plugin.xml --- plugin.xml 20 Apr 2004 09:23:45 -0000 1.47 +++ plugin.xml 13 May 2004 05:23:56 -0000 @@ -255,14 +255,16 @@ name="replaceWithGroup"> + + + + + + t1 ? -1 : t0 == t1 ? 0 : 1; + } + }; + + Arrays.sort(states, comparator); + + fileStates = Arrays.asList(states); + + // Create a dialog to let the user pick where they want to roll back to + ListDialog listDialog = new ListDialog(shell); + + listDialog.setContentProvider(new ListContentProvider()); + listDialog.setInput(fileStates); + listDialog.setLabelProvider(new LabelProvider() { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + public String getText(Object element) { + FileStateWrapper state = ((FileStateWrapper)element); + String date = DateFormat.getDateTimeInstance().format(new Date(state.timestamp)); + + return MessageFormat.format( bundle.getString("historyFormat"), new String[]{date, state.file.getName()}); + } + + }); + + listDialog.setTitle(bundle.getString("selectEarliest")); + + listDialog.setAddCancelButton(true); + listDialog.open(); + + Object[] selections = listDialog.getResult(); + + // Just exit if the user cancelled or didn't pick anything + if (selections != null && selections.length == 1) { + final FileStateWrapper earliestChange = (FileStateWrapper)selections[0]; + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + final IWorkspaceRoot root = workspace.getRoot(); + + final List finalFileStates = fileStates; + final Object[] finalStates = states; + + final String restoringFromHistoryName = bundle.getString("restoringFromHistory"); + + WorkspaceJob workspaceJob = new WorkspaceJob(restoringFromHistoryName) { + public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { + monitor.beginTask(restoringFromHistoryName, finalStates.length * 100); + + Set alreadyProcessed = new HashSet(); + + for (int idx = finalFileStates.indexOf(earliestChange); idx >= 0; idx--) { + FileStateWrapper next = (FileStateWrapper)finalStates[idx]; + IPath path = next.file.getFullPath(); + + if (!alreadyProcessed.contains(path)) { + IFile file = next.file; + + SubProgressMonitor subMon = new SubProgressMonitor(monitor, 100); + + rollback(file, earliestChange.timestamp, subMon); + + alreadyProcessed.add(path); + } else { + monitor.worked(100); + } + } + + monitor.done(); + + return Status.OK_STATUS; + } + + }; + + workspaceJob.setRule(root); + workspaceJob.setUser(true); + workspaceJob.schedule(); + }; + + } catch (CoreException e) { + MessageDialog.openError(shell, bundle.getString("error"), e.toString()); + } + } + + /** + * Rolls back the given file to the given time (if possible). + * + * @param file + * @param timestamp + * @param mon + * @throws CoreException + */ + public static void rollback(IFile file, long timestamp, IProgressMonitor mon) throws CoreException { + if (file.getLocalTimeStamp() >= timestamp) { + + IFileState[] states = file.getHistory(null); + + IFileState mostRecent = null; + long mostRecentTimestamp = 0; + + for (int stateIdx = 0; stateIdx < states.length; stateIdx++) { + IFileState state = states[stateIdx]; + + if (state.exists()) { + long modTime = state.getModificationTime(); + if (modTime > mostRecentTimestamp && modTime < timestamp) { + mostRecent = state; + mostRecentTimestamp = modTime; + } + } + } + + if (mostRecent != null) { + file.setContents(mostRecent, true, true, mon); + } + + } + } + + /** + * + * + * @param files + * @return a List of FileStateWrappers representing all known times when the files in the given + * list were modified. This includes the current file timestamp plus everything found in the + * resource history. + */ + protected static List getAllFileStates(IFile[] files) throws CoreException { + List result = new ArrayList(files.length); + + for (int idx = 0; idx < files.length; idx++) { + IFile file = files[idx]; + if (!file.isAccessible()) { + continue; + } + + result.add(new FileStateWrapper(file, file.getLocalTimeStamp())); + + IFileState[] states = files[idx].getHistory(null); + for (int stateIdx = 0; stateIdx < states.length; stateIdx++) { + IFileState state = states[stateIdx]; + + if (state.exists()) { + result.add(new FileStateWrapper(file, state.getModificationTime())); + } + } + } + + return result; + } + + protected static IFile[] getFilesRecursive(ISelection selection) throws CoreException { + List result = getFilesRecursive(Utilities.getResources(selection)); + return (IFile[]) result.toArray(new IFile[result.size()]); + } + + private static List getFilesRecursive(IResource[] input) throws CoreException { + List result = new ArrayList(input.length); + + for (int idx = 0; idx < input.length; idx++) { + + IResource resource = input[idx]; + + if (!resource.isAccessible()) { + continue; + } + + if (resource instanceof IContainer) { + IContainer container = (IContainer)resource; + + result.addAll(getFilesRecursive(container.members())); + } + + if (resource instanceof IFile) { + result.add(resource); + } + } + + return result; } } Index: compare/org/eclipse/compare/internal/ReplaceWithEditionAction.properties =================================================================== RCS file: /home/eclipse/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.properties,v retrieving revision 1.22 diff -u -r1.22 ReplaceWithEditionAction.properties --- compare/org/eclipse/compare/internal/ReplaceWithEditionAction.properties 28 Apr 2004 10:47:12 -0000 1.22 +++ compare/org/eclipse/compare/internal/ReplaceWithEditionAction.properties 13 May 2004 05:23:57 -0000 @@ -37,4 +37,10 @@ noLocalHistoryError= No local history available for selected resource. replaceError=Cannot replace resource (reason: {0}). -taskName=Replacing \ No newline at end of file +taskName=Replacing + + +historyFormat={0} : {1} +selectEarliest=Select earliest change to undo +restoringFromHistory=Restoring from history +error=Error