mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 01:26:04 -08:00
find method for FileTransfer trait
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -1409,6 +1409,7 @@ dependencies = [
|
||||
"ureq",
|
||||
"users",
|
||||
"whoami",
|
||||
"wildmatch",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1703,6 +1704,12 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wildmatch"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f44b95f62d34113cf558c93511ac93027e03e9c29a60dd0fd70e6e025c7270a"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
@@ -39,6 +39,7 @@ toml = "0.5.8"
|
||||
tui = { version = "0.14.0", features = ["crossterm"], default-features = false }
|
||||
ureq = { version = "2.0.2", features = ["json"] }
|
||||
whoami = "1.1.0"
|
||||
wildmatch = "1.0.13"
|
||||
|
||||
[target.'cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))'.dependencies]
|
||||
users = "0.11.0"
|
||||
|
||||
@@ -976,7 +976,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_copy() {
|
||||
fn test_filetransfer_ftp_copy() {
|
||||
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Connect
|
||||
assert!(ftp
|
||||
@@ -1090,6 +1090,32 @@ mod tests {
|
||||
assert!(ftp.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_ftp_find() {
|
||||
let mut client: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||
// Connect
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
21,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Pwd
|
||||
assert_eq!(client.pwd().ok().unwrap(), PathBuf::from("/"));
|
||||
// Search for file (let's search for pop3-*.png); there should be 2
|
||||
let search_res: Vec<FsFile> = client.find("pop3-*.png").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 2);
|
||||
// verify names
|
||||
assert_eq!(search_res[0].name.as_str(), "pop3-browser.png");
|
||||
assert_eq!(search_res[1].name.as_str(), "pop3-console-client.png");
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.find("pippo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_ftp_uninitialized() {
|
||||
let file: FsFile = FsFile {
|
||||
|
||||
@@ -23,12 +23,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// dependencies
|
||||
extern crate wildmatch;
|
||||
// locals
|
||||
use crate::fs::{FsEntry, FsFile};
|
||||
// ext
|
||||
use std::io::{Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::fs::{FsEntry, FsFile};
|
||||
|
||||
// Transfers
|
||||
use wildmatch::WildMatch;
|
||||
// exports
|
||||
pub mod ftp_transfer;
|
||||
pub mod scp_transfer;
|
||||
pub mod sftp_transfer;
|
||||
@@ -229,6 +232,66 @@ pub trait FileTransfer {
|
||||
/// This mighe be necessary for some protocols.
|
||||
/// You must call this method each time you want to finalize the read of the remote file.
|
||||
fn on_recv(&mut self, readable: Box<dyn Read>) -> Result<(), FileTransferError>;
|
||||
|
||||
/// ### find
|
||||
///
|
||||
/// Find files from current directory (in all subdirectories) whose name matches the provided search
|
||||
/// Search supports wildcards ('?', '*')
|
||||
fn find(&mut self, search: &str) -> Result<Vec<FsFile>, FileTransferError> {
|
||||
match self.is_connected() {
|
||||
true => {
|
||||
// Starting from current directory, iter dir
|
||||
match self.pwd() {
|
||||
Ok(p) => self.iter_search(p.as_path(), &WildMatch::new(search)),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
false => Err(FileTransferError::new(
|
||||
FileTransferErrorType::UninitializedSession,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// ### iter_search
|
||||
///
|
||||
/// Search recursively in `dir` for file matching the wildcard.
|
||||
/// NOTE: DON'T RE-IMPLEMENT THIS FUNCTION, unless the file transfer provides a faster way to do so
|
||||
/// NOTE: don't call this method from outside; consider it as private
|
||||
fn iter_search(
|
||||
&mut self,
|
||||
dir: &Path,
|
||||
filter: &WildMatch,
|
||||
) -> Result<Vec<FsFile>, FileTransferError> {
|
||||
let mut drained: Vec<FsFile> = Vec::new();
|
||||
// Scan directory
|
||||
match self.list_dir(dir) {
|
||||
Ok(entries) => {
|
||||
/* For each entry:
|
||||
- if is dir: call iter_search with `dir`
|
||||
- push `iter_search` result to `drained`
|
||||
- if is file: check if it matches `filter`
|
||||
- if it matches `filter`: push to to filter
|
||||
*/
|
||||
for entry in entries.iter() {
|
||||
match entry {
|
||||
FsEntry::Directory(dir) => {
|
||||
match self.iter_search(dir.abs_path.as_path(), filter) {
|
||||
Ok(mut filtered) => drained.append(&mut filtered),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
}
|
||||
FsEntry::File(file) => {
|
||||
if filter.is_match(file.name.as_str()) {
|
||||
drained.push(file.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(drained)
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Traits
|
||||
|
||||
@@ -1056,6 +1056,31 @@ mod tests {
|
||||
assert!(client.disconnect().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_find() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Search for file (let's search for pop3-*.png); there should be 2
|
||||
let search_res: Vec<FsFile> = client.find("pop3-*.png").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 2);
|
||||
// verify names
|
||||
assert_eq!(search_res[0].name.as_str(), "pop3-browser.png");
|
||||
assert_eq!(search_res[1].name.as_str(), "pop3-console-client.png");
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.find("pippo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_scp_recv() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
|
||||
@@ -603,15 +603,13 @@ impl FileTransfer for SftpFileTransfer {
|
||||
/// Execute a command on remote host
|
||||
fn exec(&mut self, cmd: &str) -> Result<String, FileTransferError> {
|
||||
match self.is_connected() {
|
||||
true => {
|
||||
match self.perform_shell_cmd_with_path(cmd) {
|
||||
true => match self.perform_shell_cmd_with_path(cmd) {
|
||||
Ok(output) => Ok(output),
|
||||
Err(err) => Err(FileTransferError::new_ex(
|
||||
FileTransferErrorType::ProtocolError,
|
||||
format!("{}", err),
|
||||
)),
|
||||
}
|
||||
}
|
||||
},
|
||||
false => Err(FileTransferError::new(
|
||||
FileTransferErrorType::UninitializedSession,
|
||||
)),
|
||||
@@ -876,6 +874,9 @@ mod tests {
|
||||
.is_err());
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
assert!(client
|
||||
.change_dir(PathBuf::from("gomar/pett").as_path())
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -899,6 +900,8 @@ mod tests {
|
||||
assert_eq!(files.len(), 3); // There are 3 files
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.list_dir(pwd.as_path()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -944,6 +947,33 @@ mod tests {
|
||||
assert_eq!(client.exec("echo 5").ok().unwrap().as_str(), "5\n");
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.exec("echo 1").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filetransfer_sftp_find() {
|
||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
.connect(
|
||||
String::from("test.rebex.net"),
|
||||
22,
|
||||
Some(String::from("demo")),
|
||||
Some(String::from("password"))
|
||||
)
|
||||
.is_ok());
|
||||
// Check session and scp
|
||||
assert!(client.session.is_some());
|
||||
// Search for file (let's search for pop3-*.png); there should be 2
|
||||
let search_res: Vec<FsFile> = client.find("pop3-*.png").ok().unwrap();
|
||||
assert_eq!(search_res.len(), 2);
|
||||
// verify names
|
||||
assert_eq!(search_res[0].name.as_str(), "pop3-browser.png");
|
||||
assert_eq!(search_res[1].name.as_str(), "pop3-console-client.png");
|
||||
// Disconnect
|
||||
assert!(client.disconnect().is_ok());
|
||||
// Verify err
|
||||
assert!(client.find("pippo").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user