Browse Source

Add preservelastmodified to scp. PR 33939. Based on patch by Sandra Metz.

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@677187 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 17 years ago
parent
commit
13bc6453fe
7 changed files with 138 additions and 15 deletions
  1. +1
    -0
      CONTRIBUTORS
  2. +4
    -0
      WHATSNEW
  3. +4
    -0
      contributors.xml
  4. +9
    -0
      docs/manual/OptionalTasks/scp.html
  5. +14
    -2
      src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java
  6. +72
    -8
      src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java
  7. +34
    -5
      src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java

+ 1
- 0
CONTRIBUTORS View File

@@ -236,6 +236,7 @@ Roman Ivashin
Ronen Mashal Ronen Mashal
Russell Gold Russell Gold
Sam Ruby Sam Ruby
Sandra Metz
Scott Carlson Scott Carlson
Scott Ellsworth Scott Ellsworth
Scott M. Stirling Scott M. Stirling


+ 4
- 0
WHATSNEW View File

@@ -168,6 +168,10 @@ Other changes:
* <sshexec> now supports input in a way similar to <exec> * <sshexec> now supports input in a way similar to <exec>
Bugzilla report 39197. 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 Changes from Ant 1.7.0 TO Ant 1.7.1
============================================= =============================================




+ 4
- 0
contributors.xml View File

@@ -955,6 +955,10 @@
<first>Sam</first> <first>Sam</first>
<last>Ruby</last> <last>Ruby</last>
</name> </name>
<name>
<first>Sandra</first>
<last>Metz</last>
</name>
<name> <name>
<first>Scott</first> <first>Scott</first>
<last>Carlson</last> <last>Carlson</last>


+ 9
- 0
docs/manual/OptionalTasks/scp.html View File

@@ -174,6 +174,15 @@ for more information. This task has been tested with jsch-0.1.2 and later.</p>
server that doesn't support scp1. <em>since Ant 1.7</em></td> server that doesn't support scp1. <em>since Ant 1.7</em></td>
<td valign="top" align="center">No; defaults to false.</td> <td valign="top" align="center">No; defaults to false.</td>
</tr> </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> </table>
<h3>Parameters specified as nested elements</h3> <h3>Parameters specified as nested elements</h3>




+ 14
- 2
src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java View File

@@ -49,6 +49,7 @@ public class Scp extends SSHBase {


private String fromUri; private String fromUri;
private String toUri; private String toUri;
private boolean preserveLastModified = false;
private List fileSets = null; private List fileSets = null;
private boolean isFromRemote, isToRemote; private boolean isFromRemote, isToRemote;
private boolean isSftp = false; private boolean isSftp = false;
@@ -116,6 +117,15 @@ public class Scp extends SSHBase {
this.isToRemote = false; this.isToRemote = false;
} }


