diff options
author | Michael Valenta | 2002-04-23 15:30:29 +0000 |
---|---|---|
committer | Michael Valenta | 2002-04-23 15:30:29 +0000 |
commit | acadf96a4ce3fa8044a2459c7b8de7a989541edb (patch) | |
tree | 05ac57b4be2bef4a7561dbd140d2878e2ffad2df | |
parent | 28df34b0a427aff6ffb90ee7fe456db20b65c289 (diff) | |
download | eclipse.platform.team-acadf96a4ce3fa8044a2459c7b8de7a989541edb.tar.gz eclipse.platform.team-acadf96a4ce3fa8044a2459c7b8de7a989541edb.tar.xz eclipse.platform.team-acadf96a4ce3fa8044a2459c7b8de7a989541edb.zip |
232: VCM UI + CVS: multiple round trips caused by API client (1GIZ4I8)
14 files changed, 578 insertions, 327 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Command.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Command.java index ee4bd2219..654bb3e5c 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Command.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Command.java @@ -1,10 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2000, 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM - Initial API and implementation + ******************************************************************************/ package org.eclipse.team.internal.ccvs.core.client; -/* - * (c) Copyright IBM Corp. 2000, 2002. - * All Rights Reserved. - */ - import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; @@ -675,4 +680,39 @@ public abstract class Command extends Request { protected LocalOption[] filterLocalOptions(Session session, GlobalOption[] globalOptions, LocalOption[] localOptions) { return localOptions; } + + /** + * Execute a CVS command inside an ICVSRunnable passed to Session.run() + * <p> + * Dispatches the commands, retrieves the results, and determines whether or + * not an error occurred. A listener may be supplied to capture message text + * that would normally be written to the standard error and standard output + * streams of a command line CVS client. + * </p> + * @param globalOptions the array of global options, or NO_GLOBAL_OPTIONS + * @param localOptions the array of local options, or NO_LOCAL_OPTIONS + * @param arguments the array of arguments (usually filenames relative to localRoot), or NO_ARGUMENTS + * @param listener the command output listener, or null to discard all messages + * @param monitor the progress monitor + * @return a status code indicating success or failure of the operation + * @throws CVSException if a fatal error occurs (e.g. connection timeout) + */ + public final IStatus execute(GlobalOption[] globalOptions, LocalOption[] localOptions, ICVSResource[] arguments, + ICommandOutputListener listener, IProgressMonitor pm) throws CVSException { + + // We assume that all the passed resources have the same root + Session openSession = Session.getOpenSession(arguments[0]); + if (openSession == null) { + throw new CVSException(Policy.bind("Command.noOpenSession")); //$NON-NLS-1$ + } else { + // Convert arguments + List stringArguments = new ArrayList(arguments.length); + for (int i = 0; i < arguments.length; i++) { + stringArguments.add(arguments[i].getRelativePath(openSession.getLocalRoot())); + } + return execute(openSession, globalOptions, localOptions, (String[]) stringArguments.toArray(new String[stringArguments.size()]), listener, pm); + } + + + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java index 080cf8214..a46b1846f 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java @@ -41,6 +41,7 @@ import org.eclipse.team.internal.ccvs.core.ICVSFolder; import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; import org.eclipse.team.internal.ccvs.core.ICVSResource; import org.eclipse.team.internal.ccvs.core.ICVSResourceVisitor; +import org.eclipse.team.internal.ccvs.core.ICVSRunnable; import org.eclipse.team.internal.ccvs.core.Policy; import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; import org.eclipse.team.internal.ccvs.core.connection.Connection; @@ -86,6 +87,9 @@ public class Session { private static final boolean IS_CRLF_PLATFORM = Arrays.equals( System.getProperty("line.separator").getBytes(), new byte[] { '\r', '\n' }); //$NON-NLS-1$ + private static Map currentOpenSessions = null; + private static final int MAX_SESSIONS_OPEN = 10; + private CVSRepositoryLocation location; private ICVSFolder localRoot; private boolean outputToConsole; @@ -127,6 +131,109 @@ public class Session { this.outputToConsole = outputToConsole; } + /** + * Execute the given runnable in a context that has access to an open session + * + * A session will be opened for the provided root. If the root is null, no session is opened. + * However, sessions will be open for nested calls to run and these sessions will not be closed + * until the outer most run finishes. + */ + public static void run(ICVSRepositoryLocation location, ICVSFolder root, boolean outputToConsole, + ICVSRunnable runnable, IProgressMonitor monitor) throws CVSException { + + // Determine if we are nested or not + boolean isOuterRun = false; + if (currentOpenSessions == null) { + // Initialize the variable to be a map + currentOpenSessions = new HashMap(); + isOuterRun = true; + } + + try { + monitor = Policy.monitorFor(monitor); + monitor.beginTask(null, 100); + if (root == null) { + // We don't have a root, so just run the runnable + // (assuming that nested runs will create sessions) + runnable.run(Policy.subMonitorFor(monitor, 90)); + } else { + // Open a session on the root as far up the chain as possible + ICVSFolder actualRoot = root; + while (actualRoot.isManaged()) { + actualRoot = actualRoot.getParent(); + } + // Look for the root in the current open sessions + Session session = (Session)currentOpenSessions.get(actualRoot); + if (session == null) { + // Make sure we don't exceed our maximum + if (currentOpenSessions.size() == MAX_SESSIONS_OPEN) { + // Pick one at random and close it + Object key = currentOpenSessions.keySet().iterator().next(); + try { + ((Session)currentOpenSessions.get(key)).close(); + } catch (CVSException e) { + CVSProviderPlugin.log(e.getStatus()); + } finally { + currentOpenSessions.remove(key); + } + } + // If it's not there, open a session for the given root and remember it + session = new Session(location, actualRoot, outputToConsole); + session.open(Policy.subMonitorFor(monitor, 10)); + currentOpenSessions.put(actualRoot, session); + } + + try { + root.run(runnable, Policy.subMonitorFor(monitor, 100)); + } catch (CVSException e) { + // The run didn't succeed so close the session and forget it ever existed + try { + // The session may have been close by a nested run + if (currentOpenSessions.get(actualRoot) != null) session.close(); + } finally { + currentOpenSessions.remove(actualRoot); + throw e; + } + } + } + } finally { + monitor.done(); + if (isOuterRun) { + // Close all open sessions + try { + Iterator iter = currentOpenSessions.keySet().iterator(); + while (iter.hasNext()) { + Session session = (Session)currentOpenSessions.get(iter.next()); + try { + session.close(); + } catch (CVSException e) { + CVSProviderPlugin.log(e.getStatus()); + } + } + } finally { + currentOpenSessions = null; + } + } + } + } + + /** + * Answer the currently open session + */ + protected static Session getOpenSession(ICVSResource resource) { + ICVSFolder root; + if (resource.isFolder()) { + root = (ICVSFolder)resource; + } else { + root = resource.getParent(); + } + while (root.isManaged()) { + root = root.getParent(); + } + // Look for the root in the current open sessions + return (Session)currentOpenSessions.get(root); + } + /** * Register a case collision with the session. * diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IStatusListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IStatusListener.java index 50c1e1dd8..f36162143 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IStatusListener.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IStatusListener.java @@ -1,11 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2000, 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM - Initial API and implementation + ******************************************************************************/ package org.eclipse.team.internal.ccvs.core.client.listeners; - -/* - * (c) Copyright IBM Corp. 2000, 2002. - * All Rights Reserved. - */ import org.eclipse.core.runtime.IPath; +import org.eclipse.team.internal.ccvs.core.ICVSFolder; public interface IStatusListener { @@ -14,7 +20,9 @@ public interface IStatusListener { /** * Provides access to the revision of a file through the use of the Status command. * - * The provided path is the absoulte remote path of the resource including the repository root directory + * @param commandRoot the root directory of the command + * @param path the absolute remote path of the resource including the repository root directory + * @param remoteRevision the remote revision of the file */ - public void fileStatus(IPath path, String remoteRevision); + public void fileStatus(ICVSFolder commandRoot, IPath path, String remoteRevision); } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IUpdateMessageListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IUpdateMessageListener.java index fe6f62f6b..c3583baa0 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IUpdateMessageListener.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IUpdateMessageListener.java @@ -1,11 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2000, 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM - Initial API and implementation + ******************************************************************************/ package org.eclipse.team.internal.ccvs.core.client.listeners; - -/* - * (c) Copyright IBM Corp. 2000, 2002. - * All Rights Reserved. - */ import org.eclipse.core.runtime.IPath; +import org.eclipse.team.internal.ccvs.core.ICVSFolder; /** * This listener is used by RemoteFolder to listener for E and M messages @@ -13,17 +19,34 @@ import org.eclipse.core.runtime.IPath; */ public interface IUpdateMessageListener { /** - * information that a directory which has been reported using directoryInformation() does not exist + * Notification that a directory (which may or may not have been reported by + * directoryInformation()) does not exist. + * + * @param commandRoot the root directory of the command + * @param path the path of the directory relative to the commandRoot + */ + public void directoryDoesNotExist(ICVSFolder commandRoot, IPath path); + /** + * Notification of information about a directory. + * + * @param commandRoot the root directory of the command + * @param path the path of the directory relative to the commandRoot + * @param newDirectory true if the directory does not exist locally (i.e. in the commandRoot hierarchy) */ - public void directoryDoesNotExist(IPath path); + public void directoryInformation(ICVSFolder commandRoot, IPath path, boolean newDirectory); /** - * directory information + * Notification of information about a file + * + * @param type the type of update for the file (see Update for type constants) + * @param commandRoot the root directory of the command + * @param filename the path of the file relative to the commandRoot */ - public void directoryInformation(IPath path, boolean newDirectory); + public void fileInformation(int type, ICVSFolder parent, String filename); /** - * file information + * Notification that a file does not exists remotely + * + * @param commandRoot the root directory of the command + * @param filename the path of the file relative to the commandRoot */ - public void fileInformation(int type, String filename); - - public void fileDoesNotExist(String filename); + public void fileDoesNotExist(ICVSFolder parent, String filename); } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/StatusListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/StatusListener.java index 8fccd7116..cdf501883 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/StatusListener.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/StatusListener.java @@ -1,10 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2000, 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM - Initial API and implementation + ******************************************************************************/ package org.eclipse.team.internal.ccvs.core.client.listeners; -/* - * (c) Copyright IBM Corp. 2000, 2002. - * All Rights Reserved. - */ - import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -47,7 +52,7 @@ public class StatusListener implements ICommandOutputListener { } // Inform the listener about the file revision - statusListener.fileStatus(fullPath, remoteRevision); + statusListener.fileStatus(commandRoot, fullPath, remoteRevision); } } return OK; @@ -69,7 +74,7 @@ public class StatusListener implements ICommandOutputListener { // (i.e. the resource is a folder) if (statusListener != null) // XXX We should be using that path relative to the root of the command (mRoot)!!! - statusListener.fileStatus(new Path(folderPath).removeFirstSegments(1), IStatusListener.FOLDER_REVISION); + statusListener.fileStatus(commandRoot, new Path(folderPath).removeFirstSegments(1), IStatusListener.FOLDER_REVISION); isFolder = false; return OK; } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/UpdateListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/UpdateListener.java index 847bb11f1..e70a71d8a 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/UpdateListener.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/UpdateListener.java @@ -1,10 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2000, 2002 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM - Initial API and implementation + ******************************************************************************/ package org.eclipse.team.internal.ccvs.core.client.listeners; -/* - * (c) Copyright IBM Corp. 2000, 2002. - * All Rights Reserved. - */ - import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -56,7 +61,7 @@ public class UpdateListener implements ICommandOutputListener { type = Update.STATE_MERGEABLE_CONFLICT; merging = false; } - updateMessageListener.fileInformation(type, path); + updateMessageListener.fileInformation(type, commandRoot, path); } return OK; } @@ -99,23 +104,23 @@ public class UpdateListener implements ICommandOutputListener { String message = line.substring(SERVER_PREFIX.length()); if (message.startsWith("Updating")) { //$NON-NLS-1$ if (updateMessageListener != null) { - IPath path = new Path(message.substring(8)); - updateMessageListener.directoryInformation(path, false); + IPath path = new Path(message.substring(9)); + updateMessageListener.directoryInformation(commandRoot, path, false); } } else if (message.startsWith("skipping directory")) { //$NON-NLS-1$ if (updateMessageListener != null) { IPath path = new Path(message.substring(18).trim()); - updateMessageListener.directoryDoesNotExist(path); + updateMessageListener.directoryDoesNotExist(commandRoot, path); } } else if (message.startsWith("New directory")) { //$NON-NLS-1$ if (updateMessageListener != null) { IPath path = new Path(message.substring(15, message.indexOf('\'', 15))); - updateMessageListener.directoryInformation(path, true); + updateMessageListener.directoryInformation(commandRoot, path, true); } } else if (message.endsWith("is no longer in the repository")) { //$NON-NLS-1$ if (updateMessageListener != null) { String filename = message.substring(0, message.length() - 31); - updateMessageListener.fileDoesNotExist(filename); + updateMessageListener.fileDoesNotExist(commandRoot, filename); } } else if (message.startsWith("conflict:")) { //$NON-NLS-1$ /* @@ -130,7 +135,7 @@ public class UpdateListener implements ICommandOutputListener { if (message.endsWith("is modified but no longer in the repository")) { //$NON-NLS-1$ // The "C foler/file.ext" will come after this so if whould be ignored! String filename = message.substring(10, message.length() - 44); - updateMessageListener.fileDoesNotExist(filename); + updateMessageListener.fileDoesNotExist(commandRoot, filename); } } return new CVSStatus(CVSStatus.WARNING, CVSStatus.CONFLICT, line); @@ -143,7 +148,7 @@ public class UpdateListener implements ICommandOutputListener { if (updateMessageListener != null) { if (message.endsWith("is not (any longer) pertinent")) { //$NON-NLS-1$ String filename = message.substring(9, message.length() - 30); - updateMessageListener.fileDoesNotExist(filename); + updateMessageListener.fileDoesNotExist(commandRoot, filename); } } return new CVSStatus(CVSStatus.WARNING, CVSStatus.CONFLICT, line); diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties index 2e55e5a87..83ec04217 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/messages.properties @@ -106,6 +106,7 @@ RemoteResource.invalidOperation=Invalid operation performed on remote resource RemoteFolder.errorFetchingRevisions=Error fetching file revision numbers RemoteFolder.invalidChild=Resource {0} is not a child of folder {1} RemoteFolder.errorFetchingRevisions=Error fetching file revisions +RemoteFolder.errorFetchingMembers=One or more error occured fetching the members of a remote folder RemoteFolder.doesNotExist=Folder {0} does not exist remotely RemoteFile.noContentsReceived=No contents received from server for {0} @@ -141,6 +142,7 @@ Command.valid-requests=valid-requests Command.unsupportedResponse=Unknown response received from cvs server: {0} {1} Command.argumentNotManaged=Argument {0} is not managed Command.invalidTag=HEAD is not a valid tag +Command.noOpenSession=The CVS command cannot be issued because there is no connection available Tag.notVersionOrBranchError=Error applying tag: the tag provided is not a version or branch tag. diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/CVSEntryLineTag.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/CVSEntryLineTag.java index a8c37a767..ac60cf365 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/CVSEntryLineTag.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/CVSEntryLineTag.java @@ -48,13 +48,6 @@ public class CVSEntryLineTag extends CVSTag { return "";//$NON-NLS-1$ } - public boolean equals(Object obj) { - // We assume, that the name and type can not be null - if (obj == this) return true; - if (!(obj instanceof CVSEntryLineTag)) return false; - return (type == ((CVSEntryLineTag)obj).type) && name.equals(((CVSEntryLineTag)obj).name); - } - /* * For debugging purposes. */ diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java index 03b791bb7..fe3286756 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java @@ -34,7 +34,9 @@ import org.eclipse.team.internal.ccvs.core.ICVSFolder; import org.eclipse.team.internal.ccvs.core.ICVSRemoteFile; import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; +import org.eclipse.team.internal.ccvs.core.ICVSResource; import org.eclipse.team.internal.ccvs.core.ICVSResourceVisitor; +import org.eclipse.team.internal.ccvs.core.ICVSRunnable; import org.eclipse.team.internal.ccvs.core.ILogEntry; import org.eclipse.team.internal.ccvs.core.Policy; import org.eclipse.team.internal.ccvs.core.client.Command; @@ -190,133 +192,111 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { // We will end up here if we couldn't read or delete the cache file throw new CVSException(new CVSStatus(IStatus.ERROR, 0, Policy.bind("RemoteFile.errorRetrievingFromCache", e.getMessage()), e));//$NON-NLS-1$ } - monitor = Policy.monitorFor(monitor); - monitor.beginTask(Policy.bind("RemoteFile.getContents"), 100); //$NON-NLS-1$ - try { - List entries = new ArrayList(); - IStatus status; - Session s = new Session(getRepository(), parent, false); - s.open(Policy.subMonitorFor(monitor, 10)); - try { - status = Command.UPDATE.execute(s, + + Session.run(getRepository(), parent, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + monitor.beginTask(null, 100); + IStatus status = Command.UPDATE.execute( Command.NO_GLOBAL_OPTIONS, new LocalOption[] { Update.makeTagOption(new CVSTag(info.getRevision(), CVSTag.VERSION)), Update.IGNORE_LOCAL_CHANGES }, - new String[] { getName() }, + new ICVSResource[] { RemoteFile.this }, null, - Policy.subMonitorFor(monitor, 80)); - if (status.getCode() != CVSStatus.SERVER_ERROR && entry == null) { - getLogEntry(s, Policy.subMonitorFor(monitor, 10)); - // Ignore the status of the log entry fetch. - // If it fails, the entry will still be null + Policy.subMonitorFor(monitor, 90)); + if (status.getCode() != CVSStatus.SERVER_ERROR) { + try { + getLogEntry(Policy.subMonitorFor(monitor, 10)); + } catch (CVSException e) { + // Ignore the status of the log entry fetch. + // If it fails, the entry will still be null + } + } + monitor.done(); + if (status.getCode() == CVSStatus.SERVER_ERROR) { + throw new CVSServerException(status); } - } finally { - s.close(); - } - if (status.getCode() == CVSStatus.SERVER_ERROR) { - throw new CVSServerException(status); } - // If the update succeeded but no contents were retreived from the server - // than we can assume that the remote file has no contents. - if (contents == null) { - // The above is true unless there is a cache file - try { - File ioFile = CVSProviderPlugin.getPlugin().getCacheFileFor(getCacheRelativePath()); - if (ioFile.exists()) { - return new BufferedInputStream(new FileInputStream(ioFile)); - } else { - contents = new byte[0]; - } - } catch (IOException e) { - // Something is wrong with the cached file so signal an error. - throw new CVSException(new CVSStatus(IStatus.ERROR, 0, Policy.bind("RemoteFile.errorRetrievingFromCache", e.getMessage()), e));//$NON-NLS-1$ + }, monitor); + + // If the update succeeded but no contents were retreived from the server + // than we can assume that the remote file has no contents. + if (contents == null) { + // The above is true unless there is a cache file + try { + File ioFile = CVSProviderPlugin.getPlugin().getCacheFileFor(getCacheRelativePath()); + if (ioFile.exists()) { + return new BufferedInputStream(new FileInputStream(ioFile)); + } else { + contents = new byte[0]; } + } catch (IOException e) { + // Something is wrong with the cached file so signal an error. + throw new CVSException(new CVSStatus(IStatus.ERROR, 0, Policy.bind("RemoteFile.errorRetrievingFromCache", e.getMessage()), e));//$NON-NLS-1$ } - } finally { - monitor.done(); } } return new ByteArrayInputStream(contents); } /* - * @see ICVSRemoteFile#getLogEntry() + * @see ICVSRemoteFile#getLogEntry(IProgressMonitor) */ public ILogEntry getLogEntry(IProgressMonitor monitor) throws CVSException { if (entry == null) { - monitor = Policy.monitorFor(monitor); - monitor.beginTask(Policy.bind("RemoteFile.getLogEntries"), 100); //$NON-NLS-1$ - try { - Session s = new Session(getRepository(), parent, false); - s.open(Policy.subMonitorFor(monitor, 10)); - try { - IStatus status = getLogEntry(s, Policy.subMonitorFor(monitor, 90)); - if (status.getCode() == CVSStatus.SERVER_ERROR) { - throw new CVSServerException(status); + Session.run(getRepository(), parent, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + monitor = Policy.monitorFor(monitor); + monitor.beginTask(Policy.bind("RemoteFile.getLogEntries"), 100); //$NON-NLS-1$ + try { + final List entries = new ArrayList(); + IStatus status = Command.LOG.execute( + Command.NO_GLOBAL_OPTIONS, + new LocalOption[] { + Command.LOG.makeRevisionOption(info.getRevision())}, + new ICVSResource[] { RemoteFile.this }, + new LogListener(RemoteFile.this, entries), + Policy.subMonitorFor(monitor, 100)); + if (entries.size() == 1) { + entry = (ILogEntry)entries.get(0); + } + if (status.getCode() == CVSStatus.SERVER_ERROR) { + throw new CVSServerException(status); + } + } finally { + monitor.done(); } - } finally { - s.close(); } - } finally { - monitor.done(); - } + }, monitor); } return entry; } - /* - * Fetch the log entry corresponding to the receivers revision and set the entry - * instance variable to the result. If the fecth failed, entry will be null and - * the resulting IStatus will contain any errors. - */ - private IStatus getLogEntry(Session session, IProgressMonitor monitor) throws CVSException { - List entries = new ArrayList(); - IStatus status = Command.LOG.execute(session, - Command.NO_GLOBAL_OPTIONS, - new LocalOption[] { - Command.LOG.makeRevisionOption(info.getRevision())}, - new String[] { getName() }, - new LogListener(this, entries), - Policy.subMonitorFor(monitor, 10)); - if (entries.size() == 1) { - entry = (ILogEntry)entries.get(0); - } else { - // No log entry was fetch for the remote file. - entry = null; - } - return status; - } - /** * @see ICVSRemoteFile#getLogEntries() */ public ILogEntry[] getLogEntries(IProgressMonitor monitor) throws CVSException { - monitor = Policy.monitorFor(monitor); - monitor.beginTask(Policy.bind("RemoteFile.getLogEntries"), 100); //$NON-NLS-1$ - try { - // Perform a "cvs log..." with a custom message handler - final List entries = new ArrayList(); - IStatus status; - Session s = new Session(getRepository(), parent, false); - s.open(Policy.subMonitorFor(monitor, 10)); - QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness(); - try { - CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE); - status = Command.LOG.execute(s, Command.NO_GLOBAL_OPTIONS, Command.NO_LOCAL_OPTIONS, - new String[] { getName() }, new LogListener(this, entries), - Policy.subMonitorFor(monitor, 90)); - } finally { - CVSProviderPlugin.getPlugin().setQuietness(quietness); - s.close(); - } - if (status.getCode() == CVSStatus.SERVER_ERROR) { - throw new CVSServerException(status); + final List entries = new ArrayList(); + Session.run(getRepository(), parent, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + monitor = Policy.monitorFor(monitor); + monitor.beginTask(Policy.bind("RemoteFile.getLogEntries"), 100); //$NON-NLS-1$ + QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness(); + try { + CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE); + IStatus status = Command.LOG.execute(Command.NO_GLOBAL_OPTIONS, Command.NO_LOCAL_OPTIONS, + new ICVSResource[] { RemoteFile.this }, new LogListener(RemoteFile.this, entries), + Policy.subMonitorFor(monitor, 100)); + if (status.getCode() == CVSStatus.SERVER_ERROR) { + throw new CVSServerException(status); + } + } finally { + CVSProviderPlugin.getPlugin().setQuietness(quietness); + monitor.done(); + } } - return (ILogEntry[])entries.toArray(new ILogEntry[entries.size()]); - } finally { - monitor.done(); - } + }, monitor); + return (ILogEntry[])entries.toArray(new ILogEntry[entries.size()]); } /** @@ -352,10 +332,6 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { public ResourceSyncInfo getSyncInfo() { return info; } - - public ICVSFolder getParent() { - return parent; - } /** * @see ICVSResource#getRelativePath(ICVSFolder) diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolder.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolder.java index 0db7fcdab..3ddce36cc 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolder.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolder.java @@ -12,6 +12,7 @@ import java.util.List; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.team.core.TeamException; @@ -84,13 +85,13 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC } // Get the file revisions for the given filenames - protected void updateFileRevisions(Session session, String[] fileNames, IProgressMonitor monitor) throws CVSException { + protected void updateFileRevisions(final ICVSFile[] files, IProgressMonitor monitor) throws CVSException { final int[] count = new int[] {0}; // Create a listener for receiving the revision info - IStatusListener listener = new IStatusListener() { - public void fileStatus(IPath path, String remoteRevision) { + final IStatusListener listener = new IStatusListener() { + public void fileStatus(ICVSFolder parent, IPath path, String remoteRevision) { if (remoteRevision == IStatusListener.FOLDER_REVISION) // Ignore any folders return; @@ -98,7 +99,7 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC ((RemoteFile)getChild(path.lastSegment())).setRevision(remoteRevision); count[0]++; } catch (CVSException e) { - // The count wil be off to indicate an error + // The count will be off to indicate an error } } }; @@ -107,20 +108,24 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness(); try { CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE); - IStatus status = Command.STATUS.execute(session, - Command.NO_GLOBAL_OPTIONS, - Command.NO_LOCAL_OPTIONS, - fileNames, - new StatusListener(listener), - Policy.subMonitorFor(monitor, 100)); - if (status.getCode() == CVSStatus.SERVER_ERROR) { - throw new CVSServerException(status); - } + Session.run(getRepository(), this, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + IStatus status = Command.STATUS.execute( + Command.NO_GLOBAL_OPTIONS, + Command.NO_LOCAL_OPTIONS, + files, + new StatusListener(listener), + monitor); + if (status.getCode() == CVSStatus.SERVER_ERROR) { + throw new CVSServerException(status); + } + } + }, monitor); } finally { CVSProviderPlugin.getPlugin().setQuietness(quietness); } - if (count[0] != fileNames.length) + if (count[0] != files.length) throw new CVSException(Policy.bind("RemoteFolder.errorFetchingRevisions")); //$NON-NLS-1$ } @@ -159,62 +164,63 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC * CVS will signal an error if a folder only contains subfolders when a tag is used. If we get this * error and we're looking for a folder, we need to reissue the command without a tag. */ - protected boolean exists(ICVSRemoteResource child, CVSTag tag, IProgressMonitor monitor) throws CVSException { + protected boolean exists(final ICVSRemoteResource child, CVSTag tag, IProgressMonitor monitor) throws CVSException { final IProgressMonitor progress = Policy.monitorFor(monitor); progress.beginTask(Policy.bind("RemoteFolder.exists"), 100); //$NON-NLS-1$ try { // Create the listener for remote files and folders final boolean[] exists = new boolean[] {true}; - IUpdateMessageListener listener = new IUpdateMessageListener() { - public void directoryInformation(IPath path, boolean newDirectory) { + final IUpdateMessageListener listener = new IUpdateMessageListener() { + public void directoryInformation(ICVSFolder parent, IPath path, boolean newDirectory) { exists[0] = true; } - public void directoryDoesNotExist(IPath path) { + public void directoryDoesNotExist(ICVSFolder parent, IPath path) { exists[0] = false; } - public void fileInformation(int type, String filename) { + public void fileInformation(int type, ICVSFolder parent, String filename) { // We can't set exists true here as we may get a conflict on a deleted file. // i.e. remote files are always communicated to the server as modified. } - public void fileDoesNotExist(String filename) { + public void fileDoesNotExist(ICVSFolder parent, String filename) { exists[0] = false; } }; // Build the local options - List localOptions = new ArrayList(); + final List localOptions = new ArrayList(); localOptions.add(Update.RETRIEVE_ABSENT_DIRECTORIES); if (tag != null && tag.getType() != CVSTag.HEAD) localOptions.add(Update.makeTagOption(tag)); // Retrieve the children and any file revision numbers in a single connection - // Perform a "cvs -n update -d -r tagName folderName" with custom message and error handlers - IStatus status; - Session s = new Session(getRepository(), this, false); - s.open(Policy.subMonitorFor(progress, 10)); - try { - status = Command.UPDATE.execute(s, - new GlobalOption[] { Command.DO_NOT_CHANGE }, - (LocalOption[]) localOptions.toArray(new LocalOption[localOptions.size()]), - new String[] { child.getName() }, new UpdateListener(listener), - Policy.subMonitorFor(progress, 90)); - } finally { - s.close(); - } - if (status.getCode() == CVSStatus.SERVER_ERROR) { - CVSServerException e = new CVSServerException(status); - if ( ! e.isNoTagException() || ! child.isContainer()) { - if (e.containsErrors()) { - throw e; + // Perform a "cvs -n update -d -r tagName folderName" with custom message and error handlers + final boolean[] retry = new boolean[] {false}; + Session.run(getRepository(), this, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + IStatus status = Command.UPDATE.execute( + new GlobalOption[] { Command.DO_NOT_CHANGE }, + (LocalOption[]) localOptions.toArray(new LocalOption[localOptions.size()]), + new ICVSResource[] { child }, new UpdateListener(listener), + monitor); + if (status.getCode() == CVSStatus.SERVER_ERROR) { + CVSServerException e = new CVSServerException(status); + if (e.isNoTagException() && child.isContainer()) { + retry[0] = true; + } else { + if (e.containsErrors()) { + throw e; + } + } } } - // we now know that this is an exception caused by a cvs bug. - // if the folder has no files in it (just subfolders) cvs does not respond with the subfolders... - // workaround: retry the request with no tag to get the directory names (if any) + }, Policy.subMonitorFor(progress, 80)); + + // We now know that this is an exception caused by a cvs bug. + // If the folder has no files in it (just subfolders) CVS does not respond with the subfolders... + // Workaround: Retry the request with no tag to get the directory names (if any) + if (retry[0]) { Policy.checkCanceled(progress); - if (e.isNoTagException()) { - return exists(child, null, progress); - } + return exists(child, null, Policy.subMonitorFor(progress, 20)); } return exists[0]; } finally { @@ -248,75 +254,106 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC final List newRemoteDirectories = new ArrayList(); final List newRemoteFiles = new ArrayList(); final boolean[] exists = new boolean[] {true}; - IUpdateMessageListener listener = new IUpdateMessageListener() { - public void directoryInformation(IPath path, boolean newDirectory) { - if (newDirectory && path.segmentCount() == 1) { - newRemoteDirectories.add(path.lastSegment()); - progress.subTask(path.lastSegment().toString()); - progress.worked(1); + final List exceptions = new ArrayList(); + final IUpdateMessageListener listener = new IUpdateMessageListener() { + public void directoryInformation(ICVSFolder parent, IPath path, boolean newDirectory) { + try { + path = getRelativePathRootRelativePath(parent, path); + if (newDirectory && path.segmentCount() == 1) { + newRemoteDirectories.add(path.lastSegment()); + progress.subTask(path.lastSegment().toString()); + progress.worked(1); + } + } catch (CVSException e) { + exceptions.add(e); } } - public void directoryDoesNotExist(IPath path) { - if (path.isEmpty()) { - // the remote folder doesn't exist - exists[0] = false; + public void directoryDoesNotExist(ICVSFolder parent, IPath path) { + try { + path = getRelativePathRootRelativePath(parent, path); + if (path.isEmpty()) { + // the remote folder doesn't exist + exists[0] = false; + } + } catch (CVSException e) { + exceptions.add(e); } } - public void fileInformation(int type, String filename) { - IPath filePath = new Path(filename); - if( filePath.segmentCount() == 1 ) { - String properFilename = filePath.lastSegment(); - newRemoteFiles.add(properFilename); - progress.subTask(properFilename); - progress.worked(1); + public void fileInformation(int type, ICVSFolder parent, String filename) { + try { + IPath filePath = new Path(filename); + filePath = getRelativePathRootRelativePath(parent, filePath); + if( filePath.segmentCount() == 1 ) { + String properFilename = filePath.lastSegment(); + newRemoteFiles.add(properFilename); + progress.subTask(properFilename); + progress.worked(1); + } + } catch (CVSException e) { + exceptions.add(e); } } - public void fileDoesNotExist(String filename) { + public void fileDoesNotExist(ICVSFolder parent, String filename) { } }; // Build the local options - List localOptions = new ArrayList(); + final List localOptions = new ArrayList(); localOptions.add(Update.RETRIEVE_ABSENT_DIRECTORIES); if (tag != null) localOptions.add(Update.makeTagOption(tag)); // Retrieve the children and any file revision numbers in a single connection - Session s = new Session(getRepository(), this, false); - s.open(Policy.subMonitorFor(progress, 10)); try { - // Perform a "cvs -n update -d -r tagName folderName" - IStatus status = Command.UPDATE.execute(s, - new GlobalOption[] { Command.DO_NOT_CHANGE }, - (LocalOption[])localOptions.toArray(new LocalOption[localOptions.size()]), - new String[] { Session.CURRENT_LOCAL_FOLDER }, - new UpdateListener(listener), - Policy.subMonitorFor(progress, 60)); - if (status.getCode() == CVSStatus.SERVER_ERROR) { - throw new CVSServerException(status); - } - if (progress.isCanceled()) { - throw new OperationCanceledException(); - } - if (! exists[0]) { - throw new CVSException(new CVSStatus(CVSStatus.ERROR, CVSStatus.DOES_NOT_EXIST, Policy.bind("RemoteFolder.doesNotExist", getRepositoryRelativePath()))); //$NON-NLS-1$ - } - - // Convert the file and folder names to IManagedResources - List result = new ArrayList(); - for (int i=0;i<newRemoteFiles.size();i++) { - result.add(new RemoteFile(this, Update.STATE_NONE, (String)newRemoteFiles.get(i), tag)); - } - for (int i=0;i<newRemoteDirectories.size();i++) - result.add(new RemoteFolder(this, getRepository(), new Path(getRepositoryRelativePath()).append((String)newRemoteDirectories.get(i)), tag)); - children = (ICVSRemoteResource[])result.toArray(new ICVSRemoteResource[0]); - - // Get the revision numbers for the files - if (newRemoteFiles.size() > 0) { - updateFileRevisions(s, (String[])newRemoteFiles.toArray(new String[newRemoteFiles.size()]), - Policy.subMonitorFor(progress, 30)); - } else { - progress.worked(30); - } + Session.run(getRepository(), this, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + // Perform a "cvs -n update -d -r tagName folderName" + monitor.beginTask(null, 100); //$NON-NLS-1$ + IStatus status = Command.UPDATE.execute( + new GlobalOption[] { Command.DO_NOT_CHANGE }, + (LocalOption[])localOptions.toArray(new LocalOption[localOptions.size()]), + new ICVSResource[] { RemoteFolder.this }, + new UpdateListener(listener), + Policy.subMonitorFor(monitor, 60)); + if (status.getCode() == CVSStatus.SERVER_ERROR) { + throw new CVSServerException(status); + } + if (! exists[0]) { + throw new CVSException(new CVSStatus(CVSStatus.ERROR, CVSStatus.DOES_NOT_EXIST, Policy.bind("RemoteFolder.doesNotExist", getRepositoryRelativePath()))); //$NON-NLS-1$ + } + // Report any exceptions that occured fetching the members + if ( ! exceptions.isEmpty()) { + if (exceptions.size() == 1) { + throw (CVSException)exceptions.get(0); + } else { + MultiStatus multi = new MultiStatus(CVSProviderPlugin.ID, 0, Policy.bind("RemoteFolder.errorFetchingMembers"), null); //$NON-NLS-1$ + for (int i = 0; i < exceptions.size(); i++) { + multi.merge(((CVSException)exceptions.get(i)).getStatus()); + } + throw new CVSException(multi); + } + } + // Convert the file names to remote resources + Policy.checkCanceled(monitor); + List result = new ArrayList(); + List remoteFiles = new ArrayList(); + for (int i=0;i<newRemoteFiles.size();i++) { + RemoteFile newFile = new RemoteFile(RemoteFolder.this, Update.STATE_NONE, (String)newRemoteFiles.get(i), tag); + result.add(newFile); + remoteFiles.add(newFile); + } + // Convert the folder names to remote resources + for (int i=0;i<newRemoteDirectories.size();i++) + result.add(new RemoteFolder(RemoteFolder.this, getRepository(), new Path(getRepositoryRelativePath()).append((String)newRemoteDirectories.get(i)), tag)); + children = (ICVSRemoteResource[])result.toArray(new ICVSRemoteResource[0]); + // Get the revision numbers for the files + if (remoteFiles.size() > 0) { + updateFileRevisions((ICVSFile[])remoteFiles.toArray(new ICVSFile[remoteFiles.size()]), + Policy.subMonitorFor(monitor, 40)); + } else { + monitor.worked(40); + } + } + }, Policy.subMonitorFor(progress, 80)); } catch (CVSServerException e) { if ( ! e.isNoTagException() && e.containsErrors()) throw e; @@ -326,7 +363,7 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC // if the folder has no files in it (just subfolders) cvs does not respond with the subfolders... // workaround: retry the request with no tag to get the directory names (if any) Policy.checkCanceled(progress); - children = getMembers(null, progress); + children = getMembers(null, Policy.subMonitorFor(progress, 20)); // the returned children must be given the original tag for (int i = 0; i < children.length; i++) { ICVSRemoteResource remoteResource = children[i]; @@ -334,10 +371,8 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC ((RemoteFolder)remoteResource).setTag(tag); } } - } finally { - s.close(); } - + // We need to remember the children that were fetched in order to support file // operations that depend on the parent knowing about the child (i.e. RemoteFile#getContents) return children; @@ -403,10 +438,6 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC return Command.NO_LOCAL_OPTIONS; } - protected String getLocalPath() { - throw new UnsupportedOperationException(); - } - public String getRepositoryRelativePath() { // The REPOSITORY property of the folder info is the repository relative path return getFolderSyncInfo().getRepository(); @@ -416,18 +447,19 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC * @see ICVSResource#getRelativePath(ICVSFolder) */ public String getRelativePath(ICVSFolder ancestor) throws CVSException { - - if (ancestor == this) - return Session.CURRENT_LOCAL_FOLDER; - - RemoteResource rootFolder; - try { - rootFolder = (RemoteResource)ancestor; - } catch (ClassCastException e) { - throw new CVSException(Policy.bind("RemoteResource.invalidResourceClass"),e); //$NON-NLS-1$ + // Check to see if the receiver is the ancestor + if (ancestor == this) return Session.CURRENT_LOCAL_FOLDER; + // Otherwise, we need a parent to continue + if (parent == null) { + throw new CVSException(Policy.bind("RemoteFolder.invalidChild", getName(), ancestor.getName())); //$NON-NLS-1$ + } + // Append the receivers name to the parents path relative to the ancestor + String parentPath = parent.getRelativePath(ancestor); + if (parentPath.equals(Session.CURRENT_LOCAL_FOLDER) || parentPath.length() == 0) { + return getName(); + } else { + return Util.appendPath(parentPath, getName()); } - - return Util.getRelativePath(rootFolder.getLocalPath(), getLocalPath()); } public ICVSRepositoryLocation getRepository() { @@ -473,7 +505,7 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC * does not exist, an exception is thrown. */ public ICVSResource getChild(String path) throws CVSException { - if (path.equals(Session.CURRENT_LOCAL_FOLDER)) + if (path.equals(Session.CURRENT_LOCAL_FOLDER) || path.length() == 0) return this; ICVSRemoteResource[] children = getChildren(); if (children == null) @@ -596,59 +628,57 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC * Update the file revision for the given child such that the revision is the one in the given branch. * Return true if the file exists and false otherwise */ - protected boolean updateRevision(ICVSRemoteFile child, CVSTag tag, IProgressMonitor monitor) throws CVSException { - + protected boolean updateRevision(final ICVSRemoteFile child, CVSTag tag, IProgressMonitor monitor) throws CVSException { + final IProgressMonitor progress = Policy.monitorFor(monitor); + progress.beginTask(null, 100); //$NON-NLS-1$ ICVSRemoteResource[] oldChildren = children; try { children = new ICVSRemoteResource[] {child}; // Create the listener for remote files and folders final boolean[] exists = new boolean[] {true}; - IUpdateMessageListener listener = new IUpdateMessageListener() { - public void directoryInformation(IPath path, boolean newDirectory) { + final IUpdateMessageListener listener = new IUpdateMessageListener() { + public void directoryInformation(ICVSFolder parent, IPath path, boolean newDirectory) { } - public void directoryDoesNotExist(IPath path) { + public void directoryDoesNotExist(ICVSFolder parent, IPath path) { // If we get this, we can assume that the parent directory no longer exists exists[0] = false; } - public void fileInformation(int type, String filename) { + public void fileInformation(int type, ICVSFolder parent, String filename) { // The file was found and has a different revision try { - ((RemoteFile)getChild(filename)).setWorkspaceSyncState(type); + ((RemoteFile)parent.getChild(filename)).setWorkspaceSyncState(type); } catch(CVSException e) { exists[0] = false; } exists[0] = true; } - public void fileDoesNotExist(String filename) { + public void fileDoesNotExist(ICVSFolder parent, String filename) { exists[0] = false; } }; // Build the local options - List localOptions = new ArrayList(); + final List localOptions = new ArrayList(); if (tag != null && tag.getType() != CVSTag.HEAD) localOptions.add(Update.makeTagOption(tag)); // Retrieve the children and any file revision numbers in a single connection - Session s = new Session(getRepository(), this, false); - s.open(monitor); - try { - // Perform a "cvs -n update -d -r tagName fileName" with custom message and error handlers - Command.UPDATE.execute(s, - new GlobalOption[] { Command.DO_NOT_CHANGE }, - (LocalOption[]) localOptions.toArray(new LocalOption[localOptions.size()]), - new String[] { child.getName() }, - new UpdateListener(listener), - monitor); - - if (!exists[0]) return false; - updateFileRevisions(s, new String[] {child.getName()}, monitor); - return true; - - } finally { - s.close(); - } + Session.run(getRepository(), this, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + // Perform a "cvs -n update -d -r tagName fileName" with custom message and error handlers + Command.UPDATE.execute( + new GlobalOption[] { Command.DO_NOT_CHANGE }, + (LocalOption[]) localOptions.toArray(new LocalOption[localOptions.size()]), + new ICVSResource[] { child }, + new UpdateListener(listener), + monitor); + } + }, Policy.subMonitorFor(progress, 70)); + + if (!exists[0]) return false; + updateFileRevisions(new ICVSFile[] {child}, Policy.subMonitorFor(progress, 30)); + return true; } finally { children = oldChildren; } @@ -693,4 +723,24 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC throw new CVSException(e.getStatus()); } } + + public boolean equals(Object target) { + if ( ! super.equals(target)) return false; + RemoteFolder folder = (RemoteFolder)target; + CVSTag tag1 = getTag(); + CVSTag tag2 = folder.getTag(); + if (tag1 == null) tag1 = CVSTag.DEFAULT; + if (tag2 == null) tag2 = CVSTag.DEFAULT; + return tag1.equals(tag2); + } + + protected IPath getRelativePathRootRelativePath(ICVSFolder root, IPath path) throws CVSException { + if (root == this) { + return path; + } + if (path.isEmpty()) { + throw new CVSException(Policy.bind("RemoteFolder.invalidPath")); + } + return getRelativePathRootRelativePath((ICVSFolder)root.getChild(path.segment(0)), path.removeFirstSegments(1)); + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTree.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTree.java index a4219f30a..e784c3e3e 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTree.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTree.java @@ -57,11 +57,5 @@ public class RemoteFolderTree extends RemoteFolder { ((ICVSResource)children[i]).accept(visitor); } } - - protected String getLocalPath() { - if (parent == null) - return ""; //$NON-NLS-1$ - return Util.appendPath(parent.getLocalPath(), getName()); - } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java index 90e81acd0..430e3b10b 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java @@ -41,9 +41,6 @@ public abstract class RemoteResource extends PlatformObject implements ICVSRemot return info.getName(); } - protected String getLocalPath() { - return Util.appendPath(parent.getLocalPath(), getName()); - } /* * @see ICVSRemoteResource#getParent() */ @@ -93,8 +90,8 @@ public abstract class RemoteResource extends PlatformObject implements ICVSRemot * @see ICVSResource#getParent() */ public ICVSFolder getParent() { - throw new UnsupportedOperationException(Policy.bind("RemoteResource.invalidOperation")); //$NON-NLS-1$ - } + return parent; + } /* * @see ICVSResource#isIgnored() @@ -107,7 +104,7 @@ public abstract class RemoteResource extends PlatformObject implements ICVSRemot * @see ICVSResource#isManaged() */ public boolean isManaged() { - return true; + return parent != null; } /* diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareEditorInput.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareEditorInput.java index ed7b11c69..3bd5a6c85 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareEditorInput.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareEditorInput.java @@ -35,12 +35,13 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.team.core.TeamException; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.CVSTag; -import org.eclipse.team.internal.ccvs.core.CVSTeamProvider; import org.eclipse.team.internal.ccvs.core.ICVSFile; import org.eclipse.team.internal.ccvs.core.ICVSRemoteFile; import org.eclipse.team.internal.ccvs.core.ICVSRemoteFolder; import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; import org.eclipse.team.internal.ccvs.core.ICVSResource; +import org.eclipse.team.internal.ccvs.core.ICVSRunnable; +import org.eclipse.team.internal.ccvs.core.client.Session; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; @@ -305,7 +306,7 @@ public class CVSCompareEditorInput extends CompareEditorInput { * Method declared on CompareEditorInput */ protected Object prepareInput(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { - boolean threeWay = ancestor != null; + final boolean threeWay = ancestor != null; if (right == null || left == null) { setMessage(Policy.bind("CVSCompareEditorInput.different")); //$NON-NLS-1$ return null; @@ -313,7 +314,7 @@ public class CVSCompareEditorInput extends CompareEditorInput { initLabels(); - Differencer d = new Differencer() { + final Differencer d = new Differencer() { protected boolean contentsEqual(Object input1, Object input2) { int compare = teamEqual(input1, input2); if (compare == NODE_EQUAL) { @@ -349,22 +350,30 @@ public class CVSCompareEditorInput extends CompareEditorInput { } }; - try { - monitor.beginTask(Policy.bind("CVSCompareEditorInput.comparing"), 30); //$NON-NLS-1$ - + try { // do the diff - IProgressMonitor sub = new SubProgressMonitor(monitor, 30); - try { - sub.beginTask(Policy.bind("CVSCompareEditorInput.comparing"), 100); //$NON-NLS-1$ - return d.findDifferences(threeWay, sub, null, ancestor, left, right); - } finally { - sub.done(); - } + final Object[] result = new Object[] { null }; + Session.run(null, null, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + monitor.beginTask(Policy.bind("CVSCompareEditorInput.comparing"), 30); //$NON-NLS-1$ + IProgressMonitor sub = new SubProgressMonitor(monitor, 30); + sub.beginTask(Policy.bind("CVSCompareEditorInput.comparing"), 100); //$NON-NLS-1$ + try { + result[0] = d.findDifferences(threeWay, sub, null, ancestor, left, right); + } finally { + sub.done(); + } + } + }, monitor); + return result[0]; } catch (OperationCanceledException e) { throw new InterruptedException(e.getMessage()); } catch (RuntimeException e) { handle(e); - return null; + return null; + } catch (CVSException e) { + handle(e); + return null; } finally { monitor.done(); } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/merge/MergeEditorInput.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/merge/MergeEditorInput.java index b44bea365..5481d6870 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/merge/MergeEditorInput.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/merge/MergeEditorInput.java @@ -5,16 +5,24 @@ package org.eclipse.team.internal.ccvs.ui.merge; * All Rights Reserved. */ +import java.lang.reflect.InvocationTargetException; + import org.eclipse.compare.structuremergeviewer.ICompareInput; +import org.eclipse.compare.structuremergeviewer.IDiffContainer; +import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.widgets.Composite; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.sync.IRemoteResource; import org.eclipse.team.core.sync.IRemoteSyncElement; +import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.CVSTag; +import org.eclipse.team.internal.ccvs.core.ICVSFolder; +import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; +import org.eclipse.team.internal.ccvs.core.ICVSRunnable; +import org.eclipse.team.internal.ccvs.core.client.Session; import org.eclipse.team.internal.ccvs.core.resources.CVSRemoteSyncElement; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.ui.Policy; @@ -75,4 +83,38 @@ public class MergeEditorInput extends CVSSyncCompareInput { // for merge purposes as equal. return IRemoteSyncElement.GRANULARITY_CONTENTS; } + + /** + * Wrap the input preparation in a CVS session run so open sessions will be reused + */ + public Object prepareInput(IProgressMonitor pm) throws InterruptedException, InvocationTargetException { + final Object[] result = new Object[] { null }; + final Exception[] exception = new Exception[] {null}; + try { + Session.run(null, null, false, new ICVSRunnable() { + public void run(IProgressMonitor monitor) throws CVSException { + try { + result[0] = MergeEditorInput.super.prepareInput(monitor); + } catch (InterruptedException e) { + exception[0] = e; + } catch (InvocationTargetException e) { + exception[0] = e; + } + } + }, pm); + } catch (CVSException e) { + throw new InvocationTargetException(e); + } + + if (exception[0] != null) { + if (exception[0] instanceof InvocationTargetException) { + throw (InvocationTargetException)exception[0]; + } else { + throw (InterruptedException)exception[0]; + } + } + + return result[0]; + } + }
\ No newline at end of file |