diff options
author | Michael Valenta | 2002-01-30 21:18:25 +0000 |
---|---|---|
committer | Michael Valenta | 2002-01-30 21:18:25 +0000 |
commit | 169b3120edd2b72f8ebf6f0a2e5f5bb2146db7ab (patch) | |
tree | d91d107b0e60f0cffee63b940bfd6341be4f9d82 | |
parent | 812f97006fd9d7b8a7681eaffa77786dfb110267 (diff) | |
download | eclipse.platform.team-169b3120edd2b72f8ebf6f0a2e5f5bb2146db7ab.tar.gz eclipse.platform.team-169b3120edd2b72f8ebf6f0a2e5f5bb2146db7ab.tar.xz eclipse.platform.team-169b3120edd2b72f8ebf6f0a2e5f5bb2146db7ab.zip |
Performance and refactoring
18 files changed, 451 insertions, 294 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSException.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSException.java index f106f0dc8..c802d2ede 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSException.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSException.java @@ -125,7 +125,7 @@ public class CVSException extends TeamException { IStatus.ERROR, CVSProviderPlugin.ID, UNABLE, - e.getMessage(), + e.getMessage() != null ? e.getMessage() : "", e)); } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/AbstractStructureVisitor.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/AbstractStructureVisitor.java index be7f466fe..5b71f3120 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/AbstractStructureVisitor.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/AbstractStructureVisitor.java @@ -121,14 +121,10 @@ abstract class AbstractStructureVisitor implements ICVSResourceVisitor { // If the file exists, send the appropriate indication to the server if (mFile.exists()) { if (mFile.isModified()) { -// if (session.isNoLocalChanges()) { -// session.sendIsModified(mFile); -// } else { - boolean binary = mode != null && mode.indexOf(ResourceSyncInfo.BINARY_TAG) != -1; - session.sendModified(mFile, monitor, binary); -// } + boolean binary = mode != null && mode.indexOf(ResourceSyncInfo.BINARY_TAG) != -1; + session.sendModified(mFile, binary, monitor); } else { - session.sendUnchanged(mFile.getName()); + session.sendUnchanged(mFile); } } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/AddStructureVisitor.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/AddStructureVisitor.java index 06086ec49..eb664c723 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/AddStructureVisitor.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/AddStructureVisitor.java @@ -47,9 +47,10 @@ class AddStructureVisitor extends AbstractStructureVisitor { mFile.getParent().accept(this); } - // We just send the fact, that the file is modified - // not the data, we do not need it. - session.sendIsModified(mFile); + // Sends the Is-modified request if it is supported, otherwise + // the file contents are sent as binary. The server does not + // need the contents at this stage so this should not be a problem. + session.sendIsModified(mFile, true, monitor); } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Checkout.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Checkout.java index 4baa88039..1d23b4ddc 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Checkout.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Checkout.java @@ -7,15 +7,16 @@ package org.eclipse.team.internal.ccvs.core.client; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.team.ccvs.core.CVSTag; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.client.Command.GlobalOption; import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption; import org.eclipse.team.internal.ccvs.core.client.Command.Option; import org.eclipse.team.internal.ccvs.core.client.listeners.ModuleDefinitionsListener; -import org.eclipse.team.internal.ccvs.core.client.listeners.ModuleExpansion; import org.eclipse.team.internal.ccvs.core.connection.CVSServerException; import org.eclipse.team.internal.ccvs.core.resources.ICVSResource; import org.eclipse.team.internal.ccvs.core.resources.ICVSResourceVisitor; +import org.eclipse.team.internal.ccvs.core.resources.RemoteModule; import org.eclipse.team.internal.ccvs.core.util.Assert; public class Checkout extends Command { @@ -95,7 +96,7 @@ public class Checkout extends Command { /** * Perform a checkout to get the module expansions defined in the CVSROOT/modules file */ - public ModuleExpansion[] getModuleExpansions(Session session, IProgressMonitor monitor) + public RemoteModule[] getRemoteModules(Session session, CVSTag tag, IProgressMonitor monitor) throws CVSException { ModuleDefinitionsListener moduleDefinitionListener = new ModuleDefinitionsListener(); @@ -108,6 +109,6 @@ public class Checkout extends Command { throw new CVSServerException(status); } - return moduleDefinitionListener.getModuleExpansions(); + return RemoteModule.createRemoteModules(moduleDefinitionListener.getModuleExpansions(), session.getCVSRepositoryLocation(), tag); } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/DiffStructureVisitor.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/DiffStructureVisitor.java index ca5a49d1f..6d94c0b2c 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/DiffStructureVisitor.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/DiffStructureVisitor.java @@ -42,9 +42,9 @@ class DiffStructureVisitor extends FileStructureVisitor { } if (mFile.isModified() || newFile) { - session.sendModified(mFile, monitor, binary); + session.sendModified(mFile, binary, monitor); } else { - session.sendUnchanged(mFile.getName()); + session.sendUnchanged(mFile); } } } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java index cf030d99b..85b20a7f7 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Session.java @@ -5,7 +5,9 @@ package org.eclipse.team.internal.ccvs.core.client; * All Rights Reserved. */ +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; @@ -22,21 +24,43 @@ import org.eclipse.team.internal.ccvs.core.resources.ICVSFolder; import org.eclipse.team.internal.ccvs.core.resources.ICVSResource; import org.eclipse.team.internal.ccvs.core.resources.LocalFile; import org.eclipse.team.internal.ccvs.core.resources.LocalFolder; -import org.eclipse.team.internal.ccvs.core.syncinfo.*; import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; +import org.eclipse.team.internal.ccvs.core.util.Assert; public class Session { public static final String CURRENT_LOCAL_FOLDER = "."; public static final String CURRENT_REMOTE_FOLDER = ""; public static final String SERVER_SEPARATOR = "/"; - private Connection connection; - private CVSRepositoryLocation location; - private ICVSFolder localRoot; - private String validRequests; - private Date modTime; - private boolean noLocalChanges; + // default file transfer buffer size (in bytes) + private static int TRANSFER_BUFFER_SIZE = 8192; + // update progress bar in increments of this size (in bytes) + // no incremental progress shown for files smaller than this size + private static long TRANSFER_PROGRESS_INCREMENT = 32768; + + // the platform's line termination sequence + private static final byte[] PLATFORM_NEWLINE_BYTES = + System.getProperty("line.separator").getBytes(); // at least one byte long + // the server's line termination sequence + private static final int SERVER_NEWLINE_BYTE = 0x0a; // exactly one byte long + private static final byte[] SERVER_NEWLINE_BYTES = new byte[] { SERVER_NEWLINE_BYTE }; + // true iff newlines must be converted between platform and server formats + private static boolean MUST_CONVERT_NEWLINES = PLATFORM_NEWLINE_BYTES.length != 1 + && PLATFORM_NEWLINE_BYTES[0] != SERVER_NEWLINE_BYTE; + + // VCM 1.0 comitted files using CR/LF as a delimiter + private static final int CARRIAGE_RETURN_BYTE = 0x0d; + + private final CVSRepositoryLocation location; + private final ICVSFolder localRoot; private boolean outputToConsole; + private Connection connection = null; + private String validRequests = null; + private Date modTime = null; + private boolean noLocalChanges = false; + + // a shared buffer used for file transfers + private byte[] transferBuffer = null; /** * Creates a new CVS session. @@ -51,7 +75,6 @@ public class Session { public Session(ICVSRepositoryLocation location, ICVSFolder localRoot, boolean outputToConsole) { this.location = (CVSRepositoryLocation) location; this.localRoot = localRoot; - this.validRequests = ""; this.outputToConsole = outputToConsole; } @@ -163,8 +186,35 @@ public class Session { connection.writeLine("Kopt " + arg); } - public void sendIsModified(ICVSFile file) throws CVSException { - connection.writeLine("Is-modified " + file.getName()); + /** + * Sends an Is-modified request to the server without the file contents. + * <p>e.g. if a file called "local_file" was modified, sends: + * <pre> + * Is-modified local_file \n + * </pre></p><p> + * This request is an optimized form of the Modified request and may not + * be supported by all servers. Hence, if it is not supported, a Modified + * request is sent instead along with the file's contents. According to + * the CVS protocol specification, this request is only safe for use with + * some forms of: admin, annotate, diff, editors, log, watch-add, watch-off, + * watch-on, watch-remove, and watchers.<br> + * It may be possible to use this for: add, export, remove and status.<br> + * Do not use with co, ci, history, init, import, release, rdiff, rtag, or update. + * </p><p> + * Note: The most recent Directory request must have specified the file's + * parent folder. + * </p> + * + * @param file the file that was modified + * @see #sendModified + */ + public void sendIsModified(ICVSFile file, boolean isBinary, IProgressMonitor monitor) + throws CVSException { + if (isValidRequest("Is-modified")) { + connection.writeLine("Is-modified " + file.getName()); + } else { + sendModified(file, isBinary, monitor); + } } public void sendStaticDirectory() throws CVSException { @@ -221,10 +271,22 @@ public class Session { connection.writeLine("Global_option " + option); } - public void sendUnchanged(String filename) throws CVSException { - connection.writeLine("Unchanged " + filename); + /** + * Sends an Unchanged request to the server. + * <p>e.g. if a file called "local_file" was not modified, sends: + * <pre> + * Unchanged local_file \n + * </pre></p><p> + * Note: The most recent Directory request must have specified the file's + * parent folder. + * </p> + * + * @param file the file that was not modified + */ + public void sendUnchanged(ICVSFile file) throws CVSException { + connection.writeLine("Unchanged " + file.getName()); } - + public void sendQuestionable(String filename) throws CVSException { connection.writeLine("Questionable " + filename); } @@ -234,47 +296,268 @@ public class Session { } /** - * This does not only send the message to the server that the - * file is going to be uploaded.<br> - * It does also acctually upload the file.<br> - * NOTE: The entry line has to be send before calling this method + * Sends a Modified request to the server along with the file contents. + * <p>e.g. if a file called "local_file" was modified, sends: + * <pre> + * Modified local_file \n + * file_permissions \n + * file_size \n + * [... file_contents ...] + * </pre></p><p> + * Under some circumstances, Is-modified may be used in place of this request.<br> + * Do not use with history, init, import, rdiff, release, rtag, or update. + * </p><p> + * Note: The most recent Directory request must have specified the file's + * parent folder. + * </p> + * + * @param file the file that was modified + * @param isBinary if true the file is sent without translating line delimiters + * @param monitor the progress monitor + * @see #sendIsModified */ - public void sendModified(ICVSFile file, IProgressMonitor monitor, boolean binary) + public void sendModified(ICVSFile file, boolean isBinary, IProgressMonitor monitor) throws CVSException { - - // boolean binary; - - // Send - // - MODIFIED - // - permissions - // - size - // - Content of the file - - // Does not send the entryLinde !! - connection.writeLine("Modified " + file.getName()); - + connection.writeLine("Modified " + file.getName()); ResourceSyncInfo info = file.getSyncInfo(); - if (info == null || - info.getPermissions() == null) { - connection.writeLine(ResourceSyncInfo.DEFAULT_PERMISSIONS); - } else { + if (info != null && info.getPermissions() != null) { connection.writeLine(info.getPermissions()); - } + } else { + connection.writeLine(ResourceSyncInfo.DEFAULT_PERMISSIONS); + } + sendFile(file, isBinary, monitor); + } - String progressTitle = - Policy.bind("RequestSender.sendModified", file.getName()); - monitor.subTask(progressTitle); - file.sendTo(connection.getOutputStream(),binary, monitor); + /** + * Gets the shared file transfer buffer. + */ + private byte[] getTransferBuffer() { + if (transferBuffer == null) transferBuffer = new byte[TRANSFER_BUFFER_SIZE]; + return transferBuffer; } - InputStream getInputStream() throws CVSException { - return connection.getInputStream(); + /** + * Sends a file to the remote CVS server, possibly translating line delimiters. + * <p> + * Line termination sequences are automatically converted to linefeeds only + * (required by the CVS specification) when sending non-binary files. This + * may alter the actual size and contents of the file that is sent. + * </p><p> + * Note: Non-binary files must be small enough to fit in available memory. + * </p> + * @param file the file to be sent + * @param isBinary is true if the file should be sent without translation + * @param monitor the progress monitor + */ + public void sendFile(ICVSFile file, boolean isBinary, IProgressMonitor monitor) + throws CVSException { + // update progress monitor + String title = Policy.bind("LocalFile.sending", new Object[]{ file.getName() }); + monitor.subTask(Policy.bind("LocalFile.transferNoSize", title)); + // obtain an input stream for the file and its size + long size = file.getSize(); + InputStream in = file.getInputStream(); + OutputStream out = connection.getOutputStream(); + try { + if (isBinary || PLATFORM_NEWLINE_BYTES.length == 1) { + writeLine(Long.toString(size)); + if (! isBinary && MUST_CONVERT_NEWLINES) { + /*** convert newlines on-the-fly ***/ + transferWithProgress(in, out, size, + PLATFORM_NEWLINE_BYTES[0], SERVER_NEWLINE_BYTES, monitor, title); + } else { + /*** perform no conversion ***/ + transferWithProgress(in, out, size, 0, null, monitor, title); + } + } else { + // implies file is text, and we must convert newlines since size of platform newline + // sequence is not 1, but the server's is + /*** convert newlines in memory, since file size may change ***/ + Assert.isTrue(size < Integer.MAX_VALUE); + int fsize = (int) size; + byte[] fileContents; + if (fsize <= TRANSFER_BUFFER_SIZE) fileContents = getTransferBuffer(); + else fileContents = new byte[fsize]; + // translate the file from non-LF delimiters in memory and + // compute its reduced size + try { + // read exactly _size_ bytes + try { + for (int pos = 0, read; pos < fsize; pos += read) { + Policy.checkCanceled(monitor); + read = in.read(fileContents, pos, fsize - pos); + if (read == -1) { + // file ended prematurely + throw new IOException("Read finished prematurely"); + } + } + } finally { + in.close(); // remember to close the source file + in = null; + } + } catch (IOException e) { + throw CVSException.wrapException(e); + } + // convert platform line termination sequences + // conservative since it leaves any partial sequences alone (like stray CR's) + // assumes no prefix of a sequence + int cur = 0, match = 0; + for (int pos = 0; pos < fsize; ++pos) { + byte b = fileContents[pos]; + if (PLATFORM_NEWLINE_BYTES[match] == b) { + if (match == PLATFORM_NEWLINE_BYTES.length - 1) { + b = SERVER_NEWLINE_BYTE; + cur -= match; + match = 0; + } else match += 1; + } else { + match = 0; + } + fileContents[cur++] = b; + } + // send file + writeLine(Integer.toString(cur)); + in = new ByteArrayInputStream(fileContents, 0, cur); + transferWithProgress(in, out, cur, 0, null, monitor, title); + } + } finally { + try { + if (in != null) in.close(); + } catch (IOException e) { + throw CVSException.wrapException(e); + } + } } - - OutputStream getOutputStream() throws CVSException { - return connection.getOutputStream(); + + /** + * Receives a file from the remote CVS server, possibly translating line delimiters. + * <p> + * Line termination sequences are automatically converted to platform format + * only when receiving non-binary files. This may alter the actual size and + * contents of the file that is received. + * </p><p> + * Translation is performed on-the-fly, so the file need not fit in available memory. + * </p> + * @param file the file to be received + * @param isBinary is true if the file should be received without translation + * @param monitor the progress monitor + */ + public void receiveFile(ICVSFile file, boolean isBinary, IProgressMonitor monitor) + throws CVSException { + // update progress monitor + String title = Policy.bind("LocalFile.receiving", new Object[]{ file.getName() }); + monitor.subTask(Policy.bind("LocalFile.transferNoSize", title)); + // get the file size from the server + long size; + try { + size = Long.parseLong(readLine(), 10); + } catch (NumberFormatException e) { + throw new CVSException("Malformed file transmission received", e); + } + // obtain an output stream for the file + OutputStream out = file.getOutputStream(); + try { + transferWithProgress(connection.getInputStream(), out, size, SERVER_NEWLINE_BYTE, + isBinary ? null : PLATFORM_NEWLINE_BYTES, monitor, title); + } finally { + try { + out.close(); + } catch (IOException e) { + throw CVSException.wrapException(e); + } + } } + /** + * Transfers a file to or from the remove CVS server, possibly expanding line delimiters. + * <p> + * Line termination sequences are only converted upon request by specifying an + * array containing the expected sequence of bytes representing an outbound newline, + * and a single byte representing an inbound newline. If null is passed for the + * former, the file is assumed to have binary contents, hence no translation is + * performed. + * </p><p> + * Translation is performed on-the-fly, so the file need not fit in available memory. + * </p> + * @param in the input stream + * @param out the output stream + * @param size the source file size + * @param newlineIn the single byte for a received newline, ignored if binary + * @param newlineOut the sequence of bytes for sent newline, or null if binary + * @param monitor the progress monitor + * @param title the name of the file being received (as shown in the monitor) + */ + private void transferWithProgress(InputStream in, OutputStream out, + long size, int newlineIn, byte[] newlineOut, IProgressMonitor monitor, String title) + throws CVSException { + long nextProgressThresh = TRANSFER_PROGRESS_INCREMENT; + Long ksize = new Long(size / 1024); + try { + byte[] buffer = getTransferBuffer(); + final int wfirst, wlast; + if (newlineOut != null) { + wfirst = buffer.length / 2; + wlast = buffer.length - newlineOut.length - 1; // reserve space for newline & stray CR + } else { + wfirst = buffer.length; + wlast = wfirst; + } + int wpos = wfirst; + // read exactly _size_ bytes + boolean fixCRLF = (newlineIn == SERVER_NEWLINE_BYTE); + boolean seenCR = false; // only true if fixCRLF and last byte was a CR + for (long totalRead = 0; totalRead < size;) { + Policy.checkCanceled(monitor); + int read = in.read(buffer, 0, (int) Math.min(wfirst, size - totalRead)); + if (read == -1) { + // file ended prematurely + throw new IOException("Read finished prematurely"); + } + totalRead += read; + if (newlineOut == null) { + // dump binary data + out.write(buffer, 0, read); + } else { + // filter newline sequences in memory from first half of buffer into second half + // then dump to output stream + for (int p = 0; p < read; ++p) { + final byte b = buffer[p]; + if (b == CARRIAGE_RETURN_BYTE && fixCRLF) { + seenCR = true; + } else { + if (b == newlineIn) { + // if fixCRLF we ignore previous CR (if there was one) + // replace newlineIn with newlineOut + for (int x = 0; x < newlineOut.length; ++x) buffer[wpos++] = newlineOut[x]; + } else { + if (seenCR) buffer[wpos++] = CARRIAGE_RETURN_BYTE; // preserve stray CR's + buffer[wpos++] = b; + } + seenCR = false; + } + if (wpos >= wlast) { + // flush output buffer + out.write(buffer, wfirst, wpos - wfirst); + wpos = wfirst; + } + } + } + // update progress monitor + if (totalRead > nextProgressThresh) { + monitor.subTask(Policy.bind("LocalFile.transfer", + new Object[] { title, new Long(totalRead / 1024), ksize})); + monitor.worked(read); + nextProgressThresh = totalRead + TRANSFER_PROGRESS_INCREMENT; + } + } + // flush pending buffered output + if (seenCR) buffer[wpos++] = CARRIAGE_RETURN_BYTE; // preserve stray CR's + if (wpos != wfirst) out.write(buffer, wfirst, wpos - wfirst); + } catch (IOException e) { + throw CVSException.wrapException(e); + } + } + public ICVSRepositoryLocation getCVSRepositoryLocation() { return location; } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Update.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Update.java index abce5430e..a9cca115f 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Update.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/Update.java @@ -42,11 +42,6 @@ public class Update extends Command { LocalOption[] localOptions, ICVSResource[] resources, IProgressMonitor monitor) throws CVSException { - // XXX other clients send this. Should we? - // requestSender.writeLine("UseUnchanged"); - // requestSender.writeLine("Case"); - // requestSender.sendArgument("-u"); - // Send all folders that are already managed to the server // even folders that are empty sendFileStructure(session, resources, false, true, monitor); diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/UpdatedHandler.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/UpdatedHandler.java index 9e63f0250..168cfea28 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/UpdatedHandler.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/UpdatedHandler.java @@ -9,10 +9,8 @@ import java.util.Date; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.internal.ccvs.core.CVSException; -import org.eclipse.team.internal.ccvs.core.Policy; import org.eclipse.team.internal.ccvs.core.resources.ICVSFile; import org.eclipse.team.internal.ccvs.core.resources.ICVSFolder; -import org.eclipse.team.internal.ccvs.core.syncinfo.*; import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; import org.eclipse.team.internal.ccvs.core.util.Assert; import org.eclipse.team.internal.ccvs.core.util.EntryFileDateFormat; @@ -69,14 +67,6 @@ class UpdatedHandler extends ResponseHandler { Date modTime = session.getModTime(); session.setModTime(null); - // prepare for a file transfer - int size; - try { - size = Integer.parseInt(session.readLine()); - } catch (NumberFormatException e) { - throw new CVSException(Policy.bind("Updated.numberFormat")); - } - // Get the local file String fileName = repositoryFile.substring(repositoryFile.lastIndexOf("/") + 1); @@ -87,11 +77,12 @@ class UpdatedHandler extends ResponseHandler { boolean binary = entryLine.indexOf("/" + ResourceSyncInfo.BINARY_TAG) != -1; boolean readOnly = permissionsLine.indexOf(READ_ONLY_FLAG) == -1; - mFile.receiveFrom(session.getInputStream(), size, binary, readOnly, monitor); + session.receiveFile(mFile, binary, monitor); + if (readOnly) mFile.setReadOnly(); // Set the timestamp in the file, set the result in the fileInfo String timestamp = null; - if (modTime != null) timestamp = dateFormatter.format(modTime.getTime()); + if (modTime != null) timestamp = dateFormatter.formatDate(modTime); mFile.setTimeStamp(timestamp); if (updateResponse) { timestamp = mFile.getTimeStamp(); diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ModuleDefinitionsListener.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ModuleDefinitionsListener.java index bffa517a1..797f7dc1e 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ModuleDefinitionsListener.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/listeners/ModuleDefinitionsListener.java @@ -48,72 +48,12 @@ public class ModuleDefinitionsListener implements ICommandOutputListener { else lastLine = line; - StringTokenizer tokenizer = new StringTokenizer(line); - - String module = tokenizer.nextToken(); - - List expansions = new ArrayList(10); - - // Read the options associated with the module - List localOptionsList = new ArrayList(); - String next = tokenizer.nextToken(); - while (next.charAt(0) == '-') { - switch (next.charAt(1)) { - case 'a': // alias - localOptionsList.add(Checkout.ALIAS); - break; - case 'l': // don't recurse - localOptionsList.add(Checkout.DO_NOT_RECURSE); - break; - case 'd': // directory - localOptionsList.add(Checkout.makeDirectoryNameOption(tokenizer.nextToken())); - break; - case 'e': - case 'i': - case 'o': - case 't': - case 'u': // Ignore any programs - tokenizer.nextToken(); - break; - case 's': // status - localOptionsList.add(Checkout.makeStatusOption(tokenizer.nextToken())); - break; - default: // unanticipated option. Ignore it and go on - } - next = tokenizer.nextToken(); - } - LocalOption[] localOptions = (LocalOption[]) localOptionsList.toArray(new LocalOption[localOptionsList.size()]); - - if (Checkout.ALIAS.isElementOf(localOptions)) { - // An alias expands to one or more projects or modules - expansions.add(next); - while (tokenizer.hasMoreTokens()) - expansions.add(tokenizer.nextToken()); - } else { - // The module definition can have a leading directory followed by some files - if (!(next.charAt(0) == '&')) { - String directory = next; - List files = new ArrayList(); - while (tokenizer.hasMoreTokens() && (next.charAt(0) != '&')) { - next = tokenizer.nextToken() ; - if ((next.charAt(0) != '&')) - files.add(next); - } - if (files.size() > 0) { - for (int i=0;i<files.size();i++) - expansions.add(directory + "/" + (String)files.get(i)); - } - else - expansions.add(directory); - } - // It can also have one or more module references - if (next.charAt(0) == '&') { - expansions.add(next); - while (tokenizer.hasMoreTokens()) - expansions.add(tokenizer.nextToken()); - } + // Use the module name as the key so that multi-line modules will be recorded properly + int firstSpace = line.indexOf(" "); + if (firstSpace > -1) { + String module = line.substring(firstSpace);; + moduleMap.put(module, line); } - moduleMap.put(module, new ModuleExpansion(module, (String[])expansions.toArray(new String[expansions.size()]), localOptions)); return OK; } @@ -125,12 +65,12 @@ public class ModuleDefinitionsListener implements ICommandOutputListener { ICVSFolder commandRoot, IProgressMonitor monitor) { - // XXX We should get any errors!!! + // XXX We should not get any errors!!! return OK; } - public ModuleExpansion[] getModuleExpansions() { - return (ModuleExpansion[])moduleMap.values().toArray(new ModuleExpansion[moduleMap.size()]); + public String[] getModuleExpansions() { + return (String[])moduleMap.values().toArray(new String[moduleMap.size()]); } public void reset() { diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/ICVSFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/ICVSFile.java index 8a1c499d2..bb4d3aed6 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/ICVSFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/ICVSFile.java @@ -25,19 +25,24 @@ public interface ICVSFile extends ICVSResource { */
long getSize();
+ /**
+ * Gets an input stream for reading from the file.
+ * It is the responsibility of the caller to close the stream when finished.
+ */
+ InputStream getInputStream() throws CVSException;
+
+ /**
+ * Gets an output stream for writing to the file.
+ * It is the responsibility of the caller to close the stream when finished.
+ */
+ OutputStream getOutputStream() throws CVSException;
+
/**
- * Transfer the contents of the file to the given output stream. If the file is
- * not binary the line-endings may be converted.
+ * Sets the file's read-only permission.
*/
- void sendTo(OutputStream outputStream, boolean binary, IProgressMonitor monitor) throws CVSException;
+ void setReadOnly() throws CVSException;
/**
- * Transfer the contents of an input stream to this file. If the file is
- * not binary the line-endings may be converted.
- */
- void receiveFrom(InputStream inputStream, long size, boolean binary, boolean readOnly, IProgressMonitor monitor) throws CVSException;
-
- /**
* Move the resource to another location. Does overwrite without
* promting.
*/
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/LocalFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/LocalFile.java index 290c784b8..13a5f5c57 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/LocalFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/LocalFile.java @@ -53,75 +53,29 @@ public class LocalFile extends LocalResource implements ICVSFile { return ioResource.length();
}
- public void receiveFrom(InputStream in, long size, boolean binary, boolean readOnly, IProgressMonitor monitor) throws CVSException {
- OutputStream out;
- String title;
-
- title = Policy.bind("LocalFile.receiving", ioResource.getName());
-
- try {
- // We don't need to buffer here because the methods used below do
- out = new FileOutputStream(ioResource);
-
- try {
- if (binary) {
- transferWithProgress(in, out, size, title, monitor);
- } else {
- transferText(in, out, size, title, false, monitor);
- }
- } finally {
- out.close();
- }
-
- if (readOnly) {
- ioResource.setReadOnly();
- }
+ public InputStream getInputStream() throws CVSException {
+ try {
+ return new FileInputStream(ioResource);
} catch (IOException e) {
- throw CVSException.wrapException(e);
+ throw CVSException.wrapException(e);
+ }
+ }
+
+ public OutputStream getOutputStream() throws CVSException {
+ try {
+ return new FileOutputStream(ioResource);
+ } catch (IOException e) {
+ throw CVSException.wrapException(e);
}
}
- public void sendTo(
- OutputStream out,
- boolean binary,
- IProgressMonitor monitor)
- throws CVSException {
-
- InputStream in;
- String title;
- long size = getSize();
- title = Policy.bind("LocalFile.sending",
- new Object[]{ioResource.getName()});
-
- try {
- // We don't need to buffer here because the methods used below do
- in = new FileInputStream(ioResource);
-
- try {
- if (binary) {
-
- // Send the size to the server
- out.write(("" + getSize()).getBytes());
- out.write(SERVER_NEWLINE.getBytes());
- transferWithProgress(in,out,size,title,monitor);
- } else {
-
- // In this case the size has to be computed.
- // Therefore we do send the size in transferText
- transferText(in,out,getSize(),title,true,monitor);
- }
- } finally {
- in.close();
- }
-
- } catch (IOException e) {
- throw CVSException.wrapException(e);
- }
+ public void setReadOnly() throws CVSException {
+ ioResource.setReadOnly();
}
public String getTimeStamp() throws CVSFileNotFoundException {
EntryFileDateFormat timestamp = new EntryFileDateFormat();
- return timestamp.format(ioResource.lastModified());
+ return timestamp.format(new Date(ioResource.lastModified()));
}
public void setTimeStamp(String date) throws CVSException {
@@ -132,7 +86,7 @@ public class LocalFile extends LocalResource implements ICVSFile { } else {
try {
EntryFileDateFormat timestamp = new EntryFileDateFormat();
- millSec = timestamp.toMilliseconds(date);
+ millSec = timestamp.toDate(date).getTime();
} catch (ParseException e) {
throw new CVSException(0,0,"Format of the Date for a TimeStamp not parseable",e);
}
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 8b02e0624..74d64de49 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 @@ -260,36 +260,24 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile, ICVSFi info = new ResourceSyncInfo(info.getName(), revision, info.getTimeStamp(), info.getKeywordMode(), info.getTag(), info.getPermissions()); } - /** - * @see IManagedFile#sendTo(OutputStream, IProgressMonitor, boolean) - */ - public void sendTo(OutputStream out, boolean binary, IProgressMonitor monitor) throws CVSException { - try { - String SERVER_NEWLINE = "\n"; - // Send the size to the server and no contents - out.write("0".getBytes()); - out.write(SERVER_NEWLINE.getBytes()); - } catch(IOException e) { - } - } - - /** - * @see IManagedFile#receiveFrom(InputStream, IProgressMonitor, long, boolean) - */ - public void receiveFrom(InputStream inputStream, long size, boolean binary, boolean readOnly, IProgressMonitor monitor) throws CVSException { - // NOTE: This should be changed such that the client or connection handles - // the proper transfer - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - if (binary) - LocalFile.transferWithProgress(inputStream, bos, (long)size, "", monitor); - else - LocalFile.transferText(inputStream, bos, (long)size, "", false, monitor); - contents = bos.toByteArray(); - } catch (IOException ex) { - throw CVSException.wrapException(ex); - } + + public InputStream getInputStream() throws CVSException { + return new ByteArrayInputStream(new byte[0]); } + + public OutputStream getOutputStream() throws CVSException { + // stores the contents of the file when the stream is closed + // could perhaps be optimized in some manner to avoid excessive array copying + return new ByteArrayOutputStream() { + public void close() throws IOException { + contents = toByteArray(); + super.close(); + } + }; + } + + public void setReadOnly() throws CVSException { + } /** * @see IManagedFile#getTimeStamp() diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolder.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolder.java index 1b423204a..224452e70 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolder.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolder.java @@ -56,7 +56,7 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC public static final String VIRTUAL_DIRECTORY = "CVSROOT/Emptydir"; - private FolderSyncInfo folderInfo; + protected FolderSyncInfo folderInfo; private ICVSRemoteResource[] children; private ICVSRepositoryLocation repository; @@ -68,13 +68,14 @@ public class RemoteFolder extends RemoteResource implements ICVSRemoteFolder, IC repositoryRelativePath.lastSegment() == null ? "" : repositoryRelativePath.lastSegment(), repository, repositoryRelativePath, - tag); + tag, + false); } - public RemoteFolder(RemoteFolder parent, String name, ICVSRepositoryLocation repository, IPath repositoryRelativePath, CVSTag tag) { + public RemoteFolder(RemoteFolder parent, String name, ICVSRepositoryLocation repository, IPath repositoryRelativePath, CVSTag tag, boolean isStatic) { this.info = new ResourceSyncInfo(name); this.parent = parent; - this.folderInfo = new FolderSyncInfo(repositoryRelativePath.toString(), repository.getLocation(), tag, false); + this.folderInfo = new FolderSyncInfo(repositoryRelativePath.toString(), repository.getLocation(), tag, isStatic); this.repository = repository; } diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/EntryFileDateFormat.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/EntryFileDateFormat.java index 61845541e..e475bd31e 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/EntryFileDateFormat.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/EntryFileDateFormat.java @@ -25,17 +25,18 @@ public class EntryFileDateFormat extends SimpleDateFormat { } /** - * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT - * represented by this Entry file string date format. + * Returns a date representing the number of milliseconds since + * January 1, 1970, 00:00:00 GMT represented by this Entry file + * string date format. */ - public long toMilliseconds(String text) throws ParseException { - return parse(text).getTime(); + public Date toDate(String text) throws ParseException { + return parse(text); } /** * long since 1970 => "Thu Oct 18 20:21:13 2001" */ - public String format(long milliseconds) { - return format(new Date(milliseconds)); + public String formatDate(Date date) { + return format(date); } }
\ No newline at end of file diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/compatible/SameResultEnv.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/compatible/SameResultEnv.java index 9d73848d8..a17ffc143 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/compatible/SameResultEnv.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/compatible/SameResultEnv.java @@ -475,8 +475,8 @@ public final class SameResultEnv extends JUnitTestCase { assertEquals("both timestamps should show same conflict state", merge1, merge2); assertEquals("both timestamps should show same dummy state", dummy1, dummy2); if(!merge1 && !dummy1) { - long time1 = timestampFormat.toMilliseconds(timestamp1); - long time2 = timestampFormat.toMilliseconds(timestamp2); + long time1 = timestampFormat.toDate(timestamp1).getTime(); + long time2 = timestampFormat.toDate(timestamp2).getTime(); /* timestamp tests don't seem to work on some systems. long difference = Math.abs(time1 - time2); assertTrue("timestamps should be in same timezone:" + timestamp1 + ":" + timestamp2, difference < (5*60*1000)); // 5 minutes diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/cvsresources/LocalFileTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/cvsresources/LocalFileTest.java index c043092df..d7fcb0ebc 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/cvsresources/LocalFileTest.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/cvsresources/LocalFileTest.java @@ -102,42 +102,42 @@ public class LocalFileTest extends JUnitTestCase { assertEquals(file1.getSyncInfo(),fileInfo3); } - public void testSendReceive() throws Exception { - - String sendTxt; - String expectTxt; - InputStream in; - - sendTxt = "This is my text"; - expectTxt = sendTxt.length() + "\n" + sendTxt; - - byte[] result = new byte[sendTxt.length()]; - - PipedInputStream pIn; - PipedOutputStream pOut; - - pIn = new PipedInputStream(); - pOut = new PipedOutputStream(pIn); - - in = new BufferedInputStream(pIn,sendTxt.length()); - - pOut.write(sendTxt.getBytes()); - file1.receiveFrom(in,sendTxt.length(),false,false, new NullProgressMonitor()); - in.close(); - pOut.close(); - - result = new byte[expectTxt.length()]; - pIn = new PipedInputStream(); - pOut = new PipedOutputStream(pIn); - - in = new BufferedInputStream(pIn,sendTxt.length()); - file1.sendTo(pOut,false, new NullProgressMonitor()); - in.read(result); - in.close(); - pOut.close(); - - assertEquals(new String(result),expectTxt); - } +// public void testSendReceive() throws Exception { +// +// String sendTxt; +// String expectTxt; +// InputStream in; +// +// sendTxt = "This is my text"; +// expectTxt = sendTxt.length() + "\n" + sendTxt; +// +// byte[] result = new byte[sendTxt.length()]; +// +// PipedInputStream pIn; +// PipedOutputStream pOut; +// +// pIn = new PipedInputStream(); +// pOut = new PipedOutputStream(pIn); +// +// in = new BufferedInputStream(pIn,sendTxt.length()); +// +// pOut.write(sendTxt.getBytes()); +// file1.receiveFrom(in,sendTxt.length(),false,false, new NullProgressMonitor()); +// in.close(); +// pOut.close(); +// +// result = new byte[expectTxt.length()]; +// pIn = new PipedInputStream(); +// pOut = new PipedOutputStream(pIn); +// +// in = new BufferedInputStream(pIn,sendTxt.length()); +// file1.sendTo(pOut,false, new NullProgressMonitor()); +// in.read(result); +// in.close(); +// pOut.close(); +// +// assertEquals(new String(result),expectTxt); +// } public void testTimestamp() throws Exception { diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/AllTests.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/AllTests.java index c596d472a..ddf80a3cc 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/AllTests.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/AllTests.java @@ -31,6 +31,7 @@ public class AllTests extends EclipseTest { public static Test suite() { TestSuite suite = new TestSuite(); + //suite.addTestSuite(ModuleTest.class); suite.addTestSuite(ImportTest.class); suite.addTestSuite(CVSProviderTest.class); suite.addTestSuite(RemoteResourceTest.class); diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/SyncElementTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/SyncElementTest.java index fb0407b58..52497e2f0 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/SyncElementTest.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/SyncElementTest.java @@ -51,7 +51,7 @@ public class SyncElementTest extends EclipseTest { public static Test suite() { TestSuite suite = new TestSuite(SyncElementTest.class); return new CVSTestSetup(suite); - //return new CVSTestSetup(new SyncElementTest("testSimpleMerge")); + //return new CVSTestSetup(new SyncElementTest("testOutgoingChanges")); } /* |