Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ILogEntryListener.java26
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java428
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java33
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RemoteLogOperation.java105
4 files changed, 313 insertions, 279 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ILogEntryListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ILogEntryListener.java
new file mode 100644
index 000000000..5e44de599
--- /dev/null
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ILogEntryListener.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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.ILogEntry;
+
+/**
+ * Interface for receiving log entries from the <code>LogListener</code>
+ */
+public interface ILogEntryListener {
+
+ /**
+ * A log entry was received for the current file
+ * @param entry the received log entry.
+ */
+ void handleLogEntryReceived(ILogEntry entry);
+
+}
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java
index 2159ff726..06e7fe4d2 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/LogListener.java
@@ -10,243 +10,217 @@
*******************************************************************************/
package org.eclipse.team.internal.ccvs.core.client.listeners;
-
import java.util.*;
+
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.CommandOutputListener;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
import org.eclipse.team.internal.ccvs.core.util.Util;
+/**
+ * Log listener that parses the log entries returned from the
+ * server but delegates the handling of the entries to a subclass.
+ */
public class LogListener extends CommandOutputListener {
- private Map entries = new HashMap(); /* Map repo relative path->List of LogEntry */
- private RemoteFile currentFile;
- private List currentFileEntries;
-
- // state
- private final int BEGIN = 0, SYMBOLIC_NAMES = 1, REVISION = 2, COMMENT = 3, DONE = 4;
- private List tagNames = new ArrayList(5);
- private List tagRevisions = new ArrayList(5);
- private int state = BEGIN; // current state
- private String creationDate;
- private String author;
- private String revision; // revision number
- private String fileState; //
- private StringBuffer comment; // comment
-
+
+ // Server message prefix used for error detection
+ private static final String NOTHING_KNOWN_ABOUT = "nothing known about "; //$NON-NLS-1$
+
+ // States of log accumulation.
+ private final int DONE = 4;
+ private final int COMMENT = 3;
+ private final int REVISION = 2;
+ private final int SYMBOLIC_NAMES = 1;
+ private final int BEGIN = 0;
+
+ // Instance variables for accumulating Log information
+ private RemoteFile currentFile;
+ private int state = BEGIN;
+ private StringBuffer comment;
+ private String fileState;
+ private String revision;
+ private String author;
+ private String creationDate;
+ private List tagRevisions = new ArrayList(5);
+ private List tagNames = new ArrayList(5);
+
+ private final ILogEntryListener listener;
+
+ /**
+ * Create a log listener for receiving entries for one or more files.
+ */
+ public LogListener(ILogEntryListener listener) {
+ this.listener = listener;
+ }
+
+ public LogListener(RemoteFile file, ILogEntryListener listener) {
+ this(listener);
+ this.currentFile = file;
+ }
+
+ private String getRelativeFilePath(ICVSRepositoryLocation location, String fileName) {
+ if (fileName.endsWith(",v")) { //$NON-NLS-1$
+ fileName = fileName.substring(0, fileName.length() - 2);
+ }
+ fileName = Util.removeAtticSegment(fileName);
+ String rootDirectory = location.getRootDirectory();
+ if (fileName.startsWith(rootDirectory)) {
+ try {
+ fileName = Util.getRelativePath(rootDirectory, fileName);
+ } catch (CVSException e) {
+ CVSProviderPlugin.log(e);
+ return null;
+ }
+ }
+ return fileName;
+ }
+
+ public IStatus errorLine(String line, ICVSRepositoryLocation location, ICVSFolder commandRoot, IProgressMonitor monitor) {
+ String serverMessage = getServerMessage(line, location);
+ if (serverMessage != null) {
+ // look for the following condition
+ // E cvs server: nothing known about fileName
+ if (serverMessage.startsWith(NOTHING_KNOWN_ABOUT)) {
+ return new CVSStatus(IStatus.ERROR, CVSStatus.DOES_NOT_EXIST, commandRoot, line);
+ }
+ }
+ return OK;
+ }
+
+ public IStatus messageLine(String line, ICVSRepositoryLocation location, ICVSFolder commandRoot, IProgressMonitor monitor) {
+ // Fields we will find in the log for a file
+ // keys = String (tag name), values = String (tag revision number) */
+ switch (state) {
+ case BEGIN:
+ if (line.startsWith("RCS file: ")) { //$NON-NLS-1$
+ // We are starting to recieve the log for a file
+ String fileName = getRelativeFilePath(location, line.substring(10).trim());
+ if (fileName == null) {
+ currentFile = null;
+ handleInvalidFileName(location, fileName);
+ } else {
+ if (currentFile == null || !currentFile.getRepositoryRelativePath().equals(fileName)) {
+ // We are starting another file
+ beginFile(location, fileName);
+ }
+ }
+ } else if (line.startsWith("symbolic names:")) { //$NON-NLS-1$
+ state = SYMBOLIC_NAMES;
+ } else if (line.startsWith("revision ")) { //$NON-NLS-1$
+ revision = line.substring(9);
+ state = REVISION;
+ }
+ break;
+ case SYMBOLIC_NAMES:
+ if (line.startsWith("keyword substitution:")) { //$NON-NLS-1$
+ state = BEGIN;
+ } else {
+ int firstColon = line.indexOf(':');
+ String tagName = line.substring(1, firstColon);
+ String tagRevision = line.substring(firstColon + 2);
+ tagNames.add(tagName);
+ tagRevisions.add(tagRevision);
+ }
+ break;
+ case REVISION:
+ // date: 2000/06/19 04:56:21; author: somebody; state: Exp; lines: +114 -45
+ // get the creation date
+ int endOfDateIndex = line.indexOf(';', 6);
+ creationDate = line.substring(6, endOfDateIndex) + " GMT"; //$NON-NLS-1$
+
+ // get the author name
+ int endOfAuthorIndex = line.indexOf(';', endOfDateIndex + 1);
+ author = line.substring(endOfDateIndex + 11, endOfAuthorIndex);
+
+ // get the file state (because this revision might be "dead")
+ fileState = line.substring(endOfAuthorIndex + 10, line.indexOf(';', endOfAuthorIndex + 1));
+ comment = new StringBuffer();
+ state = COMMENT;
+ break;
+ case COMMENT:
+ // skip next line (info about branches) if it exists, if not then it is a comment line.
+ if (line.startsWith("branches:")) break; //$NON-NLS-1$
+ if (line.equals("=============================================================================") //$NON-NLS-1$
+ || line.equals("----------------------------")) { //$NON-NLS-1$
+ state = DONE;
+ break;
+ }
+ if (comment.length() != 0) comment.append('\n');
+ comment.append(line);
+ break;
+ }
+ if (state == DONE) {
+ // we are only interested in tag names for this revision, remove all others.
+ List thisRevisionTags = new ArrayList(3);
+ for (int i = 0; i < tagNames.size(); i++) {
+ String tagName = (String) tagNames.get(i);
+ String tagRevision = (String) tagRevisions.get(i);
+ // If this is a branch tag then only include this tag with the revision
+ // that is the root of this branch (e.g. 1.1 is root of branch 1.1.2).
+ boolean isBranch = isBranchTag(tagRevision);
+ if (isBranch) {
+ int lastDot = tagRevision.lastIndexOf('.');
+ if (lastDot == -1) {
+ CVSProviderPlugin.log(IStatus.ERROR,
+ Policy.bind("LogListener.invalidRevisionFormat", tagName, tagRevision), null); //$NON-NLS-1$
+ } else {
+ if (tagRevision.charAt(lastDot - 1) == '0' && tagRevision.charAt(lastDot - 2) == '.') {
+ lastDot = lastDot - 2;
+ }
+ tagRevision = tagRevision.substring(0, lastDot);
+ }
+ }
+ if (tagRevision.equals(revision)) {
+ int type = isBranch ? CVSTag.BRANCH : CVSTag.VERSION;
+ thisRevisionTags.add(new CVSTag(tagName, type));
+ }
+ }
+ Date date = DateUtil.convertFromLogTime(creationDate);
+ if (currentFile != null) {
+ LogEntry entry = new LogEntry(currentFile, revision, author, date,
+ comment.toString(), fileState, (CVSTag[]) thisRevisionTags.toArray(new CVSTag[0]));
+ addEntry(entry);
+ }
+ state = BEGIN;
+ }
+ return OK;
+ }
+
+ protected void beginFile(ICVSRepositoryLocation location, String fileName) {
+ currentFile = RemoteFile.create(fileName, location);
+ tagNames.clear();
+ tagRevisions.clear();
+ }
+
+ protected void addEntry(LogEntry entry) {
+ listener.handleLogEntryReceived(entry);
+ }
- private static final String NOTHING_KNOWN_ABOUT = "nothing known about "; //$NON-NLS-1$
-
- /**
- * Constructor used to get the log information for one or more files.
- */
- public LogListener() {
- this.currentFile = null;
- this.currentFileEntries = new ArrayList();
- }
-
- /**
- * Constructor used to get the log information for one file.
- */
- public LogListener(RemoteFile file, List entries) {
- this.currentFile = file;
- this.currentFileEntries = entries;
- this.entries.put(file.getRepositoryRelativePath(), entries);
- }
-
- /**
- * Return the log entry for the given remote file. The revision
- * of the remote file is used to determine which log entry to
- * return. If no log entry was fetched, <code>null</code>
- * is returned.
- */
- public ILogEntry getEntryFor(ICVSRemoteFile file) {
- List fileEntries = (List)entries.get(file.getRepositoryRelativePath());
- if (fileEntries != null) {
- for (Iterator iter = fileEntries.iterator(); iter.hasNext();) {
- ILogEntry entry = (ILogEntry) iter.next();
- try {
- if (entry.getRevision().equals(file.getRevision())) {
- return entry;
- }
- } catch (TeamException e) {
- // Log and continue
- CVSProviderPlugin.log(e);
- }
- }
- }
- return null;
- }
-
- public ILogEntry[] getEntriesFor(ICVSRemoteFile file) {
- List fileEntries = (List)entries.get(file.getRepositoryRelativePath());
- if (fileEntries != null) {
- return (ILogEntry[]) fileEntries.toArray(new ILogEntry[fileEntries.size()]);
- }
- return new ILogEntry[0];
- }
+ protected void handleInvalidFileName(ICVSRepositoryLocation location, String badFilePath) {
+ CVSProviderPlugin.log(IStatus.WARNING, "Invalid file path '" + badFilePath + "' received from " + location.toString(), null);
+ }
- public IStatus messageLine(String line, ICVSRepositoryLocation location, ICVSFolder commandRoot,
- IProgressMonitor monitor) {
- // Fields we will find in the log for a file
- // keys = String (tag name), values = String (tag revision number) */
- switch (state) {
- case BEGIN:
- if (line.startsWith("RCS file: ")) { //$NON-NLS-1$
- // We are starting to recieve the log for a file
- String fileName = getRelativeFilePath(location, line.substring(10).trim());
- if (fileName == null) {
- // We couldn't determine the file name so dump the entries
- currentFile = null;
- currentFileEntries = new ArrayList();
- } else {
- if (currentFile == null || !currentFile.getRepositoryRelativePath().equals(fileName)) {
- // We are starting another file
- currentFile = RemoteFile.create(fileName, location);
- currentFileEntries = (List)entries.get(currentFile.getRepositoryRelativePath());
- if (currentFileEntries == null) {
- currentFileEntries = new ArrayList();
- entries.put(currentFile.getRepositoryRelativePath(), currentFileEntries);
- }
- tagNames.clear();
- tagRevisions.clear();
- }
- }
- } else if (line.startsWith("symbolic names:")) { //$NON-NLS-1$
- state = SYMBOLIC_NAMES;
- } else if (line.startsWith("revision ")) { //$NON-NLS-1$
- revision = line.substring(9);
- state = REVISION;
- }
- break;
- case SYMBOLIC_NAMES:
- if (line.startsWith("keyword substitution:")) { //$NON-NLS-1$
- state = BEGIN;
- } else {
- int firstColon = line.indexOf(':');
- String tagName = line.substring(1, firstColon);
- String tagRevision = line.substring(firstColon + 2);
- tagNames.add(tagName);
- tagRevisions.add(tagRevision);
- }
- break;
- case REVISION:
- // date: 2000/06/19 04:56:21; author: somebody; state: Exp; lines: +114 -45
- // get the creation date
- int endOfDateIndex = line.indexOf(';', 6);
- creationDate = line.substring(6, endOfDateIndex) + " GMT"; //$NON-NLS-1$
-
- // get the author name
- int endOfAuthorIndex = line.indexOf(';', endOfDateIndex + 1);
- author = line.substring(endOfDateIndex + 11, endOfAuthorIndex);
-
- // get the file state (because this revision might be "dead")
- fileState = line.substring(endOfAuthorIndex + 10, line.indexOf(';', endOfAuthorIndex + 1));
- comment = new StringBuffer();
- state = COMMENT;
- break;
- case COMMENT:
- // skip next line (info about branches) if it exists, if not then it is a comment line.
- if (line.startsWith("branches:")) break; //$NON-NLS-1$
- if (line.equals("=============================================================================") //$NON-NLS-1$
- || line.equals("----------------------------")) { //$NON-NLS-1$
- state = DONE;
- break;
- }
- if (comment.length() != 0) comment.append('\n');
- comment.append(line);
- break;
- }
- if (state == DONE) {
- // we are only interested in tag names for this revision, remove all others.
- List thisRevisionTags = new ArrayList(3);
- for (int i = 0; i < tagNames.size(); i++) {
- String tagName = (String) tagNames.get(i);
- String tagRevision = (String) tagRevisions.get(i);
- // If this is a branch tag then only include this tag with the revision
- // that is the root of this branch (e.g. 1.1 is root of branch 1.1.2).
- boolean isBranch = isBranchTag(tagRevision);
- if (isBranch) {
- int lastDot = tagRevision.lastIndexOf('.');
- if (lastDot == -1) {
- CVSProviderPlugin.log(IStatus.ERROR,
- Policy.bind("LogListener.invalidRevisionFormat", tagName, tagRevision), null); //$NON-NLS-1$
- } else {
- if (tagRevision.charAt(lastDot - 1) == '0' && tagRevision.charAt(lastDot - 2) == '.') {
- lastDot = lastDot - 2;
- }
- tagRevision = tagRevision.substring(0, lastDot);
- }
- }
- if (tagRevision.equals(revision)) {
- int type = isBranch ? CVSTag.BRANCH : CVSTag.VERSION;
- thisRevisionTags.add(new CVSTag(tagName, type));
- }
- }
- Date date = DateUtil.convertFromLogTime(creationDate);
- if (currentFile != null) {
- LogEntry entry = new LogEntry(currentFile, revision, author, date,
- comment.toString(), fileState, (CVSTag[]) thisRevisionTags.toArray(new CVSTag[0]));
- currentFileEntries.add(entry);
- }
- state = BEGIN;
- }
- return OK;
- }
+ /** branch tags have odd number of segments or have
+ * an even number with a zero as the second last segment
+ * e.g: 1.1.1, 1.26.0.2 are branch revision numbers */
+ protected boolean isBranchTag(String tagName) {
+ // First check if we have an odd number of segments (i.e. even number of dots)
+ int numberOfDots = 0;
+ int lastDot = 0;
+ for (int i = 0; i < tagName.length(); i++) {
+ if (tagName.charAt(i) == '.') {
+ numberOfDots++;
+ lastDot = i;
+ }
+ }
+ if ((numberOfDots % 2) == 0) return true;
+ if (numberOfDots == 1) return false;
+
+ // If not, check if the second lat segment is a zero
+ if (tagName.charAt(lastDot - 1) == '0' && tagName.charAt(lastDot - 2) == '.') return true;
+ return false;
+ }
- public IStatus errorLine(String line, ICVSRepositoryLocation location, ICVSFolder commandRoot, IProgressMonitor monitor) {
- String serverMessage = getServerMessage(line, location);
- if (serverMessage != null) {
- // look for the following condition
- // E cvs server: nothing known about fileName
- if (serverMessage.startsWith(NOTHING_KNOWN_ABOUT)) {
- return new CVSStatus(IStatus.ERROR, CVSStatus.DOES_NOT_EXIST, commandRoot, line);
- }
- }
- return OK;
- }
-
- /** branch tags have odd number of segments or have
- * an even number with a zero as the second last segment
- * e.g: 1.1.1, 1.26.0.2 are branch revision numbers */
- protected boolean isBranchTag(String tagName) {
- // First check if we have an odd number of segments (i.e. even number of dots)
- int numberOfDots = 0;
- int lastDot = 0;
- for (int i = 0; i < tagName.length(); i++) {
- if (tagName.charAt(i) == '.') {
- numberOfDots++;
- lastDot = i;
- }
- }
- if ((numberOfDots % 2) == 0) return true;
- if (numberOfDots == 1) return false;
-
- // If not, check if the second lat segment is a zero
- if (tagName.charAt(lastDot - 1) == '0' && tagName.charAt(lastDot - 2) == '.') return true;
- return false;
- }
-
- /*
- * Return the file path as a relative path to the
- * repository location
- */
- private String getRelativeFilePath(ICVSRepositoryLocation location, String fileName) {
- if (fileName.endsWith(",v")) { //$NON-NLS-1$
- fileName = fileName.substring(0, fileName.length() - 2);
- }
- fileName = Util.removeAtticSegment(fileName);
- String rootDirectory = location.getRootDirectory();
- if (fileName.startsWith(rootDirectory)) {
- try {
- fileName = Util.getRelativePath(rootDirectory, fileName);
- } catch (CVSException e) {
- CVSProviderPlugin.log(e);
- return null;
- }
- }
- return fileName;
- }
}
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 7703cd2fc..e685233a5 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
@@ -22,6 +22,7 @@ import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.*;
import org.eclipse.team.internal.ccvs.core.client.Command.*;
+import org.eclipse.team.internal.ccvs.core.client.listeners.ILogEntryListener;
import org.eclipse.team.internal.ccvs.core.client.listeners.LogListener;
import org.eclipse.team.internal.ccvs.core.connection.CVSServerException;
import org.eclipse.team.internal.ccvs.core.syncinfo.*;
@@ -33,7 +34,22 @@ import org.eclipse.team.internal.ccvs.core.util.Assert;
*/
public class RemoteFile extends RemoteResource implements ICVSRemoteFile {
- // sync info in byte form
+ /*
+ * Listener for accumulating the entries fetched using the "cvs log" command
+ */
+ private final class LogEntryListener implements ILogEntryListener {
+ private final List entries = new ArrayList();
+ public void handleLogEntryReceived(ILogEntry entry) {
+ if (entry.getRemoteFile().getRepositoryRelativePath().equals(getRepositoryRelativePath())) {
+ entries.add(entry);
+ }
+ }
+ public ILogEntry[] getEntries() {
+ return (ILogEntry[])entries.toArray(new ILogEntry[entries.size()]);
+ }
+ }
+
+ // sync info in byte form
private byte[] syncBytes;
// cache the log entry for the remote file
private ILogEntry entry;
@@ -210,17 +226,18 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile {
session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
try {
try {
- final List entries = new ArrayList();
+ LogEntryListener listener = new LogEntryListener();
IStatus status = Command.LOG.execute(
session,
Command.NO_GLOBAL_OPTIONS,
new LocalOption[] {
Log.makeRevisionOption(getRevision())},
new ICVSResource[] { RemoteFile.this },
- new LogListener(RemoteFile.this, entries),
+ new LogListener(RemoteFile.this, listener),
Policy.subMonitorFor(monitor, 90));
- if (entries.size() == 1) {
- entry = (ILogEntry)entries.get(0);
+ ILogEntry[] entries = listener.getEntries();
+ if (entries.length == 1) {
+ entry = entries[0];
}
if (status.getCode() == CVSStatus.SERVER_ERROR) {
throw new CVSServerException(status);
@@ -241,21 +258,22 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile {
public ILogEntry[] getLogEntries(IProgressMonitor monitor) throws CVSException {
monitor = Policy.monitorFor(monitor);
monitor.beginTask(Policy.bind("RemoteFile.getLogEntries"), 100); //$NON-NLS-1$
- final List entries = new ArrayList();
Session session = new Session(getRepository(), parent, false /* output to console */);
session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
try {
QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness();
try {
CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE);
+ LogEntryListener listener = new LogEntryListener();
IStatus status = Command.LOG.execute(
session,
Command.NO_GLOBAL_OPTIONS, Command.NO_LOCAL_OPTIONS,
- new ICVSResource[] { RemoteFile.this }, new LogListener(RemoteFile.this, entries),
+ new ICVSResource[] { RemoteFile.this }, new LogListener(RemoteFile.this, listener),
Policy.subMonitorFor(monitor, 90));
if (status.getCode() == CVSStatus.SERVER_ERROR) {
throw new CVSServerException(status);
}
+ return listener.getEntries();
} finally {
CVSProviderPlugin.getPlugin().setQuietness(quietness);
monitor.done();
@@ -263,7 +281,6 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile {
} finally {
session.close();
}
- return (ILogEntry[])entries.toArray(new ILogEntry[entries.size()]);
}
/**
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RemoteLogOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RemoteLogOperation.java
index b50aff5e5..4604aac40 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RemoteLogOperation.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/RemoteLogOperation.java
@@ -18,10 +18,10 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.*;
-import org.eclipse.team.internal.ccvs.core.client.listeners.LogEntry;
-import org.eclipse.team.internal.ccvs.core.client.listeners.LogListener;
+import org.eclipse.team.internal.ccvs.core.client.listeners.*;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.util.Util;
+import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.Policy;
import org.eclipse.ui.IWorkbenchPart;
@@ -39,36 +39,62 @@ public class RemoteLogOperation extends RepositoryLocationOperation {
* A log entry cache that can be shared by multiple instances of the
* remote log operation.
*/
- public static class LogEntryCache {
+ public static class LogEntryCache implements ILogEntryListener {
/*
- * Map that is used for the single revision cases
+ * Cache of all log entries
*/
- private Map entries = new HashMap(); /* Map ICVSRemoteFile->ILogEntry */
-
- /*
- * Map that is used to cache multiple ILogEntry for a single resource
- */
- private Map allEntries = new HashMap(); /* Map String->ILogEntry[] */
+ private Map entries = new HashMap(); /* Map String:remoteFilePath->Map (String:revision -> ILogEntry) */
+ private Map internalGetLogEntries(String path) {
+ return (Map)entries.get(path);
+ }
+
+ private ILogEntry internalGetLogEntry(String path, String revision) {
+ Map fileEntries = internalGetLogEntries(path);
+ if (fileEntries != null) {
+ return (ILogEntry)fileEntries.get(revision);
+ }
+ return null;
+ }
+
+ public String[] getCachedFilePaths() {
+ return (String[]) entries.keySet().toArray(new String[entries.size()]);
+ }
+
/**
- * Return the log entry that was fetch for the given resource
- * or <code>null</code> if no entry was fetched.
+ * Return the log entry that for the given resource
+ * or <code>null</code> if no entry was fetched or the
+ * resource is not a file.
* @param getFullPath(resource) the resource
- * @return the fetched log entry or <code>null</code>
+ * @return the log entry or <code>null</code>
*/
public synchronized ILogEntry getLogEntry(ICVSRemoteResource resource) {
- return (ILogEntry)entries.get(resource);
+ if (resource instanceof ICVSRemoteFile) {
+ try {
+ String path = getFullPath(resource);
+ String revision = ((ICVSRemoteFile)resource).getRevision();
+ return internalGetLogEntry(path, revision);
+ } catch (TeamException e) {
+ // Log and return null
+ CVSUIPlugin.log(e);
+ }
+ }
+ return null;
}
-
- /**
+
+ /**
* Return the log entries that were fetched for the given resource
* or an empty list if no entry was fetched.
* @param getFullPath(resource) the resource
* @return the fetched log entries or an empty list is none were found
*/
public synchronized ILogEntry[] getLogEntries(ICVSRemoteResource resource) {
- return (ILogEntry[])allEntries.get(getFullPath(resource));
+ Map fileEntries = internalGetLogEntries(getFullPath(resource));
+ if (fileEntries != null) {
+ return (ILogEntry[]) fileEntries.values().toArray(new ILogEntry[fileEntries.size()]);
+ }
+ return null;
}
/*
@@ -83,27 +109,10 @@ public class RemoteLogOperation extends RepositoryLocationOperation {
public synchronized void clearEntries() {
entries.clear();
- allEntries.clear();
}
-
- public synchronized void cacheEntries(ICVSRemoteResource[] remotes, LogListener listener) {
- // Record the log entries for the files we want
- for (int i = 0; i < remotes.length; i++) {
- ICVSRemoteResource resource = remotes[i];
- if (!resource.isContainer()) {
- ICVSRemoteFile file = (ICVSRemoteFile) resource;
- ILogEntry entry = listener.getEntryFor(file);
- if (entry != null) {
- entries.put(file, entry);
- }
- ILogEntry allLogs[] = listener.getEntriesFor(file);
- allEntries.put(getFullPath(file), allLogs);
- }
- }
- }
public synchronized ICVSRemoteFile getImmediatePredecessor(ICVSRemoteFile file) throws TeamException {
- ILogEntry[] allLogs = (ILogEntry[])allEntries.get(getFullPath(file));
+ ILogEntry[] allLogs = getLogEntries(file);
String revision = file.getRevision();
// First decrement the last digit and see if that revision exists
String predecessorRevision = getPredecessorRevision(revision);
@@ -186,13 +195,22 @@ public class RemoteLogOperation extends RepositoryLocationOperation {
*/
public synchronized void clearEntries(ICVSRemoteResource resource) {
String remotePath = getFullPath(resource);
- LogEntry[] entries = (LogEntry[])allEntries.remove(remotePath);
- if (entries != null) {
- for (int i = 0; i < entries.length; i++) {
- LogEntry entry = entries[i];
- this.entries.remove(entry.getRemoteFile());
- }
+ entries.remove(remotePath);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.ccvs.core.client.listeners.ILogEntryListener#addEntry(org.eclipse.team.internal.ccvs.core.client.listeners.LogEntry)
+ */
+ public void handleLogEntryReceived(ILogEntry entry) {
+ ICVSRemoteFile file = entry.getRemoteFile();
+ String fullPath = getFullPath(file);
+ String revision = entry.getRevision();
+ Map fileEntries = internalGetLogEntries(fullPath);
+ if (fileEntries == null) {
+ fileEntries = new HashMap();
+ entries.put(fullPath, fileEntries);
}
+ fileEntries.put(revision, entry);
}
}
@@ -209,7 +227,8 @@ public class RemoteLogOperation extends RepositoryLocationOperation {
protected void execute(ICVSRepositoryLocation location, ICVSRemoteResource[] remoteResources, IProgressMonitor monitor) throws CVSException {
monitor.beginTask(Policy.bind("RemoteLogOperation.0", location.getHost()), 100); //$NON-NLS-1$
Session s = new Session(location, CVSWorkspaceRoot.getCVSFolderFor(ResourcesPlugin.getWorkspace().getRoot()), false /* do not output to console */);
- LogListener listener = new LogListener();
+ // Create a log listener that will update the cache as entries are received
+ LogListener listener = new LogListener(entryCache);
ICVSRemoteResource[] remotes = remoteResources;
Command.LocalOption[] localOptions;
@@ -236,8 +255,6 @@ public class RemoteLogOperation extends RepositoryLocationOperation {
} finally {
s.close();
}
-
- entryCache.cacheEntries(remotes, listener);
}
}

Back to the top