Author: bodewig Date: Wed Jul 16 01:07:44 2008 New Revision: 677187 URL: http://svn.apache.org/viewvc?rev=677187&view=rev Log: Add preservelastmodified to scp. PR 33939. Based on patch by Sandra Metz.
Modified: ant/core/trunk/CONTRIBUTORS ant/core/trunk/WHATSNEW ant/core/trunk/contributors.xml ant/core/trunk/docs/manual/OptionalTasks/scp.html ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java Modified: ant/core/trunk/CONTRIBUTORS URL: http://svn.apache.org/viewvc/ant/core/trunk/CONTRIBUTORS?rev=677187&r1=677186&r2=677187&view=diff ============================================================================== Binary files - no diff available. Modified: ant/core/trunk/WHATSNEW URL: http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=677187&r1=677186&r2=677187&view=diff ============================================================================== --- ant/core/trunk/WHATSNEW (original) +++ ant/core/trunk/WHATSNEW Wed Jul 16 01:07:44 2008 @@ -168,6 +168,10 @@ * <sshexec> now supports input in a way similar to <exec> Bugzilla report 39197. + * <scp> can now preserve the file modification time when downloading + files. + Bugzilla Issue 33939. + Changes from Ant 1.7.0 TO Ant 1.7.1 ============================================= Modified: ant/core/trunk/contributors.xml URL: http://svn.apache.org/viewvc/ant/core/trunk/contributors.xml?rev=677187&r1=677186&r2=677187&view=diff ============================================================================== --- ant/core/trunk/contributors.xml (original) +++ ant/core/trunk/contributors.xml Wed Jul 16 01:07:44 2008 @@ -956,6 +956,10 @@ <last>Ruby</last> </name> <name> + <first>Sandra</first> + <last>Metz</last> + </name> + <name> <first>Scott</first> <last>Carlson</last> </name> Modified: ant/core/trunk/docs/manual/OptionalTasks/scp.html URL: http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/OptionalTasks/scp.html?rev=677187&r1=677186&r2=677187&view=diff ============================================================================== --- ant/core/trunk/docs/manual/OptionalTasks/scp.html (original) +++ ant/core/trunk/docs/manual/OptionalTasks/scp.html Wed Jul 16 01:07:44 2008 @@ -174,6 +174,15 @@ server that doesn't support scp1. <em>since Ant 1.7</em></td> <td valign="top" align="center">No; defaults to false.</td> </tr> + <tr> + <td valign="top">preserveLastModified</td> + <td valign="top">Determines whether the last modification + timestamp of downloaded files is preserved. It only works when + transferring from a remote to a local system and probably doesn't + work with a server that doesn't support SSH2. <em>since Ant + 1.8.0</em></td> + <td valign="top" align="center">No; defaults to false.</td> + </tr> </table> <h3>Parameters specified as nested elements</h3> Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java?rev=677187&r1=677186&r2=677187&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java Wed Jul 16 01:07:44 2008 @@ -49,6 +49,7 @@ private String fromUri; private String toUri; + private boolean preserveLastModified = false; private List fileSets = null; private boolean isFromRemote, isToRemote; private boolean isSftp = false; @@ -117,6 +118,15 @@ } /** + * Sets flag to determine if file timestamp from + * remote system is to be preserved during copy. + * @since Ant 1.8.0 + */ + public void setPreservelastmodified(boolean yesOrNo) { + this.preserveLastModified = yesOrNo; + } + + /** * Similiar to [EMAIL PROTECTED] #setTodir setTodir} but explicitly states * that the directory is a remote. * @param aToUri a string representing the target of the copy. @@ -231,12 +241,14 @@ message = new ScpFromMessage(getVerbose(), session, file, getProject().resolveFile(toPath), - fromSshUri.endsWith("*")); + fromSshUri.endsWith("*"), + preserveLastModified); } else { message = new ScpFromMessageBySftp(getVerbose(), session, file, getProject().resolveFile(toPath), - fromSshUri.endsWith("*")); + fromSshUri.endsWith("*"), + preserveLastModified); } log("Receiving file: " + file); message.setLogListener(this); Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java?rev=677187&r1=677186&r2=677187&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java Wed Jul 16 01:07:44 2008 @@ -27,7 +27,11 @@ import java.io.ByteArrayOutputStream; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; +import com.jcraft.jsch.SftpATTRS; +import com.jcraft.jsch.SftpException; import com.jcraft.jsch.Channel; +import com.jcraft.jsch.ChannelSftp; +import org.apache.tools.ant.util.FileUtils; /** * A helper object representing an scp download. @@ -41,6 +45,7 @@ private String remoteFile; private File localFile; private boolean isRecursive = false; + private boolean preserveLastModified = false; /** * Constructor for ScpFromMessage @@ -74,10 +79,7 @@ String aRemoteFile, File aLocalFile, boolean recursive) { - super(verbose, session); - this.remoteFile = aRemoteFile; - this.localFile = aLocalFile; - this.isRecursive = recursive; + this(false, session, aRemoteFile, aLocalFile, recursive, false); } /** @@ -95,6 +97,30 @@ } /** + * 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 preservceLastModified whether to preserve file + * modification times + * @since Ant 1.8.0 + */ + public ScpFromMessage(boolean verbose, + Session session, + String aRemoteFile, + File aLocalFile, + boolean recursive, + boolean preserveLastModified) { + super(verbose, session); + this.remoteFile = aRemoteFile; + this.localFile = aLocalFile; + this.isRecursive = recursive; + this.preserveLastModified = preserveLastModified; + } + + /** * Carry out the transfer. * @throws IOException on i/o errors * @throws JSchException on errors detected by scp @@ -123,9 +149,14 @@ log("done\n"); } + protected boolean getPreserveLastModified() { + return preserveLastModified; + } + private void startRemoteCpProtocol(InputStream in, OutputStream out, - File localFile) throws IOException { + File localFile) + throws IOException, JSchException { File startFile = localFile; while (true) { // C0644 filesize filename - header for a regular file @@ -147,7 +178,7 @@ parseAndFetchFile(serverResponse, startFile, out, in); } else if (serverResponse.charAt(0) == 'D') { startFile = parseAndCreateDirectory(serverResponse, - startFile); + startFile); sendAck(out); } else if (serverResponse.charAt(0) == 'E') { startFile = startFile.getParentFile(); @@ -178,7 +209,8 @@ private void parseAndFetchFile(String serverResponse, File localFile, OutputStream out, - InputStream in) throws IOException { + InputStream in) + throws IOException, JSchException { int start = 0; int end = serverResponse.indexOf(" ", start + 1); start = end + 1; @@ -197,7 +229,8 @@ private void fetchFile(File localFile, long filesize, OutputStream out, - InputStream in) throws IOException { + InputStream in) + throws IOException, JSchException { byte[] buf = new byte[BUFFER_SIZE]; sendAck(out); @@ -241,6 +274,37 @@ fos.flush(); fos.close(); } + + if (getPreserveLastModified()) { + setLastModified(localFile); + } } + private void setLastModified(File localFile) throws JSchException { + SftpATTRS fileAttributes = null; + String remotePath = null; + ChannelSftp channel = openSftpChannel(); + channel.connect(); + try { + fileAttributes = channel.lstat(remoteDir(remoteFile) + + localFile.getName()); + } catch (SftpException e) { + throw new JSchException("failed to stat remote file", e); + } + FileUtils.getFileUtils().setFileLastModified(localFile, + ((long) fileAttributes + .getMTime()) + * 1000); + } + + /** + * returns the directory part of the remote file, if any. + */ + private static String remoteDir(String remoteFile) { + int index = remoteFile.lastIndexOf("/"); + if (index < 0) { + index = remoteFile.lastIndexOf("\\"); + } + return index > -1 ? remoteFile.substring(0, index + 1) : ""; + } } Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java?rev=677187&r1=677186&r2=677187&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java Wed Jul 16 01:07:44 2008 @@ -28,6 +28,8 @@ import com.jcraft.jsch.SftpATTRS; import com.jcraft.jsch.SftpProgressMonitor; +import org.apache.tools.ant.util.FileUtils; + /** * A helper object representing an scp download. */ @@ -54,11 +56,7 @@ String aRemoteFile, File aLocalFile, boolean recursive) { - super(verbose, session); - this.verbose = verbose; - this.remoteFile = aRemoteFile; - this.localFile = aLocalFile; - this.isRecursive = recursive; + this(verbose, session, aRemoteFile, aLocalFile, recursive, false); } /** @@ -76,6 +74,31 @@ } /** + * Constructor for ScpFromMessageBySftp. + * @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 + * @param preservceLastModified whether to preserve file + * modification times + * @since Ant 1.8.0 + */ + public ScpFromMessageBySftp(boolean verbose, + Session session, + String aRemoteFile, + File aLocalFile, + boolean recursive, + boolean preserveLastModified) { + super(verbose, session, aRemoteFile, aLocalFile, recursive, + preserveLastModified); + this.verbose = verbose; + this.remoteFile = aRemoteFile; + this.localFile = aLocalFile; + this.isRecursive = recursive; + } + + /** * Carry out the transfer. * @throws IOException on i/o errors * @throws JSchException on errors detected by scp @@ -171,5 +194,11 @@ long endTime = System.currentTimeMillis(); logStats(startTime, endTime, (int) totalLength); } + if (getPreserveLastModified()) { + FileUtils.getFileUtils().setFileLastModified(localFile, + ((long) le.getAttrs() + .getMTime()) + * 1000); + } } }