https://bz.apache.org/bugzilla/show_bug.cgi?id=47552 Patch-by: Matthew Yanosmaster
@@ -252,6 +252,7 @@ Matthew Hawthorne | |||||
Matthew Inger | Matthew Inger | ||||
Matthew Kuperus Heun | Matthew Kuperus Heun | ||||
Matthew Watson | Matthew Watson | ||||
Matthew Yanos | |||||
Matthias Bhend | Matthias Bhend | ||||
Michael Bayne | Michael Bayne | ||||
Michael Clarke | Michael Clarke | ||||
@@ -27,6 +27,10 @@ Fixed bugs: | |||||
Other changes: | Other changes: | ||||
-------------- | -------------- | ||||
* <scp> now supports compression via the optional compressed attribute. | |||||
Bugzilla Report 47552 | |||||
Changes from Ant 1.9.6 TO Ant 1.9.7 | Changes from Ant 1.9.6 TO Ant 1.9.7 | ||||
=================================== | =================================== | ||||
@@ -1037,6 +1037,10 @@ | |||||
<first>Matthew</first> | <first>Matthew</first> | ||||
<last>Watson</last> | <last>Watson</last> | ||||
</name> | </name> | ||||
<name> | |||||
<first>Matthew</first> | |||||
<last>Yanos</last> | |||||
</name> | |||||
<name> | <name> | ||||
<first>Michael</first> | <first>Michael</first> | ||||
<last>Bayne</last> | <last>Bayne</last> | ||||
@@ -217,6 +217,12 @@ for more information. This task has been tested with jsch-0.1.2 and later.</p> | |||||
<em>since Ant 1.9.7</em></td> | <em>since Ant 1.9.7</em></td> | ||||
<td align="center" valign="top">No, defaults to 3</td> | <td align="center" valign="top">No, defaults to 3</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">compressed</td> | |||||
<td valign="top">Whether to enable compression during transfer. | |||||
<em>since Ant 1.9.8</em></td> | |||||
<td align="center" valign="top">No, defaults to false</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
@@ -40,6 +40,7 @@ public abstract class AbstractSshMessage { | |||||
private final Session session; | private final Session session; | ||||
private final boolean verbose; | private final boolean verbose; | ||||
private final boolean compressed; | |||||
private LogListener listener = new LogListener() { | private LogListener listener = new LogListener() { | ||||
public void log(final String message) { | public void log(final String message) { | ||||
// do nothing; | // do nothing; | ||||
@@ -61,7 +62,19 @@ public abstract class AbstractSshMessage { | |||||
* @since Ant 1.6.2 | * @since Ant 1.6.2 | ||||
*/ | */ | ||||
public AbstractSshMessage(final boolean verbose, final Session session) { | public AbstractSshMessage(final boolean verbose, final Session session) { | ||||
this(verbose, false, session); | |||||
} | |||||
/** | |||||
* Constructor for AbstractSshMessage | |||||
* @param verbose if true do verbose logging | |||||
* @param compression if true use compression | |||||
* @param session the ssh session to use | |||||
* @since Ant 1.9.8 | |||||
*/ | |||||
public AbstractSshMessage(boolean verbose, boolean compressed, Session session) { | |||||
this.verbose = verbose; | this.verbose = verbose; | ||||
this.compressed = compressed; | |||||
this.session = session; | this.session = session; | ||||
} | } | ||||
@@ -191,6 +204,15 @@ public abstract class AbstractSshMessage { | |||||
return verbose; | return verbose; | ||||
} | } | ||||
/** | |||||
* Is the compressed attribute set. | |||||
* @return true if the compressed attribute is set | |||||
* @since Ant 1.9.8 | |||||
*/ | |||||
protected final boolean getCompressed() { | |||||
return compressed; | |||||
} | |||||
/** | /** | ||||
* Track progress every 10% if 100kb < filesize < 1mb. For larger | * Track progress every 10% if 100kb < filesize < 1mb. For larger | ||||
* files track progress for every percent transmitted. | * files track progress for every percent transmitted. | ||||
@@ -54,6 +54,7 @@ public class Scp extends SSHBase { | |||||
private String fromUri; | private String fromUri; | ||||
private String toUri; | private String toUri; | ||||
private boolean preserveLastModified = false; | private boolean preserveLastModified = false; | ||||
private boolean compressed = false; | |||||
private List<ResourceCollection> rcs = null; | private List<ResourceCollection> rcs = null; | ||||
private boolean isFromRemote, isToRemote; | private boolean isFromRemote, isToRemote; | ||||
private boolean isSftp = false; | private boolean isSftp = false; | ||||
@@ -111,6 +112,15 @@ public class Scp extends SSHBase { | |||||
this.isFromRemote = true; | this.isFromRemote = true; | ||||
} | } | ||||
/** | |||||
* Sets flag to determine if compression should | |||||
* be used for the copy. | |||||
* @since Ant 1.9.8 | |||||
*/ | |||||
public void setCompressed(boolean compressed) { | |||||
this.compressed = compressed; | |||||
} | |||||
/** | /** | ||||
* Similar to {@link #setTodir setTodir} but explicitly states | * Similar to {@link #setTodir setTodir} but explicitly states | ||||
* that the directory is a local. This is the only way to specify | * that the directory is a local. This is the only way to specify | ||||
@@ -295,7 +305,8 @@ public class Scp extends SSHBase { | |||||
new ScpFromMessage(getVerbose(), session, file, | new ScpFromMessage(getVerbose(), session, file, | ||||
getProject().resolveFile(toPath), | getProject().resolveFile(toPath), | ||||
fromSshUri.endsWith("*"), | fromSshUri.endsWith("*"), | ||||
preserveLastModified); | |||||
preserveLastModified, | |||||
compressed); | |||||
} else { | } else { | ||||
message = | message = | ||||
new ScpFromMessageBySftp(getVerbose(), session, file, | new ScpFromMessageBySftp(getVerbose(), session, file, | ||||
@@ -339,7 +350,7 @@ public class Scp extends SSHBase { | |||||
session = openSession(); | session = openSession(); | ||||
ScpToMessage message = null; | ScpToMessage message = null; | ||||
if (!isSftp) { | if (!isSftp) { | ||||
message = new ScpToMessage(getVerbose(), session, | |||||
message = new ScpToMessage(getVerbose(), compressed, session, | |||||
list, file, preserveLastModified); | list, file, preserveLastModified); | ||||
} else { | } else { | ||||
message = new ScpToMessageBySftp(getVerbose(), session, | message = new ScpToMessageBySftp(getVerbose(), session, | ||||
@@ -371,7 +382,7 @@ public class Scp extends SSHBase { | |||||
ScpToMessage message = null; | ScpToMessage message = null; | ||||
if (!isSftp) { | if (!isSftp) { | ||||
message = | message = | ||||
new ScpToMessage(getVerbose(), session, | |||||
new ScpToMessage(getVerbose(), compressed, session, | |||||
getProject().resolveFile(fromPath), file, | getProject().resolveFile(fromPath), file, | ||||
preserveLastModified); | preserveLastModified); | ||||
} else { | } else { | ||||
@@ -115,7 +115,29 @@ public class ScpFromMessage extends AbstractSshMessage { | |||||
final File aLocalFile, | final File aLocalFile, | ||||
final boolean recursive, | final boolean recursive, | ||||
final boolean preserveLastModified) { | final boolean preserveLastModified) { | ||||
super(verbose, session); | |||||
this(verbose, session, aRemoteFile, aLocalFile, recursive, preserveLastModified, false); | |||||
} | |||||
/** | |||||
* Constructor for ScpFromMessage. | |||||
* @param verbose if true log extra information | |||||
* @param session the Scp session to use | |||||
* @param aRemoteFile the remote file name | |||||
* @param aLocalFile the local file | |||||
* @param recursive if true use recursion (-r option to scp) | |||||
* @param preserveLastModified whether to preserve file | |||||
* @param compressed if true use compression (-C option to scp) | |||||
* modification times | |||||
* @since Ant 1.9.8 | |||||
*/ | |||||
public ScpFromMessage(boolean verbose, | |||||
Session session, | |||||
String aRemoteFile, | |||||
File aLocalFile, | |||||
boolean recursive, | |||||
boolean preserveLastModified, | |||||
boolean compressed) { | |||||
super(verbose, compressed, session); | |||||
this.remoteFile = aRemoteFile; | this.remoteFile = aRemoteFile; | ||||
this.localFile = aLocalFile; | this.localFile = aLocalFile; | ||||
this.isRecursive = recursive; | this.isRecursive = recursive; | ||||
@@ -132,6 +154,9 @@ public class ScpFromMessage extends AbstractSshMessage { | |||||
if (isRecursive) { | if (isRecursive) { | ||||
command += "-r "; | command += "-r "; | ||||
} | } | ||||
if (getCompressed()) { | |||||
command += "-C "; | |||||
} | |||||
command += remoteFile; | command += remoteFile; | ||||
final Channel channel = openExecChannel(command); | final Channel channel = openExecChannel(command); | ||||
try { | try { | ||||
@@ -61,7 +61,18 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
* @since Ant 1.7 | * @since Ant 1.7 | ||||
*/ | */ | ||||
public ScpToMessage(final boolean verbose, final Session session) { | public ScpToMessage(final boolean verbose, final Session session) { | ||||
super(verbose, session); | |||||
this(verbose, false, session); | |||||
} | |||||
/** | |||||
* Constructor for ScpToMessage | |||||
* @param verbose if true do verbose logging | |||||
* @param compressed if true use compression | |||||
* @param session the ssh session to use | |||||
* @since Ant 1.9.8 | |||||
*/ | |||||
public ScpToMessage(final boolean verbose, boolean compressed, final Session session) { | |||||
super(verbose, compressed, session); | |||||
} | } | ||||
/** | /** | ||||
@@ -78,7 +89,26 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
final File aLocalFile, | final File aLocalFile, | ||||
final String aRemotePath, | final String aRemotePath, | ||||
final boolean preserveLastModified) { | final boolean preserveLastModified) { | ||||
this(verbose, session, aRemotePath); | |||||
this(verbose, false, session, aLocalFile, aRemotePath, preserveLastModified); | |||||
} | |||||
/** | |||||
* Constructor for a local file to remote. | |||||
* @param verbose if true do verbose logging | |||||
* @param compressed if true use compression | |||||
* @param session the scp session to use | |||||
* @param aLocalFile the local file | |||||
* @param aRemotePath the remote path | |||||
* @param preserveLastModified whether to preserve the last modified timestamps | |||||
* @since Ant 1.9.8 | |||||
*/ | |||||
public ScpToMessage(final boolean verbose, | |||||
final boolean compressed, | |||||
final Session session, | |||||
final File aLocalFile, | |||||
final String aRemotePath, | |||||
final boolean preserveLastModified) { | |||||
this(verbose, compressed, session, aRemotePath); | |||||
this.localFile = aLocalFile; | this.localFile = aLocalFile; | ||||
this.preserveLastModified = preserveLastModified; | this.preserveLastModified = preserveLastModified; | ||||
} | } | ||||
@@ -97,7 +127,26 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
final List aDirectoryList, | final List aDirectoryList, | ||||
final String aRemotePath, | final String aRemotePath, | ||||
final boolean preserveLastModified) { | final boolean preserveLastModified) { | ||||
this(verbose, session, aRemotePath); | |||||
this(verbose, false, session, aDirectoryList, aRemotePath, preserveLastModified); | |||||
} | |||||
/** | |||||
* Constructor for a local directories to remote. | |||||
* @param verbose if true do verbose logging | |||||
* @param compressed whether to use compression | |||||
* @param session the scp session to use | |||||
* @param aDirectoryList a list of directories | |||||
* @param aRemotePath the remote path | |||||
* @param preserveLastModified whether to preserve the last modified timestamps | |||||
* @since Ant 1.9.8 | |||||
*/ | |||||
public ScpToMessage(final boolean verbose, | |||||
final boolean compressed, | |||||
final Session session, | |||||
final List aDirectoryList, | |||||
final String aRemotePath, | |||||
final boolean preserveLastModified) { | |||||
this(verbose, compressed, session, aRemotePath); | |||||
this.directoryList = aDirectoryList; | this.directoryList = aDirectoryList; | ||||
this.preserveLastModified = preserveLastModified; | this.preserveLastModified = preserveLastModified; | ||||
} | } | ||||
@@ -142,7 +191,22 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
private ScpToMessage(final boolean verbose, | private ScpToMessage(final boolean verbose, | ||||
final Session session, | final Session session, | ||||
final String aRemotePath) { | final String aRemotePath) { | ||||
super(verbose, session); | |||||
this(verbose, false, session, aRemotePath); | |||||
} | |||||
/** | |||||
* Constructor for ScpToMessage. | |||||
* @param verbose if true do verbose logging | |||||
* @param compressed if true use compression | |||||
* @param session the scp session to use | |||||
* @param aRemotePath the remote path | |||||
* @since Ant 1.9.8 | |||||
*/ | |||||
private ScpToMessage(final boolean verbose, | |||||
final boolean compressed, | |||||
final Session session, | |||||
final String aRemotePath) { | |||||
super(verbose, compressed, session); | |||||
this.remotePath = aRemotePath; | this.remotePath = aRemotePath; | ||||
} | } | ||||
@@ -187,7 +251,15 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
} | } | ||||
private void doSingleTransfer() throws IOException, JSchException { | private void doSingleTransfer() throws IOException, JSchException { | ||||
final String cmd = "scp -t " + (getPreserveLastModified() ? "-p " : "") + remotePath; | |||||
StringBuilder sb = new StringBuilder("scp -t "); | |||||
if (getPreserveLastModified()) { | |||||
sb.append("-p "); | |||||
} | |||||
if (getCompressed()) { | |||||
sb.append("-C "); | |||||
} | |||||
sb.append(remotePath); | |||||
final String cmd = sb.toString(); | |||||
final Channel channel = openExecChannel(cmd); | final Channel channel = openExecChannel(cmd); | ||||
try { | try { | ||||
@@ -206,10 +278,15 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
} | } | ||||
private void doMultipleTransfer() throws IOException, JSchException { | private void doMultipleTransfer() throws IOException, JSchException { | ||||
final Channel channel = | |||||
openExecChannel("scp -r -d -t " | |||||
+ (getPreserveLastModified() ? "-p " : "") | |||||
+ remotePath); | |||||
StringBuilder sb = new StringBuilder("scp -r -d -t "); | |||||
if (getPreserveLastModified()) { | |||||
sb.append("-p "); | |||||
} | |||||
if (getCompressed()) { | |||||
sb.append("-C "); | |||||
} | |||||
sb.append(remotePath); | |||||
final Channel channel = openExecChannel(sb.toString()); | |||||
try { | try { | ||||
final OutputStream out = channel.getOutputStream(); | final OutputStream out = channel.getOutputStream(); | ||||
final InputStream in = channel.getInputStream(); | final InputStream in = channel.getInputStream(); | ||||