diff options
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); } } |