/**
* 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 {@link #setTodir setTodir} but explicitly states * Similiar to {@link #setTodir setTodir} but explicitly states
* that the directory is a remote. * that the directory is a remote.
@@ -231,12 +241,14 @@ public class Scp extends SSHBase {
message = message =
new ScpFromMessage(getVerbose(), session, file, new ScpFromMessage(getVerbose(), session, file,
getProject().resolveFile(toPath), getProject().resolveFile(toPath),
fromSshUri.endsWith("*"));
fromSshUri.endsWith("*"),
preserveLastModified);
} else { } else {
message = message =
new ScpFromMessageBySftp(getVerbose(), session, file, new ScpFromMessageBySftp(getVerbose(), session, file,
getProject().resolveFile(toPath), getProject().resolveFile(toPath),
fromSshUri.endsWith("*"));
fromSshUri.endsWith("*"),
preserveLastModified);
} }
log("Receiving file: " + file); log("Receiving file: " + file);
message.setLogListener(this); message.setLogListener(this);


+ 72
- 8
src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java View File

@@ -27,7 +27,11 @@ import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import com.jcraft.jsch.JSchException; import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session; import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.Channel; import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import org.apache.tools.ant.util.FileUtils;


/** /**
* A helper object representing an scp download. * A helper object representing an scp download.
@@ -41,6 +45,7 @@ public class ScpFromMessage extends AbstractSshMessage {
private String remoteFile; private String remoteFile;
private File localFile; private File localFile;
private boolean isRecursive = false; private boolean isRecursive = false;
private boolean preserveLastModified = false;


/** /**
* Constructor for ScpFromMessage * Constructor for ScpFromMessage
@@ -74,10 +79,7 @@ public class ScpFromMessage extends AbstractSshMessage {
String aRemoteFile, String aRemoteFile,
File aLocalFile, File aLocalFile,
boolean recursive) { boolean recursive) {
super(verbose, session);
this.remoteFile = aRemoteFile;
this.localFile = aLocalFile;
this.isRecursive = recursive;
this(false, session, aRemoteFile, aLocalFile, recursive, false);
} }


/** /**
@@ -94,6 +96,30 @@ public class ScpFromMessage extends AbstractSshMessage {
this(false, session, aRemoteFile, aLocalFile, recursive); this(false, session, aRemoteFile, aLocalFile, recursive);
} }


/**
* 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. * Carry out the transfer.
* @throws IOException on i/o errors * @throws IOException on i/o errors
@@ -123,9 +149,14 @@ public class ScpFromMessage extends AbstractSshMessage {
log("done\n"); log("done\n");
} }


protected boolean getPreserveLastModified() {
return preserveLastModified;
}

private void startRemoteCpProtocol(InputStream in, private void startRemoteCpProtocol(InputStream in,
OutputStream out, OutputStream out,
File localFile) throws IOException {
File localFile)
throws IOException, JSchException {
File startFile = localFile; File startFile = localFile;
while (true) { while (true) {
// C0644 filesize filename - header for a regular file // C0644 filesize filename - header for a regular file
@@ -147,7 +178,7 @@ public class ScpFromMessage extends AbstractSshMessage {
parseAndFetchFile(serverResponse, startFile, out, in); parseAndFetchFile(serverResponse, startFile, out, in);
} else if (serverResponse.charAt(0) == 'D') { } else if (serverResponse.charAt(0) == 'D') {
startFile = parseAndCreateDirectory(serverResponse, startFile = parseAndCreateDirectory(serverResponse,
startFile);
startFile);
sendAck(out); sendAck(out);
} else if (serverResponse.charAt(0) == 'E') { } else if (serverResponse.charAt(0) == 'E') {
startFile = startFile.getParentFile(); startFile = startFile.getParentFile();
@@ -178,7 +209,8 @@ public class ScpFromMessage extends AbstractSshMessage {
private void parseAndFetchFile(String serverResponse, private void parseAndFetchFile(String serverResponse,
File localFile, File localFile,
OutputStream out, OutputStream out,
InputStream in) throws IOException {
InputStream in)
throws IOException, JSchException {
int start = 0; int start = 0;
int end = serverResponse.indexOf(" ", start + 1); int end = serverResponse.indexOf(" ", start + 1);
start = end + 1; start = end + 1;
@@ -197,7 +229,8 @@ public class ScpFromMessage extends AbstractSshMessage {
private void fetchFile(File localFile, private void fetchFile(File localFile,
long filesize, long filesize,
OutputStream out, OutputStream out,
InputStream in) throws IOException {
InputStream in)
throws IOException, JSchException {
byte[] buf = new byte[BUFFER_SIZE]; byte[] buf = new byte[BUFFER_SIZE];
sendAck(out); sendAck(out);


@@ -241,6 +274,37 @@ public class ScpFromMessage extends AbstractSshMessage {
fos.flush(); fos.flush();
fos.close(); 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) : "";
}
} }

+ 34
- 5
src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessageBySftp.java View File

@@ -28,6 +28,8 @@ import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.SftpATTRS; import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpProgressMonitor; import com.jcraft.jsch.SftpProgressMonitor;


import org.apache.tools.ant.util.FileUtils;

/** /**
* A helper object representing an scp download. * A helper object representing an scp download.
*/ */
@@ -54,11 +56,7 @@ public class ScpFromMessageBySftp extends ScpFromMessage {
String aRemoteFile, String aRemoteFile,
File aLocalFile, File aLocalFile,
boolean recursive) { boolean recursive) {
super(verbose, session);
this.verbose = verbose;
this.remoteFile = aRemoteFile;
this.localFile = aLocalFile;
this.isRecursive = recursive;
this(verbose, session, aRemoteFile, aLocalFile, recursive, false);
} }


/** /**
@@ -75,6 +73,31 @@ public class ScpFromMessageBySftp extends ScpFromMessage {
this(false, session, aRemoteFile, aLocalFile, recursive); this(false, session, aRemoteFile, aLocalFile, recursive);
} }


/**
* 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. * Carry out the transfer.
* @throws IOException on i/o errors * @throws IOException on i/o errors
@@ -171,5 +194,11 @@ public class ScpFromMessageBySftp extends ScpFromMessage {
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
logStats(startTime, endTime, (int) totalLength); logStats(startTime, endTime, (int) totalLength);
} }
if (getPreserveLastModified()) {
FileUtils.getFileUtils().setFileLastModified(localFile,
((long) le.getAttrs()
.getMTime())
* 1000);
}
} }
} }

Loading…
Cancel
Save