diff options
author | Michael Valenta | 2003-10-22 14:54:17 +0000 |
---|---|---|
committer | Michael Valenta | 2003-10-22 14:54:17 +0000 |
commit | 2eb76c226da3ac930122c29d1c16c7a3083697fe (patch) | |
tree | efb38d8e49e7df3c0f38cf2209c917dbd4cf8c30 | |
parent | a2286f98c4e2ef45800dfe7ba51a825ab564e2d5 (diff) | |
download | eclipse.platform.team-2eb76c226da3ac930122c29d1c16c7a3083697fe.tar.gz eclipse.platform.team-2eb76c226da3ac930122c29d1c16c7a3083697fe.tar.xz eclipse.platform.team-2eb76c226da3ac930122c29d1c16c7a3083697fe.zip |
41738: Comparing two remote versions can result in many connectionsRoot_SynchronizeViewPageBook20031011
30 files changed, 1145 insertions, 142 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java index 48f244e15..8e66c0c7c 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java @@ -737,6 +737,10 @@ public class CVSProviderPlugin extends Plugin { Policy.DEBUG_CVS_PROTOCOL = value; } + public boolean isDebugProtocol() { + return Policy.DEBUG_CVS_PROTOCOL; + } + /* * Create the crash indicator file. This method returns true if the file * already existed, indicating that a crash occurred on the last invokation of diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java index e8188540f..6bc313765 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSTeamProvider.java @@ -649,7 +649,11 @@ public class CVSTeamProvider extends RepositoryProvider { Session session = new Session(workspaceRoot.getRemoteLocation(), workspaceRoot.getLocalRoot(), true /* output to console */); session.open(Policy.subMonitorFor(progress,10), false /* read-only */); try { - new PrepareForReplaceVisitor().visitResources(getProject(), resources, "CVSTeamProvider.scrubbingResource", depth, Policy.subMonitorFor(progress, 20)); //$NON-NLS-1$ + ICVSResource[] cvsResources = new ICVSResource[resources.length]; + for (int i = 0; i < cvsResources.length; i++) { + cvsResources[i] = CVSWorkspaceRoot.getCVSResourceFor(resources[i]); + } + new PrepareForReplaceVisitor().visitResources(getProject(), cvsResources, "CVSTeamProvider.scrubbingResource", depth, Policy.subMonitorFor(progress, 20)); //$NON-NLS-1$ List options = new ArrayList(); options.add(Update.IGNORE_LOCAL_CHANGES); 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 f23cc3f59..afba8870a 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 @@ -45,6 +45,7 @@ public abstract class Command extends Request { public final static Checkout CHECKOUT = new CheckoutWithOverwrite(); public final static Commit COMMIT = new Commit(); public final static Diff DIFF = new Diff(); + public final static RDiff RDIFF = new RDiff(); public final static Editors EDITORS = new Editors(); public final static Import IMPORT = new Import(); public final static Log LOG = new Log(); diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Diff.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Diff.java index 14d43e601..dc32ec188 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Diff.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Diff.java @@ -27,6 +27,7 @@ public class Diff extends Command { public static final LocalOption UNIFIED_FORMAT = new LocalOption("-u"); //$NON-NLS-1$ public static final LocalOption CONTEXT_FORMAT = new LocalOption("-c"); //$NON-NLS-1$ public static final LocalOption INCLUDE_NEWFILES = new LocalOption("-N"); //$NON-NLS-1$ + public static final LocalOption BRIEF = new LocalOption("--brief"); //$NON-NLS-1$ protected Diff() { } protected String getRequestId() { diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RDiff.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RDiff.java new file mode 100644 index 000000000..de27da825 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RDiff.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ccvs.core.client; + +import org.eclipse.team.internal.ccvs.core.CVSTag; + +public class RDiff extends RemoteCommand { + + /*** Local options: specific to rdiff ***/ + public static final LocalOption SUMMARY = new LocalOption("-s", null); //$NON-NLS-1$ + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.core.client.Request#getRequestId() + */ + protected String getRequestId() { + return "rdiff"; //$NON-NLS-1$ + } + + /** + * Makes a -r or -D option for a tag. + * Valid for: checkout export history rdiff update + */ + public static LocalOption makeTagOption(CVSTag tag) { + if (tag == null) tag = CVSTag.DEFAULT; + int type = tag.getType(); + switch (type) { + case CVSTag.BRANCH: + case CVSTag.VERSION: + case CVSTag.HEAD: + return new LocalOption("-r", tag.getName()); //$NON-NLS-1$ + case CVSTag.DATE: + return new LocalOption("-D", tag.getName()); //$NON-NLS-1$ + default: + // Unknow tag type!!! + throw new IllegalArgumentException(); + } + } +} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RTag.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RTag.java index a83cca00b..0baca4b3a 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RTag.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RTag.java @@ -98,8 +98,7 @@ public class RTag extends RemoteCommand { CVSTag sourceTag, CVSTag tag, ICVSRemoteResource[] arguments, IProgressMonitor monitor) throws CVSException { - ICVSResource[] resources = (ICVSResource[])Arrays.asList(arguments).toArray(new ICVSResource[arguments.length]); - String[] stringArguments = convertArgumentsForOpenSession(arguments); + String[] stringArguments = convertArgumentsForOpenSession(arguments, session); return execute(session, globalOptions, localOptions, sourceTag, tag, stringArguments, monitor); } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemoteCommand.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemoteCommand.java index 3343962a7..bc99a257d 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemoteCommand.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemoteCommand.java @@ -15,7 +15,6 @@ import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.internal.ccvs.core.CVSException; -import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; import org.eclipse.team.internal.ccvs.core.ICVSResource; /** @@ -42,12 +41,20 @@ public abstract class RemoteCommand extends Command { // do nothing } - protected String[] convertArgumentsForOpenSession(ICVSRemoteResource[] arguments) throws CVSException { - // Convert arguments - List stringArguments = new ArrayList(arguments.length); - for (int i = 0; i < arguments.length; i++) { - stringArguments.add(arguments[i].getRepositoryRelativePath()); - } - return (String[]) stringArguments.toArray(new String[stringArguments.size()]); + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.core.client.Command#convertArgumentsForOpenSession(org.eclipse.team.internal.ccvs.core.ICVSResource[], org.eclipse.team.internal.ccvs.core.client.Session) + */ + protected String[] convertArgumentsForOpenSession( + ICVSResource[] arguments, + Session openSession) + throws CVSException { + + // Convert arguments + List stringArguments = new ArrayList(arguments.length); + for (int i = 0; i < arguments.length; i++) { + stringArguments.add(arguments[i].getRepositoryRelativePath()); + } + return (String[]) stringArguments.toArray(new String[stringArguments.size()]); } + } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/CompareDiffListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/CompareDiffListener.java new file mode 100644 index 000000000..02e448576 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/CompareDiffListener.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ccvs.core.client.listeners; + +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; +import org.eclipse.team.internal.ccvs.core.CVSStatus; +import org.eclipse.team.internal.ccvs.core.ICVSFolder; +import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; +import org.eclipse.team.internal.ccvs.core.client.CommandOutputListener; + +/** + * This class interprets the output of "cvs diff --brief ..." in order to get the revisions + * of two compared versions of a project or folder. + */ +public class CompareDiffListener extends CommandOutputListener { + + private static ServerMessageLineMatcher LOCAL_FILE_MATCHER; + private static ServerMessageLineMatcher REMOTE_FILE_MATCHER; + private static ServerMessageLineMatcher REVISION_LINE_MATCHER; + + static { + try { + LOCAL_FILE_MATCHER = new ServerMessageLineMatcher( + "Index: (localFile:.*:localFile)", new String[] {"localFile"}); + REMOTE_FILE_MATCHER = new ServerMessageLineMatcher( + "RCS file: (remoteFile:.*:remoteFile),v", new String[] {"remoteFile"}); + REVISION_LINE_MATCHER = new ServerMessageLineMatcher( + "diff .* -r(leftRevision:.*:leftRevision) -r(rightRevision:.*:rightRevision)", new String[] {"leftRevision", "rightRevision"}); + } catch (CVSException e) { + // This is serious as the listener will not function properly + CVSProviderPlugin.log(e); + LOCAL_FILE_MATCHER = null; + REMOTE_FILE_MATCHER = null; + REVISION_LINE_MATCHER = null; + } + } + + private String localFilePath, remoteFilePath, leftRevision, rightRevision; + + private IFileDiffListener listener; + + public interface IFileDiffListener { + public void fileDiff( + String localFilePath, + String remoteFilePath, + String leftRevision, + String rightRevision); + } + + public CompareDiffListener(IFileDiffListener listener) { + this.listener = listener; + } + + public IStatus messageLine( + String line, + ICVSRepositoryLocation location, + ICVSFolder commandRoot, + IProgressMonitor monitor) { + // ignore any server messages + if (getServerMessage(line, location) != null) { + return OK; + } + Map map = LOCAL_FILE_MATCHER.processServerMessage(line); + if (map != null) { + localFilePath = (String)map.get("localFile"); + return OK; + } + map = REMOTE_FILE_MATCHER.processServerMessage(line); + if (map != null) { + remoteFilePath = (String)map.get("remoteFile"); + return OK; + } + map = REVISION_LINE_MATCHER.processServerMessage(line); + if (map != null) { + leftRevision = (String)map.get("leftRevision"); + rightRevision = (String)map.get("rightRevision"); + if (localFilePath == null || remoteFilePath == null) { + return new CVSStatus(IStatus.ERROR, "Unsupported message sequence received while comparing using CVS diff command"); + } + listener.fileDiff(localFilePath, remoteFilePath, leftRevision, rightRevision); + localFilePath = remoteFilePath = leftRevision = rightRevision = null; + return OK; + } + // Ignore all other lines + return OK; + } + + private IStatus handleUnknownDiffFormat(String line) { + return new CVSStatus(IStatus.ERROR, "Unknown message format received while comparing using CVS diff command: {0}" + line); + } + + public IStatus errorLine( + String line, + ICVSRepositoryLocation location, + ICVSFolder commandRoot, + IProgressMonitor monitor) { + // ignore server messages for now - this is used only with the diff + // request and the errors can be safely ignored. + if (getServerMessage(line, location) != null) { + return OK; + } + return super.errorLine(line, location, commandRoot, monitor); + } + +} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IMessagePatterns.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IMessagePatterns.java new file mode 100644 index 000000000..e3207ec7c --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/IMessagePatterns.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ccvs.core.client.listeners; + +import org.eclipse.team.internal.ccvs.core.util.Util; + +/** + * This class contains the default server message patterns + */ +public interface IMessagePatterns { + + public static final String SERVER_MESSAGE_PREFIX = "\\w* \\w*: "; //$NON-NLS-1$ + public static final String SERVER_ABORTED_MESSAGE_PREFIX = "\\w* [\\w* aborted]: "; //$NON-NLS-1$ + + // TODO: These patterns could be more specific but this would require non-capturing + // groups which currently throw off variable matching + public static final String TAG_PATTERN = "\\w*"; //$NON-NLS-1$ + public static final String REVISION_PATTERN = ".*"; //$NON-NLS-1$ + public static final String FILE_PATH_PATTERN = ".*"; //$NON-NLS-1$ + + // TODO: It would be better if the prefix was optional but this requires the use of a capturing group which throws the group count off + public static final String RDIFF_DIRECTORY = SERVER_MESSAGE_PREFIX + "Diffing " + Util.getVariablePattern(FILE_PATH_PATTERN, "remoteFolderPath"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String RDIFF_SUMMARY_FILE_DIFF = "File " + Util.getVariablePattern(FILE_PATH_PATTERN, "remoteFilePath") + " changed from revision " + Util.getVariablePattern(REVISION_PATTERN, "leftRevision") + " to " + Util.getVariablePattern(REVISION_PATTERN, "rightRevision"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + public static final String RDIFF_SUMMARY_NEW_FILE = "File " + Util.getVariablePattern(FILE_PATH_PATTERN, "remoteFilePath") + " is new; " + TAG_PATTERN + " revision " + Util.getVariablePattern(REVISION_PATTERN, "rightRevision"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + public static final String RDIFF_SUMMARY_DELETED_FILE = "File " + Util.getVariablePattern(FILE_PATH_PATTERN, "remoteFilePath") + " is removed; not included in release tag " + TAG_PATTERN; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + // This format was introduced in 1.11.7 + public static final String RDIFF_SUMMARY_DELETED_FILE2 = "File " + Util.getVariablePattern(FILE_PATH_PATTERN, "remoteFilePath") + " is removed; " + TAG_PATTERN + " revision " + Util.getVariablePattern(REVISION_PATTERN, "leftRevision"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ +} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/RDiffSummaryListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/RDiffSummaryListener.java new file mode 100644 index 000000000..29d2ec260 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/RDiffSummaryListener.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ccvs.core.client.listeners; + +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; +import org.eclipse.team.internal.ccvs.core.ICVSFolder; +import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; +import org.eclipse.team.internal.ccvs.core.client.CommandOutputListener; + +/** + * This class parses the messages recieved in response to an "cvs rdiff -s ..." command + */ +public class RDiffSummaryListener extends CommandOutputListener { + + private static final String RIGHT_REVISION_VARIABLE_NAME = "rightRevision"; //$NON-NLS-1$ + private static final String LEFT_REVISION_VARIABLE_NAME = "leftRevision"; //$NON-NLS-1$ + private static final String REMOTE_FILE_PATH_VARIABLE_NAME = "remoteFilePath"; //$NON-NLS-1$ + private static final String REMOTE_FOLDER_PATH_VARIABLE_NAME = "remoteFolderPath"; //$NON-NLS-1$ + + private IFileDiffListener listener; + private static ServerMessageLineMatcher DIRECTORY_MATCHER; + private static ServerMessageLineMatcher FILE_DIFF_MATCHER; + private static ServerMessageLineMatcher NEW_FILE_MATCHER; + private static ServerMessageLineMatcher DELETED_FILE_MATCHER; + private static ServerMessageLineMatcher DELETED_FILE_MATCHER2; + + static { + // TODO: temprary until proper lifecycle is defined + initializePatterns(); + } + public static void initializePatterns() { + try { + DIRECTORY_MATCHER = new ServerMessageLineMatcher( + IMessagePatterns.RDIFF_DIRECTORY, new String[] {REMOTE_FOLDER_PATH_VARIABLE_NAME}); + FILE_DIFF_MATCHER = new ServerMessageLineMatcher( + IMessagePatterns.RDIFF_SUMMARY_FILE_DIFF, new String[] {REMOTE_FILE_PATH_VARIABLE_NAME, LEFT_REVISION_VARIABLE_NAME, RIGHT_REVISION_VARIABLE_NAME}); + NEW_FILE_MATCHER = new ServerMessageLineMatcher( + IMessagePatterns.RDIFF_SUMMARY_NEW_FILE, new String[] {REMOTE_FILE_PATH_VARIABLE_NAME, RIGHT_REVISION_VARIABLE_NAME}); + DELETED_FILE_MATCHER = new ServerMessageLineMatcher( + IMessagePatterns.RDIFF_SUMMARY_DELETED_FILE, new String[] {REMOTE_FILE_PATH_VARIABLE_NAME}); + DELETED_FILE_MATCHER2 = new ServerMessageLineMatcher( + IMessagePatterns.RDIFF_SUMMARY_DELETED_FILE2, new String[] {REMOTE_FILE_PATH_VARIABLE_NAME, LEFT_REVISION_VARIABLE_NAME}); + } catch (CVSException e) { + // This is serious as the listener will not function properly + CVSProviderPlugin.log(e); + } + } + + public interface IFileDiffListener { + public void fileDiff( + String remoteFilePath, + String leftRevision, + String rightRevision); + public void newFile( + String remoteFilePath, + String rightRevision); + public void deletedFile( + String remoteFilePath, + String leftRevision); + public void directory(String remoteFolderPath); + } + + public RDiffSummaryListener(IFileDiffListener listener) { + this.listener = listener; + } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.core.client.listeners.ICommandOutputListener#messageLine(java.lang.String, org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation, org.eclipse.team.internal.ccvs.core.ICVSFolder, org.eclipse.core.runtime.IProgressMonitor) + */ + public IStatus messageLine( + String line, + ICVSRepositoryLocation location, + ICVSFolder commandRoot, + IProgressMonitor monitor) { + + Map variables = FILE_DIFF_MATCHER.processServerMessage(line); + if (variables != null) { + listener.fileDiff( + (String)variables.get(REMOTE_FILE_PATH_VARIABLE_NAME), + (String)variables.get(LEFT_REVISION_VARIABLE_NAME), + (String)variables.get(RIGHT_REVISION_VARIABLE_NAME)); + return OK; + } + + variables = NEW_FILE_MATCHER.processServerMessage(line); + if (variables != null) { + listener.newFile( + (String)variables.get(REMOTE_FILE_PATH_VARIABLE_NAME), + (String)variables.get(RIGHT_REVISION_VARIABLE_NAME)); + return OK; + } + + variables = DELETED_FILE_MATCHER.processServerMessage(line); + if (variables != null) { + listener.deletedFile( + (String)variables.get(REMOTE_FILE_PATH_VARIABLE_NAME), + null); + return OK; + } + + variables = DELETED_FILE_MATCHER2.processServerMessage(line); + if (variables != null) { + listener.deletedFile( + (String)variables.get(REMOTE_FILE_PATH_VARIABLE_NAME), + (String)variables.get(LEFT_REVISION_VARIABLE_NAME)); + return OK; + } + + return super.messageLine(line, location, commandRoot, monitor); + } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.core.client.listeners.ICommandOutputListener#errorLine(java.lang.String, org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation, org.eclipse.team.internal.ccvs.core.ICVSFolder, org.eclipse.core.runtime.IProgressMonitor) + */ + public IStatus errorLine( + String line, + ICVSRepositoryLocation location, + ICVSFolder commandRoot, + IProgressMonitor monitor) { + + Map variables = DIRECTORY_MATCHER.processServerMessage(line); + if (variables != null) { + listener.directory( + (String)variables.get(REMOTE_FOLDER_PATH_VARIABLE_NAME)); + return OK; + } + + return super.errorLine(line, location, commandRoot, monitor); + } + +} diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ServerMessageLineMatcher.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ServerMessageLineMatcher.java new file mode 100644 index 000000000..3e42ee1a6 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ServerMessageLineMatcher.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ccvs.core.client.listeners; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.util.Assert; +import org.eclipse.team.internal.ccvs.core.Policy; + +/** + * This class extracts matches server lines to expected patterns and extracts + * required information from the line. + */ +public class ServerMessageLineMatcher { + + protected static final Pattern VARIABLE_MATCHING_PATTERN = Pattern.compile("(\\((\\w*):.*:\\2\\))"); //$NON-NLS-1$ + + Pattern pattern; + String[] variables; + + public ServerMessageLineMatcher(String template, String[] expectedVariables) throws CVSException { + // Extract the variable names from the template + Matcher matcher = VARIABLE_MATCHING_PATTERN.matcher(template); + List variables = new ArrayList(); + while (matcher.find()) { + if (matcher.groupCount() != 2) { + throw new CVSException(Policy.bind("ServerMessageLineMatcher.5", template)); //$NON-NLS-1$ + } + variables.add(matcher.group(2)); + } + ensureMatches(template, variables, expectedVariables); + this.variables = (String[]) variables.toArray(new String[variables.size()]); + + // Modify the template so it can be used to match message lines from the server + // (i.e. remove the variable markup) + for (Iterator iter = variables.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + template = template.replaceAll(element + ":", ""); //$NON-NLS-1$ //$NON-NLS-2$ + template = template.replaceAll(":" + element, ""); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Ensure that the number of groups in the pattern match the number of variables + int count = 0; + int start = -1; + while ((start = template.indexOf('(', start + 1)) != -1) { + count++; + } + if (count != variables.size()) { + throw new CVSException(Policy.bind("ServerMessageLineMatcher.6", template)); //$NON-NLS-1$ + } + + // Create the pattern fir matching lines from the server + this.pattern = Pattern.compile(template); + } + + /* + * Throw an exception if the found variables do not match the expected variables + */ + private void ensureMatches(String template, List variables, String[] expectedVariables) throws CVSException { + for (int i = 0; i < expectedVariables.length; i++) { + String expected = expectedVariables[i]; + if (!variables.contains(expected)) { + throw new CVSException(Policy.bind("ServerMessageLineMatcher.7", expected, template)); //$NON-NLS-1$ + } + } + } + + public Map processServerMessage(String line) { + Matcher matcher = pattern.matcher(line); + if (!matcher.find()) return null; + Assert.isTrue(matcher.groupCount() == variables.length); + Map result = new HashMap(); + for (int i = 1; i <= matcher.groupCount(); i++) { + result.put(variables[i - 1], matcher.group(i)); + } + return result; + } + + public boolean matches(String line) { + Matcher matcher = pattern.matcher(line); + return (matcher.find()); + } + +} 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 3eb870416..aa23fa7fb 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 @@ -330,3 +330,6 @@ DeferredResourceChangeHandler.0=Reconciling CVS state changes DeferredResourceChangeHandler.1=Errors occured handling ignore file (.cvsignore) changes. Some resources may not be decorated properly. CVSWorkspaceRoot.11=The parent folder of managed file {0} does not have sync info associated with it. RemoveEntryHandler.2=Remove-entry received and ignored from CVS server for existing file {0}. +ServerMessageLineMatcher.5=Variable in template is not of the correct format: {0} +ServerMessageLineMatcher.6=There are additional groups above those defining variables in template: {0} +ServerMessageLineMatcher.7=Expected variable {0} in {1} but it is not present. diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/FileContentCachingService.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/FileContentCachingService.java index c2735c91d..e7b9146e4 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/FileContentCachingService.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/FileContentCachingService.java @@ -16,6 +16,7 @@ import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; import org.eclipse.team.internal.ccvs.core.CVSTag; import org.eclipse.team.internal.ccvs.core.ICVSFile; import org.eclipse.team.internal.ccvs.core.ICVSFolder; @@ -49,6 +50,18 @@ public class FileContentCachingService { } } + /** + * Fetch and cache the file contents for the specified files. + * @param root the root folder for the files being fetched + * @param filePaths the root relative file paths + * @param monitor + * @throws CVSException + */ + public static void fetchFileContents(RemoteFolderTree root, String[] filePaths, IProgressMonitor monitor) throws CVSException { + FileContentCachingService service = new FileContentCachingService((CVSRepositoryLocation)root.getRepository(), root, filePaths); + service.cacheFileContents(monitor); + } + public static RemoteFile buildRemoteTree(CVSRepositoryLocation repository, ICVSFile file, CVSTag tag, IProgressMonitor monitor) throws CVSException { monitor.beginTask(null, 100); try { @@ -86,6 +99,10 @@ public class FileContentCachingService { files, null, Policy.subMonitorFor(monitor, files.length * 100)); + if (!status.isOK()) { + // No big deal but log the problem anyway + CVSProviderPlugin.log (new CVSException(status)); + } } finally { session.close(); monitor.done(); 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 1556dccf4..8d04eb5dc 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 @@ -180,6 +180,13 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { /* package*/ void fetchContents(IProgressMonitor monitor) throws CVSException { monitor.beginTask(Policy.bind("RemoteFile.getContents"), 100);//$NON-NLS-1$ + if (getRevision().equals(ResourceSyncInfo.ADDED_REVISION)) { + // The revision of the remote file is not known so we need to use the tag to get the status of the file + CVSTag tag = getSyncInfo().getTag(); + if (tag == null) tag = CVSTag.DEFAULT; + RemoteFolderMemberFetcher fetcher = new RemoteFolderMemberFetcher((RemoteFolder)getParent(), tag); + fetcher.updateFileRevisions(new ICVSFile[] { this }, Policy.subMonitorFor(monitor, 10)); + } Session session = new Session(getRepository(), parent, false /* create backups */); session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */); try { @@ -191,7 +198,7 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { Update.IGNORE_LOCAL_CHANGES }, new ICVSResource[] { this }, null, - Policy.subMonitorFor(monitor, 90)); + Policy.subMonitorFor(monitor, 80)); if (status.getCode() == CVSStatus.SERVER_ERROR) { throw new CVSServerException(status); } @@ -412,13 +419,15 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { * Return whether there are already contents cached for the given handle */ public boolean isContentsCached() { + if (getRevision().equals(ResourceSyncInfo.ADDED_REVISION)) return false; return getRemoteContentsCache().hasContents(getCacheRelativePath()); } /* * @see ICVSFile#setReadOnly(boolean) */ - public void setReadOnly(boolean readOnly) throws CVSException { + public void setReadOnly(boolean readOnly) { + // RemoteFiles are always read only } /* @@ -438,20 +447,21 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { /* * @see ICVSFile#setTimeStamp(Date) */ - public void setTimeStamp(Date date) throws CVSException { + public void setTimeStamp(Date date) { + // RemoteFiles are not muttable so do not support timestamp changes } /** * @see ICVSFile#moveTo(String) */ - public void copyTo(String mFile) throws CVSException { + public void copyTo(String mFile) { // Do nothing } /* * @see IRemoteResource#members(IProgressMonitor) */ - public IRemoteResource[] members(IProgressMonitor progress) throws TeamException { + public IRemoteResource[] members(IProgressMonitor progress) { return new IRemoteResource[0]; } @@ -505,14 +515,14 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#checkout(int) */ - public void edit(int notifications, IProgressMonitor monitor) throws CVSException { + public void edit(int notifications, IProgressMonitor monitor) { // do nothing } /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#uncheckout() */ - public void unedit(IProgressMonitor monitor) throws CVSException { + public void unedit(IProgressMonitor monitor) { // do nothing } @@ -526,7 +536,7 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#getPendingNotification() */ - public NotifyInfo getPendingNotification() throws CVSException { + public NotifyInfo getPendingNotification() { return null; } @@ -551,13 +561,13 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#committed(org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo) */ - public void checkedIn(String info) throws CVSException { + public void checkedIn(String info) { // do nothing } /** * @see org.eclipse.team.internal.ccvs.core.ICVSFile#isEdited() */ - public boolean isEdited() throws CVSException { + public boolean isEdited() { return false; } /** @@ -588,7 +598,7 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile { /* (non-Javadoc) * @see org.eclipse.team.core.sync.IRemoteResource#getContentIdentifier() */ - public String getContentIdentifier() throws CVSException { + public String getContentIdentifier() { return getRevision(); } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/PrepareForReplaceVisitor.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/PrepareForReplaceVisitor.java index 4fef8987f..8963c8d83 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/PrepareForReplaceVisitor.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/PrepareForReplaceVisitor.java @@ -91,7 +91,7 @@ public class PrepareForReplaceVisitor implements ICVSResourceVisitor { monitor.worked(1); } - public void visitResources(IProject project, final IResource[] resources, final String key, int depth, IProgressMonitor pm) throws CVSException { + public void visitResources(IProject project, final ICVSResource[] resources, final String key, int depth, IProgressMonitor pm) throws CVSException { this.depth = depth; CVSWorkspaceRoot.getCVSFolderFor(project).run(new ICVSRunnable() { public void run(IProgressMonitor pm) throws CVSException { @@ -99,10 +99,9 @@ public class PrepareForReplaceVisitor implements ICVSResourceVisitor { monitor.beginTask(null, 512); for (int i = 0; i < resources.length; i++) { if (key != null) { - monitor.subTask(Policy.bind(key, resources[i].getFullPath().toString())); //$NON-NLS-1$ + monitor.subTask(Policy.bind(key, resources[i].getIResource().getFullPath().toString())); //$NON-NLS-1$ } - IResource resource = resources[i]; - CVSWorkspaceRoot.getCVSResourceFor(resource).accept(PrepareForReplaceVisitor.this); + resources[i].accept(PrepareForReplaceVisitor.this); } monitor.done(); } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java index 1b9977154..d5f3c7c08 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java @@ -540,4 +540,8 @@ public class Util { } return resource.getName(); } + + public static String getVariablePattern(String pattern, String variableName) { + return "(" + variableName + ":" + pattern + ":" + variableName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIPlugin.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIPlugin.java index 0b8060306..3d991d751 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIPlugin.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSUIPlugin.java @@ -623,7 +623,7 @@ public class CVSUIPlugin extends AbstractUIPlugin { CVSProviderPlugin.getPlugin().setRepositoriesAreBinary(store.getBoolean(ICVSUIConstants.PREF_REPOSITORIES_ARE_BINARY)); CVSProviderPlugin.getPlugin().setDetermineVersionEnabled(store.getBoolean(ICVSUIConstants.PREF_DETERMINE_SERVER_VERSION)); CVSProviderPlugin.getPlugin().setConfirmMoveTagEnabled(store.getBoolean(ICVSUIConstants.PREF_CONFIRM_MOVE_TAG)); - CVSProviderPlugin.getPlugin().setDebugProtocol(store.getBoolean(ICVSUIConstants.PREF_DEBUG_PROTOCOL)); + CVSProviderPlugin.getPlugin().setDebugProtocol(CVSProviderPlugin.getPlugin().isDebugProtocol() || store.getBoolean(ICVSUIConstants.PREF_DEBUG_PROTOCOL)); } /** diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRemoteResourcesAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRemoteResourcesAction.java index 1ccf064e5..039f9eee7 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRemoteResourcesAction.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRemoteResourcesAction.java @@ -18,10 +18,16 @@ import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; 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.ICVSRemoteFile; +import org.eclipse.team.internal.ccvs.core.ICVSRemoteFolder; import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; +import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; import org.eclipse.team.internal.ccvs.ui.CVSCompareEditorInput; import org.eclipse.team.internal.ccvs.ui.Policy; import org.eclipse.team.internal.ccvs.ui.ResourceEditionNode; +import org.eclipse.team.internal.ccvs.ui.operations.RemoteCompareOperation; /** * This action is used for comparing two arbitrary remote resources. This is @@ -37,22 +43,53 @@ public class CompareRemoteResourcesAction extends CVSAction { MessageDialog.openError(getShell(), Policy.bind("CompareRemoteResourcesAction.unableToCompare"), Policy.bind("CompareRemoteResourcesAction.selectTwoResources")); //$NON-NLS-1$ //$NON-NLS-2$ return; } - ResourceEditionNode left = new ResourceEditionNode(editions[0]); - ResourceEditionNode right = new ResourceEditionNode(editions[1]); - CompareUI.openCompareEditorOnPage( - new CVSCompareEditorInput(left, right), - getTargetPage()); + if (isSameFolder(editions)) { + // Run the compare operation in the background + try { + new RemoteCompareOperation(null, editions[0], getTag(editions[1])) + .run(); + } catch (CVSException e) { + throw new InvocationTargetException(e); + } catch (InterruptedException e) { + // Ignored + } + } else { + ResourceEditionNode left = new ResourceEditionNode(editions[0]); + ResourceEditionNode right = new ResourceEditionNode(editions[1]); + CompareUI.openCompareEditorOnPage( + new CVSCompareEditorInput(left, right), + getTargetPage()); + } } }, false /* cancelable */, PROGRESS_BUSYCURSOR); } + protected CVSTag getTag(ICVSRemoteResource resource) throws CVSException { + CVSTag tag = null; + if (resource.isContainer()) { + tag = ((ICVSRemoteFolder)resource).getTag(); + } else { + ResourceSyncInfo info = ((ICVSRemoteFile)resource).getSyncInfo(); + if (info != null) tag = info.getTag(); + } + if (tag == null) tag = CVSTag.DEFAULT; + return tag; + } + + protected boolean isSameFolder(ICVSRemoteResource[] editions) { + return editions[0].getRepository().equals(editions[1].getRepository()) + && editions[0].getRepositoryRelativePath().equals(editions[1].getRepositoryRelativePath()); + } + /* * @see TeamAction#isEnabled() */ protected boolean isEnabled() throws TeamException { ICVSRemoteResource[] resources = getSelectedRemoteResources(); if (resources.length != 2) return false; - return resources[0].isContainer() == resources[1].isContainer(); + if (resources[0].isContainer() != resources[1].isContainer()) return false; + // Don't allow comparisons of two unrelated remote projects + return !resources[0].isContainer() || isSameFolder(resources); } } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRemoteWithTagAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRemoteWithTagAction.java index 3eadde99f..75132bde9 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRemoteWithTagAction.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/actions/CompareRemoteWithTagAction.java @@ -12,31 +12,19 @@ package org.eclipse.team.internal.ccvs.ui.actions; import java.lang.reflect.InvocationTargetException; -import org.eclipse.compare.CompareUI; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.action.IAction; import org.eclipse.jface.operation.IRunnableWithProgress; -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.ICVSFile; import org.eclipse.team.internal.ccvs.core.ICVSFolder; import org.eclipse.team.internal.ccvs.core.ICVSRemoteFolder; import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; -import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; -import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; -import org.eclipse.team.internal.ccvs.core.resources.RemoteFolderTreeBuilder; -import org.eclipse.team.internal.ccvs.ui.CVSCompareEditorInput; -import org.eclipse.team.internal.ccvs.ui.ResourceEditionNode; import org.eclipse.team.internal.ccvs.ui.TagSelectionDialog; +import org.eclipse.team.internal.ccvs.ui.operations.RemoteCompareOperation; /** - * @author Administrator - * - * To change this generated comment edit the template variable "typecomment": - * Window>Preferences>Java>Templates. - * To enable and disable the creation of type comments go to - * Window>Preferences>Java>Code Generation. + * Compare to versions of a remote resource. */ public class CompareRemoteWithTagAction extends CVSAction { @@ -45,15 +33,14 @@ public class CompareRemoteWithTagAction extends CVSAction { */ protected void execute(IAction action) throws InvocationTargetException, InterruptedException { - ICVSRemoteResource[] editions = getSelectedRemoteResources(); - if (editions.length == 0) return; - final ICVSRemoteResource resource = editions[0]; + ICVSRemoteResource[] resources = getSelectedRemoteResources(); + if (resources.length == 0) return; - final ResourceEditionNode[] input = new ResourceEditionNode[] { null /* left */, null /* right */}; + // Obtain the tag to compare against + final ICVSRemoteResource resource = resources[0]; final CVSTag[] tag = new CVSTag[] { null}; - run(new IRunnableWithProgress() { - public void run(IProgressMonitor monitor) throws InvocationTargetException { + public void run(IProgressMonitor monitor) { ICVSFolder folder; if (resource instanceof ICVSRemoteFolder) { folder = (ICVSFolder)resource; @@ -63,43 +50,21 @@ public class CompareRemoteWithTagAction extends CVSAction { tag[0] = TagSelectionDialog.getTagToCompareWith(getShell(), new ICVSFolder[] {folder}); } }, false /* cancelable */, PROGRESS_BUSYCURSOR); - if (tag[0] == null) return; - final ICVSRemoteResource[] remote = new ICVSRemoteResource[] { null }; - if (resource.isFolder()) { - remote[0] = resource.forTag(tag[0]); - } else { - run(new IRunnableWithProgress() { - public void run(IProgressMonitor monitor) throws InvocationTargetException { - try { - ICVSRepositoryLocation location = resource.getRepository(); - remote[0] = RemoteFolderTreeBuilder.buildRemoteTree((CVSRepositoryLocation)location, (ICVSFile)resource, tag[0], monitor); - } catch (CVSException e) { - throw new InvocationTargetException(e); - } - } - }, false /* cancelable */, PROGRESS_DIALOG); + // Run the compare operation in the background + try { + new RemoteCompareOperation(null, resource, tag[0]) + .run(); + } catch (CVSException e) { + throw new InvocationTargetException(e); } - - input[0] = new ResourceEditionNode(resource); - input[1] = new ResourceEditionNode(remote[0]); - - if (input[0] == null || input[1] == null) return; - - run(new IRunnableWithProgress() { - public void run(IProgressMonitor monitor) throws InvocationTargetException { - CompareUI.openCompareEditorOnPage( - new CVSCompareEditorInput(input[0] /* left */, input[1] /* right */), - getTargetPage()); - } - }, false /* cancelable */, PROGRESS_BUSYCURSOR); } /** * @see org.eclipse.team.internal.ui.actions.TeamAction#isEnabled() */ - protected boolean isEnabled() throws TeamException { + protected boolean isEnabled() { ICVSRemoteResource[] resources = getSelectedRemoteResources(); // Only support single select for now. // Need to avoid overlap if multi-select is supported diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties index 8d5144747..cde9e01f0 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/messages.properties @@ -1030,3 +1030,4 @@ FetchMembersOperation.0=Fetching members of {0}; RemoteRevisionQuickDiffProvider.readingFile=Error reading remote file RemoteRevisionQuickDiffProvider.closingFile=Error closing remote file RemoteRevisionQuickDiffProvider.fetchingFile=CVS QuickDiff: fetching remote contents for ''{0}'' +RemoteCompareOperation.0=Comparing tags {0} and {1} of {2} diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RemoteCompareOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RemoteCompareOperation.java new file mode 100644 index 000000000..bc4255e11 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RemoteCompareOperation.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ccvs.ui.operations; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.compare.CompareUI; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; +import org.eclipse.team.internal.ccvs.core.CVSTag; +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.client.Command; +import org.eclipse.team.internal.ccvs.core.client.RDiff; +import org.eclipse.team.internal.ccvs.core.client.Session; +import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption; +import org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener; +import org.eclipse.team.internal.ccvs.core.resources.FileContentCachingService; +import org.eclipse.team.internal.ccvs.core.resources.RemoteFile; +import org.eclipse.team.internal.ccvs.core.resources.RemoteFolderTree; +import org.eclipse.team.internal.ccvs.core.util.Assert; +import org.eclipse.team.internal.ccvs.ui.CVSCompareEditorInput; +import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin; +import org.eclipse.team.internal.ccvs.ui.ICVSUIConstants; +import org.eclipse.team.internal.ccvs.ui.Policy; +import org.eclipse.team.internal.ccvs.ui.ResourceEditionNode; +import org.eclipse.team.internal.ui.TeamUIPlugin; +import org.eclipse.ui.IWorkbenchPage; + +/** + * Compare the two versions of given remote folders obtained from the two tags specified. + */ +public class RemoteCompareOperation extends RemoteOperation implements RDiffSummaryListener.IFileDiffListener { + + private CVSTag left; + private CVSTag right; + + private RemoteFolderTree leftTree, rightTree; + + /** + * Compare two versions of the given remote resource. + * @param shell + * @param remoteResource the resource whose tags are being compared + * @param left the earlier tag (not null) + * @param right the later tag (not null) + */ + public RemoteCompareOperation(Shell shell, ICVSRemoteResource remoteResource, CVSTag tag) { + super(shell, new ICVSRemoteResource[] {remoteResource}); + Assert.isNotNull(tag); + this.right = tag; + if (remoteResource.isContainer()) { + this.left = ((ICVSRemoteFolder)remoteResource).getTag(); + } else { + try { + this.left = remoteResource.getSyncInfo().getTag(); + } catch (CVSException e) { + // This shouldn't happen but log it just in case + CVSProviderPlugin.log(e); + } + } + if (this.left == null) { + this.left = CVSTag.DEFAULT; + } + } + + /* + * This command only supports the use of a single resource + */ + private ICVSRemoteResource getRemoteResource() { + return getRemoteResources()[0]; + } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#execute(org.eclipse.core.runtime.IProgressMonitor) + */ + protected void execute(IProgressMonitor monitor) throws CVSException { + leftTree = rightTree = null; + boolean fetchContents = CVSUIPlugin.getPlugin().getPluginPreferences().getBoolean(ICVSUIConstants.PREF_CONSIDER_CONTENTS); + monitor.beginTask(getTaskName(), 50 + (fetchContents ? 100 : 0)); + try { + ICVSRemoteResource resource = getRemoteResource(); + IStatus status = buildTrees(resource, Policy.subMonitorFor(monitor, 50)); + if (status.isOK() && fetchContents) { + String[] overlappingFilePaths = getOverlappingFilePaths(); + if (overlappingFilePaths.length > 0) { + fetchFileContents(leftTree, overlappingFilePaths, Policy.subMonitorFor(monitor, 50)); + fetchFileContents(rightTree, overlappingFilePaths, Policy.subMonitorFor(monitor, 50)); + } + } + collectStatus(status); + openCompareEditor(leftTree, rightTree); + } finally { + monitor.done(); + } + } + + private String[] getOverlappingFilePaths() { + String[] leftFiles = getFilePaths(leftTree); + String[] rightFiles = getFilePaths(rightTree); + Set set = new HashSet(); + for (int i = 0; i < rightFiles.length; i++) { + String rightFile = rightFiles[i]; + for (int j = 0; j < leftFiles.length; j++) { + String leftFile = leftFiles[j]; + if (leftFile.equals(rightFile)) { + set.add(leftFile); + } + } + } + return (String[]) set.toArray(new String[set.size()]); + } + + private void fetchFileContents(RemoteFolderTree tree, String[] overlappingFilePaths, IProgressMonitor monitor) throws CVSException { + FileContentCachingService.fetchFileContents(tree, overlappingFilePaths, monitor); + } + + private String[] getFilePaths(RemoteFolderTree tree) { + ICVSRemoteResource[] children = tree.getChildren(); + List result = new ArrayList(); + for (int i = 0; i < children.length; i++) { + ICVSRemoteResource resource = children[i]; + if (resource.isContainer()) { + result.addAll(Arrays.asList(getFilePaths((RemoteFolderTree)resource))); + } else { + result.add(resource.getRepositoryRelativePath()); + } + } + return (String[]) result.toArray(new String[result.size()]); + } + + /* + * Build the two trees uses the reponses from "cvs rdiff -s ...". + */ + private IStatus buildTrees(ICVSRemoteResource resource, IProgressMonitor monitor) throws CVSException { + // Initialize the resulting trees + leftTree = new RemoteFolderTree(null, resource.getRepository(), ICVSRemoteFolder.REPOSITORY_ROOT_FOLDER_NAME, left); + rightTree = new RemoteFolderTree(null, resource.getRepository(), ICVSRemoteFolder.REPOSITORY_ROOT_FOLDER_NAME, right); + Command.QuietOption oldOption= CVSProviderPlugin.getPlugin().getQuietness(); + Session session = new Session(resource.getRepository(), leftTree, false); + try { + monitor.beginTask(getTaskName(), 100); + CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE); + session.open(Policy.subMonitorFor(monitor, 10)); + IStatus status = Command.RDIFF.execute(session, + Command.NO_GLOBAL_OPTIONS, + getLocalOptions(), + new ICVSResource[] { resource }, + new RDiffSummaryListener(this), + Policy.subMonitorFor(monitor, 90)); + return status; + } finally { + try { + session.close(); + } finally { + CVSProviderPlugin.getPlugin().setQuietness(oldOption); + } + monitor.done(); + } + } + + private LocalOption[] getLocalOptions() { + return new LocalOption[] {RDiff.SUMMARY, RDiff.makeTagOption(left), RDiff.makeTagOption(right)}; + } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#getTaskName() + */ + protected String getTaskName() { + return Policy.bind("RemoteCompareOperation.0", new Object[] {left.getName(), right.getName(), getRemoteResource().getRepositoryRelativePath()}); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener.IFileDiffListener#fileDiff(java.lang.String, java.lang.String, java.lang.String) + */ + public void fileDiff(String remoteFilePath, String leftRevision, String rightRevision) { + try { + addFile(rightTree, right, new Path(remoteFilePath), rightRevision); + } catch (CVSException e) { + CVSUIPlugin.log(e); + } + try { + addFile(leftTree, left, new Path(remoteFilePath), leftRevision); + } catch (CVSException e) { + CVSUIPlugin.log(e); + } + } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener.IFileDiffListener#newFile(java.lang.String, java.lang.String) + */ + public void newFile(String remoteFilePath, String rightRevision) { + try { + addFile(rightTree, right, new Path(remoteFilePath), rightRevision); + } catch (CVSException e) { + CVSUIPlugin.log(e); + } + } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener.IFileDiffListener#deletedFile(java.lang.String) + */ + public void deletedFile(String remoteFilePath, String leftRevision) { + // The leftRevision may be null in which case the tag is used + try { + addFile(leftTree, left, new Path(remoteFilePath), leftRevision); + } catch (CVSException e) { + CVSUIPlugin.log(e); + } + } + + /* (non-Javadoc) + * @see org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener.IFileDiffListener#directory(java.lang.String) + */ + public void directory(String remoteFolderPath) { + try { + getFolder(leftTree, left, new Path(remoteFolderPath), Path.EMPTY); + } catch (CVSException e) { + CVSUIPlugin.log(e); + } + try { + getFolder(rightTree, right, new Path(remoteFolderPath), Path.EMPTY); + } catch (CVSException e) { + CVSUIPlugin.log(e); + } + } + + /* + * Get the folder at the given path in the given tree, creating any missing folders as needed. + */ + private ICVSRemoteFolder getFolder(RemoteFolderTree tree, CVSTag tag, IPath remoteFolderPath, IPath parentPath) throws CVSException { + if (remoteFolderPath.segmentCount() == 0) return tree; + String name = remoteFolderPath.segment(0); + ICVSResource child; + IPath childPath = parentPath.append(name); + if (tree.childExists(name)) { + child = tree.getChild(name); + } else { + child = new RemoteFolderTree(tree, tree.getRepository(), childPath.toString(), tag); + ((RemoteFolderTree)child).setChildren(new ICVSRemoteResource[0]); + addChild(tree, (ICVSRemoteResource)child); + } + return getFolder((RemoteFolderTree)child, tag, remoteFolderPath.removeFirstSegments(1), childPath); + } + + private void addChild(RemoteFolderTree tree, ICVSRemoteResource resource) { + ICVSRemoteResource[] children = tree.getChildren(); + ICVSRemoteResource[] newChildren; + if (children == null) { + newChildren = new ICVSRemoteResource[] { resource }; + } else { + newChildren = new ICVSRemoteResource[children.length + 1]; + System.arraycopy(children, 0, newChildren, 0, children.length); + newChildren[children.length] = resource; + } + tree.setChildren(newChildren); + } + + private void addFile(RemoteFolderTree tree, CVSTag tag, Path filePath, String revision) throws CVSException { + RemoteFolderTree parent = (RemoteFolderTree)getFolder(tree, tag, filePath.removeLastSegments(1), Path.EMPTY); + String name = filePath.lastSegment(); + ICVSRemoteFile file = new RemoteFile(parent, 0, name, revision, null, tag); + addChild(parent, file); + } + + /* + * Only intended to be overridden by test cases. + */ + protected void openCompareEditor(final ICVSRemoteFolder leftTree, final ICVSRemoteFolder rightTree) { + if (leftTree == null || rightTree == null) return; + Display.getDefault().asyncExec(new Runnable() { + public void run() { + CompareUI.openCompareEditorOnPage( + new CVSCompareEditorInput(new ResourceEditionNode(leftTree), new ResourceEditionNode(rightTree)), + getTargetPage()); + } + }); + } + + protected IWorkbenchPage getTargetPage() { + return TeamUIPlugin.getActivePage(); + } +} diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReplaceOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReplaceOperation.java index 9f4e7bb1a..c49567055 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReplaceOperation.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReplaceOperation.java @@ -20,6 +20,7 @@ import org.eclipse.swt.widgets.Shell; 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.ICVSResource; import org.eclipse.team.internal.ccvs.core.client.Command; import org.eclipse.team.internal.ccvs.core.client.Session; import org.eclipse.team.internal.ccvs.core.client.Update; @@ -64,7 +65,7 @@ public class ReplaceOperation extends UpdateOperation { protected IStatus executeCommand( Session session, CVSTeamProvider provider, - IResource[] resources, + ICVSResource[] resources, IProgressMonitor monitor) throws CVSException, InterruptedException { diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/SingleCommandOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/SingleCommandOperation.java index de2f9a8c5..97121d9f9 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/SingleCommandOperation.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/SingleCommandOperation.java @@ -15,8 +15,8 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.swt.widgets.Shell; import org.eclipse.team.internal.ccvs.core.CVSException; -import org.eclipse.team.internal.ccvs.core.CVSStatus; import org.eclipse.team.internal.ccvs.core.CVSTeamProvider; +import org.eclipse.team.internal.ccvs.core.ICVSResource; import org.eclipse.team.internal.ccvs.core.client.Command; import org.eclipse.team.internal.ccvs.core.client.Session; import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption; @@ -24,7 +24,7 @@ import org.eclipse.team.internal.ccvs.ui.Policy; public abstract class SingleCommandOperation extends RepositoryProviderOperation { - LocalOption[] options = Command.NO_LOCAL_OPTIONS; + private LocalOption[] options = Command.NO_LOCAL_OPTIONS; public SingleCommandOperation(Shell shell, IResource[] resources, LocalOption[] options) { super(shell, resources); @@ -41,10 +41,8 @@ public abstract class SingleCommandOperation extends RepositoryProviderOperation Session session = new Session(getRemoteLocation(provider), getLocalRoot(provider), true /* output to console */); session.open(Policy.subMonitorFor(monitor, 10), isServerModificationOperation()); try { - IStatus status = executeCommand(session, provider, resources, Policy.subMonitorFor(monitor, 90)); - if (status.getCode() == CVSStatus.SERVER_ERROR) { - addError(status); - } + IStatus status = executeCommand(session, provider, getCVSArguments(resources), Policy.subMonitorFor(monitor, 90)); + collectStatus(status); } finally { session.close(); } @@ -62,7 +60,7 @@ public abstract class SingleCommandOperation extends RepositoryProviderOperation /** * Method overridden by subclasses to issue the command to the CVS repository using the given session. */ - protected abstract IStatus executeCommand(Session session, CVSTeamProvider provider, IResource[] resources, IProgressMonitor monitor) throws CVSException, InterruptedException; + protected abstract IStatus executeCommand(Session session, CVSTeamProvider provider, ICVSResource[] resources, IProgressMonitor monitor) throws CVSException, InterruptedException; protected LocalOption[] getLocalOptions() { return options; @@ -72,4 +70,10 @@ public abstract class SingleCommandOperation extends RepositoryProviderOperation this.options = options; } + protected void addLocalOption(LocalOption option) { + LocalOption[] newOptions = new LocalOption[options.length + 1]; + System.arraycopy(options, 0, newOptions, 0, options.length); + newOptions[options.length] = option; + options = newOptions; + } } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/UpdateOnlyMergableOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/UpdateOnlyMergableOperation.java index cfecbfcc8..ed56623e0 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/UpdateOnlyMergableOperation.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/UpdateOnlyMergableOperation.java @@ -21,6 +21,7 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.swt.widgets.Shell; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.CVSTeamProvider; +import org.eclipse.team.internal.ccvs.core.ICVSResource; import org.eclipse.team.internal.ccvs.core.client.Command; import org.eclipse.team.internal.ccvs.core.client.Session; import org.eclipse.team.internal.ccvs.core.client.UpdateMergableOnly; @@ -42,13 +43,13 @@ public class UpdateOnlyMergableOperation extends SingleCommandOperation { /* (non-Javadoc) * @see org.eclipse.team.internal.ccvs.ui.operations.SingleCommandOperation#executeCommand(org.eclipse.team.internal.ccvs.core.client.Session, org.eclipse.team.internal.ccvs.core.CVSTeamProvider, org.eclipse.core.resources.IResource[], org.eclipse.core.runtime.IProgressMonitor) */ - protected IStatus executeCommand(Session session, CVSTeamProvider provider, IResource[] resources, IProgressMonitor monitor) throws CVSException, InterruptedException { + protected IStatus executeCommand(Session session, CVSTeamProvider provider, ICVSResource[] resources, IProgressMonitor monitor) throws CVSException, InterruptedException { UpdateMergableOnly update = new UpdateMergableOnly(); IStatus status = update.execute( session, Command.NO_GLOBAL_OPTIONS, getLocalOptions(), - getCVSArguments(resources), + resources, null, Policy.subMonitorFor(monitor, 90)); if (status.getCode() != IStatus.ERROR) { diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/UpdateOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/UpdateOperation.java index da17e6076..bdbe5b081 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/UpdateOperation.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/UpdateOperation.java @@ -50,7 +50,7 @@ public class UpdateOperation extends SingleCommandOperation { protected IStatus executeCommand( Session session, CVSTeamProvider provider, - IResource[] resources, + ICVSResource[] resources, IProgressMonitor monitor) throws CVSException, InterruptedException { @@ -65,13 +65,12 @@ public class UpdateOperation extends SingleCommandOperation { // Build the arguments list localOptions.addAll(Arrays.asList(getLocalOptions())); LocalOption[] commandOptions = (LocalOption[])localOptions.toArray(new LocalOption[localOptions.size()]); - ICVSResource[] arguments = getCVSArguments(resources); return Command.UPDATE.execute( session, Command.NO_GLOBAL_OPTIONS, commandOptions, - arguments, + resources, null, monitor); } diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java index 2f3a4bc85..ba0bb474b 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java @@ -348,6 +348,13 @@ public class EclipseTest extends EclipseWorkspaceTest { } /* + * Create a test project using the currently running test case as the project name prefix + */ + protected IProject createProject(String[] strings) throws TeamException, CoreException { + return createProject(getName(), strings); + } + + /* * Compare two projects by comparing thier providers */ protected void assertEquals(IProject project1, IProject project2) throws CoreException, TeamException, IOException { diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/AllUIUnitTests.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/AllUIUnitTests.java index 40eaa011a..71e9d07d7 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/AllUIUnitTests.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/AllUIUnitTests.java @@ -28,6 +28,7 @@ public class AllUIUnitTests extends EclipseTest { public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(CheckoutOperationTests.suite()); + suite.addTest(CompareOperationTests.suite()); return suite; } diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CVSOperationTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CVSOperationTest.java new file mode 100644 index 000000000..a87ac7882 --- /dev/null +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CVSOperationTest.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.tests.ccvs.ui.unit; + +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.ui.operations.CVSOperation; +import org.eclipse.team.tests.ccvs.core.EclipseTest; + +public abstract class CVSOperationTest extends EclipseTest { + + protected CVSOperationTest() { + super(); + } + + protected CVSOperationTest(String name) { + super(name); + } + + protected void run(CVSOperation op) throws CVSException { + executeHeadless(op); + } +} diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CheckoutOperationTests.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CheckoutOperationTests.java index c333f7d8d..48057d8bf 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CheckoutOperationTests.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CheckoutOperationTests.java @@ -20,7 +20,6 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; import org.eclipse.team.core.TeamException; -import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.ICVSFolder; import org.eclipse.team.internal.ccvs.core.ICVSRemoteFolder; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; @@ -29,9 +28,8 @@ import org.eclipse.team.internal.ccvs.ui.operations.CVSOperation; import org.eclipse.team.internal.ccvs.ui.operations.CheckoutMultipleProjectsOperation; import org.eclipse.team.internal.ccvs.ui.operations.CheckoutSingleProjectOperation; import org.eclipse.team.tests.ccvs.core.CVSTestSetup; -import org.eclipse.team.tests.ccvs.core.EclipseTest; -public class CheckoutOperationTests extends EclipseTest { +public class CheckoutOperationTests extends CVSOperationTest { public CheckoutOperationTests() { } @@ -57,15 +55,11 @@ public class CheckoutOperationTests extends EclipseTest { IProject movedProject = ResourcesPlugin.getWorkspace().getRoot().getProject("moved-project"); // checkout the project to the default location - try { - CVSOperation op = new CheckoutMultipleProjectsOperation( - null /* shell */, - new ICVSRemoteFolder[] { (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(movedProject) }, - null /*target location*/); - run(op); - } catch (InterruptedException e) { - fail("Operation should not have been interrupted"); - } + CVSOperation op = new CheckoutMultipleProjectsOperation( + null /* shell */, + new ICVSRemoteFolder[] { (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(movedProject) }, + null /*target location*/); + run(op); assertEquals(project, movedProject); } @@ -74,15 +68,11 @@ public class CheckoutOperationTests extends EclipseTest { IProject project = createProject("testNonRootCheckout", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" }); // checkout the non-root folder as a project to the default location - try { - CVSOperation op = new CheckoutMultipleProjectsOperation( - null /* shell */, - new ICVSRemoteFolder[] { (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(project.getFolder("folder1")) }, - null /*target location*/); - run(op); - } catch (InterruptedException e) { - fail("Operation should not have been interrupted"); - } + CVSOperation op = new CheckoutMultipleProjectsOperation( + null /* shell */, + new ICVSRemoteFolder[] { (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(project.getFolder("folder1")) }, + null /*target location*/); + run(op); IProject newProject = ResourcesPlugin.getWorkspace().getRoot().getProject("folder1"); assertTrue(newProject.exists()); @@ -107,18 +97,14 @@ public class CheckoutOperationTests extends EclipseTest { // checkout the project to the default location - try { - CVSOperation op = new CheckoutMultipleProjectsOperation( - null /* shell */, - new ICVSRemoteFolder[] { - (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(movedProject1), - (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(movedProject2) - }, - null /*target location*/); - run(op); - } catch (InterruptedException e) { - fail("Operation should not have been interrupted"); - } + CVSOperation op = new CheckoutMultipleProjectsOperation( + null /* shell */, + new ICVSRemoteFolder[] { + (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(movedProject1), + (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(movedProject2) + }, + null /*target location*/); + run(op); } public void testCheckoutAs() throws TeamException, CoreException, IOException { @@ -126,22 +112,15 @@ public class CheckoutOperationTests extends EclipseTest { IProject copy = ResourcesPlugin.getWorkspace().getRoot().getProject(project.getName() + "-copy"); // checkout the project to the default location - try { - CVSOperation op = new CheckoutSingleProjectOperation( - null /* shell */, - (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(project), - copy, - null /*target location*/, - false); - run(op); - } catch (InterruptedException e) { - fail("Operation should not have been interrupted"); - } + CVSOperation op = new CheckoutSingleProjectOperation( + null /* shell */, + (ICVSRemoteFolder)CVSWorkspaceRoot.getRemoteResourceFor(project), + copy, + null /*target location*/, + false); + run(op); assertEquals(project, copy); } - private void run(CVSOperation op) throws CVSException, InterruptedException { - executeHeadless(op); - } } diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CompareOperationTests.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CompareOperationTests.java new file mode 100644 index 000000000..c7c21b58a --- /dev/null +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/unit/CompareOperationTests.java @@ -0,0 +1,184 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.tests.ccvs.ui.unit; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.internal.ccvs.core.CVSTag; +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.resources.CVSWorkspaceRoot; +import org.eclipse.team.internal.ccvs.core.resources.RemoteFolder; +import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; +import org.eclipse.team.internal.ccvs.ui.operations.RemoteCompareOperation; +import org.eclipse.team.tests.ccvs.core.CVSTestSetup; + +public class CompareOperationTests extends CVSOperationTest { + + public class TestRemoteCompareOperation extends RemoteCompareOperation { + private ICVSRemoteFolder leftTree, rightTree; + + public TestRemoteCompareOperation(Shell shell, ICVSRemoteResource resource, CVSTag tag) { + super(shell, resource, tag); + } + + /* + * Override to prevent compare editor from opening and to capture the results + */ + protected void openCompareEditor(ICVSRemoteFolder leftTree, ICVSRemoteFolder rightTree) { + this.leftTree = leftTree; + this.rightTree = rightTree; + } + + public ICVSRemoteFolder getLeftTree() { + return leftTree; + } + + public ICVSRemoteFolder getRightTree() { + return rightTree; + } + + } + + public CompareOperationTests() { + super(); + } + + public CompareOperationTests(String name) { + super(name); + } + + public static Test suite() { + String testName = System.getProperty("eclipse.cvs.testName"); + if (testName == null) { + TestSuite suite = new TestSuite(CompareOperationTests.class); + return new CVSTestSetup(suite); + } else { + return new CVSTestSetup(new CompareOperationTests(testName)); + } + } + + + /** + * Assert that the revisions of any files in the remote tree match the revisions in the local tree + */ + + private void assertRevisionsMatch(ICVSRemoteFolder folder, IProject project, String[] filePathsWithRevisions, String[] filePathsWithoutRevisions) throws CoreException { + if (filePathsWithRevisions == null) filePathsWithRevisions = new String[0]; + if (filePathsWithoutRevisions == null) filePathsWithoutRevisions = new String[0]; + IResource[] filesWithRevisions = getResources(project, filePathsWithRevisions); + IResource[] filesWithoutRevisions = getResources(project, filePathsWithoutRevisions); + ICVSRemoteFile[] files= getAllFiles(folder); + assertTrue("The number of remote files with differences does not match the expected number", files.length == (filePathsWithoutRevisions.length + filePathsWithRevisions.length)); + for (int i = 0; i < files.length; i++) { + ICVSRemoteFile remoteFile = files[i]; + for (int j = 0; j < filesWithRevisions.length; j++) { + IResource local = filesWithRevisions[j]; + ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor((IFile)local); + if (cvsFile.getRepositoryRelativePath().equals(remoteFile.getRepositoryRelativePath())) { + ResourceSyncInfo info = cvsFile.getSyncInfo(); + assertNotNull(info); + String localRevision = info.getRevision(); + assertNotNull(localRevision); + String remoteRevision = files[i].getRevision(); + assertNotNull(remoteRevision); + assertEquals("Revisions do not match for " + local.getProjectRelativePath(), localRevision, remoteRevision); + } + } + for (int j = 0; j < filesWithoutRevisions.length; j++) { + IResource local = filesWithoutRevisions[j]; + ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor((IFile)local); + if (cvsFile.getRepositoryRelativePath().equals(remoteFile.getRepositoryRelativePath())) { + ResourceSyncInfo info = cvsFile.getSyncInfo(); + assertNotNull(info); + String localRevision = info.getRevision(); + assertNotNull(localRevision); + // Cannot assert anything about the remote revision + } + } + } + } + + private ICVSRemoteFile[] getAllFiles(ICVSRemoteFolder folder) { + List result = new ArrayList(); + ICVSRemoteResource[] children = ((RemoteFolder)folder).getChildren(); + if (children != null) { + for (int i = 0; i < children.length; i++) { + ICVSRemoteResource resource = children[i]; + if (resource.isContainer()) { + result.addAll(Arrays.asList(getAllFiles((ICVSRemoteFolder)resource))); + } else { + result.add(resource); + } + } + } + return (ICVSRemoteFile[]) result.toArray(new ICVSRemoteFile[result.size()]); + } + + public void testCompareWithLatest() throws TeamException, CoreException { + // Create a test project + IProject project = createProject(new String[] { "file1.txt", "folder1/", "folder1/a.txt", "folder1/b.txt"}); + CVSTag v1 = new CVSTag("v1", CVSTag.VERSION); + tagProject(project, v1, false); + + // Checkout and modify a copy (and commit the changes) + IProject copy = checkoutCopy(project, "-copy"); + setContentsAndEnsureModified(copy.getFile("folder1/a.txt")); + addResources(copy, new String[] { "folder1/newFile", "folder2/folder3/add.txt" }, false); + deleteResources(copy, new String[] {"folder1/b.txt"}, false); + getProvider(copy).checkin(new IResource[] {copy}, IResource.DEPTH_INFINITE, DEFAULT_MONITOR); + + // Run the compare operation of the project folder + ICVSRemoteResource remoteResource = CVSWorkspaceRoot.getRemoteResourceFor(project); + TestRemoteCompareOperation op = new TestRemoteCompareOperation(null, remoteResource, v1); + run(op); + assertRevisionsMatch(op.getRightTree(), project, new String[] {"folder1/a.txt", "folder1/b.txt"}, null); + assertRevisionsMatch(op.getLeftTree(), copy, new String[] {"folder1/a.txt" }, new String[] {"folder1/newFile", "folder2/folder3/add.txt" } /* files with no revision */); + + + // Run the compare operation of the project folder the other way + remoteResource = CVSWorkspaceRoot.getRemoteResourceFor(project); + remoteResource = ((ICVSRemoteFolder)remoteResource).forTag(v1); + op = new TestRemoteCompareOperation(null, remoteResource, CVSTag.DEFAULT); + run(op); + assertRevisionsMatch(op.getLeftTree(), project, new String[] {"folder1/a.txt"}, new String[] {"folder1/b.txt"}); + assertRevisionsMatch(op.getRightTree(), copy, new String[] {"folder1/a.txt", "folder1/newFile", "folder2/folder3/add.txt" }, null /* files with no revision */); + + // Run the compare operation of a subfolder + remoteResource = CVSWorkspaceRoot.getRemoteResourceFor(project.getFolder("folder1")); + op = new TestRemoteCompareOperation(null, remoteResource, v1); + run(op); + assertRevisionsMatch(op.getRightTree(), project, new String[] {"folder1/a.txt", "folder1/b.txt"}, null); + assertRevisionsMatch(op.getLeftTree(), copy, new String[] {"folder1/a.txt"}, new String[] {"folder1/newFile" } /* files with no revision */); + + // Run the operation on a single file + remoteResource = CVSWorkspaceRoot.getRemoteResourceFor(project.getFile("folder1/a.txt")); + op = new TestRemoteCompareOperation(null, remoteResource, v1); + run(op); + assertRevisionsMatch(op.getRightTree(), project, new String[] {"folder1/a.txt"}, null); + assertRevisionsMatch(op.getLeftTree(), copy, new String[] {"folder1/a.txt" }, null /* files with no revision */); + + } + +} |