Localhost in activity; no more in Context

This commit is contained in:
veeso
2021-05-06 22:16:38 +02:00
parent 892be42988
commit a5fe62e502
5 changed files with 118 additions and 172 deletions

View File

@@ -56,6 +56,7 @@ pub enum NextActivity {
pub struct ActivityManager { pub struct ActivityManager {
context: Option<Context>, context: Option<Context>,
interval: Duration, interval: Duration,
local_dir: PathBuf,
} }
impl ActivityManager { impl ActivityManager {
@@ -64,19 +65,16 @@ impl ActivityManager {
/// Initializes a new Activity Manager /// Initializes a new Activity Manager
pub fn new(local_dir: &Path, interval: Duration) -> Result<ActivityManager, HostError> { pub fn new(local_dir: &Path, interval: Duration) -> Result<ActivityManager, HostError> {
// Prepare Context // Prepare Context
let host: Localhost = match Localhost::new(local_dir.to_path_buf()) {
Ok(h) => h,
Err(e) => return Err(e),
};
// Initialize configuration client // Initialize configuration client
let (config_client, error): (Option<ConfigClient>, Option<String>) = let (config_client, error): (Option<ConfigClient>, Option<String>) =
match Self::init_config_client() { match Self::init_config_client() {
Ok(cli) => (Some(cli), None), Ok(cli) => (Some(cli), None),
Err(err) => (None, Some(err)), Err(err) => (None, Some(err)),
}; };
let ctx: Context = Context::new(host, config_client, error); let ctx: Context = Context::new(config_client, error);
Ok(ActivityManager { Ok(ActivityManager {
context: Some(ctx), context: Some(ctx),
local_dir: local_dir.to_path_buf(),
interval, interval,
}) })
} }
@@ -182,7 +180,7 @@ impl ActivityManager {
/// Returns the next activity to run /// Returns the next activity to run
fn run_filetransfer(&mut self) -> Option<NextActivity> { fn run_filetransfer(&mut self) -> Option<NextActivity> {
// Get context // Get context
let ctx: Context = match self.context.take() { let mut ctx: Context = match self.context.take() {
Some(ctx) => ctx, Some(ctx) => ctx,
None => return None, None => return None,
}; };
@@ -193,7 +191,15 @@ impl ActivityManager {
}; };
// Prepare activity // Prepare activity
let protocol: FileTransferProtocol = ft_params.protocol; let protocol: FileTransferProtocol = ft_params.protocol;
let mut activity: FileTransferActivity = FileTransferActivity::new(protocol); let host: Localhost = match Localhost::new(self.local_dir.clone()) {
Ok(host) => host,
Err(err) => {
// Set error in context
ctx.set_error(format!("Could not initialize localhost: {}", err));
return None;
}
};
let mut activity: FileTransferActivity = FileTransferActivity::new(host, protocol);
// Prepare result // Prepare result
let result: Option<NextActivity>; let result: Option<NextActivity>;
// Create activity // Create activity

View File

@@ -191,32 +191,30 @@ impl FileTransferActivity {
if let Some(idx) = self.get_local_file_idx() { if let Some(idx) = self.get_local_file_idx() {
let dest_path: PathBuf = PathBuf::from(input); let dest_path: PathBuf = PathBuf::from(input);
let entry: FsEntry = self.local.get(idx).unwrap().clone(); let entry: FsEntry = self.local.get(idx).unwrap().clone();
if let Some(ctx) = self.context.as_mut() { match self.host.copy(&entry, dest_path.as_path()) {
match ctx.local.copy(&entry, dest_path.as_path()) { Ok(_) => {
Ok(_) => { self.log(
self.log( LogLevel::Info,
LogLevel::Info,
format!(
"Copied \"{}\" to \"{}\"",
entry.get_abs_path().display(),
dest_path.display()
)
.as_str(),
);
// Reload entries
let wrkdir: PathBuf = self.local.wrkdir.clone();
self.local_scan(wrkdir.as_path());
}
Err(err) => self.log_and_alert(
LogLevel::Error,
format!( format!(
"Could not copy \"{}\" to \"{}\": {}", "Copied \"{}\" to \"{}\"",
entry.get_abs_path().display(), entry.get_abs_path().display(),
dest_path.display(), dest_path.display()
err )
), .as_str(),
), );
// Reload entries
let wrkdir: PathBuf = self.local.wrkdir.clone();
self.local_scan(wrkdir.as_path());
} }
Err(err) => self.log_and_alert(
LogLevel::Error,
format!(
"Could not copy \"{}\" to \"{}\": {}",
entry.get_abs_path().display(),
dest_path.display(),
err
),
),
} }
} }
} }
@@ -255,13 +253,7 @@ impl FileTransferActivity {
} }
pub(super) fn action_local_mkdir(&mut self, input: String) { pub(super) fn action_local_mkdir(&mut self, input: String) {
match self match self.host.mkdir(PathBuf::from(input.as_str()).as_path()) {
.context
.as_mut()
.unwrap()
.local
.mkdir(PathBuf::from(input.as_str()).as_path())
{
Ok(_) => { Ok(_) => {
// Reload files // Reload files
self.log( self.log(
@@ -316,13 +308,7 @@ impl FileTransferActivity {
} }
let full_path: PathBuf = entry.get_abs_path(); let full_path: PathBuf = entry.get_abs_path();
// Rename file or directory and report status as popup // Rename file or directory and report status as popup
match self match self.host.rename(&entry, dst_path.as_path()) {
.context
.as_mut()
.unwrap()
.local
.rename(&entry, dst_path.as_path())
{
Ok(_) => { Ok(_) => {
// Reload files // Reload files
let path: PathBuf = self.local.wrkdir.clone(); let path: PathBuf = self.local.wrkdir.clone();
@@ -386,7 +372,7 @@ impl FileTransferActivity {
if let Some(entry) = entry { if let Some(entry) = entry {
let full_path: PathBuf = entry.get_abs_path(); let full_path: PathBuf = entry.get_abs_path();
// Delete file or directory and report status as popup // Delete file or directory and report status as popup
match self.context.as_mut().unwrap().local.remove(&entry) { match self.host.remove(&entry) {
Ok(_) => { Ok(_) => {
// Reload files // Reload files
let p: PathBuf = self.local.wrkdir.clone(); let p: PathBuf = self.local.wrkdir.clone();
@@ -473,22 +459,20 @@ impl FileTransferActivity {
} }
// Create file // Create file
let file_path: PathBuf = PathBuf::from(input.as_str()); let file_path: PathBuf = PathBuf::from(input.as_str());
if let Some(ctx) = self.context.as_mut() { if let Err(err) = self.host.open_file_write(file_path.as_path()) {
if let Err(err) = ctx.local.open_file_write(file_path.as_path()) { self.log_and_alert(
self.log_and_alert( LogLevel::Error,
LogLevel::Error, format!("Could not create file \"{}\": {}", file_path.display(), err),
format!("Could not create file \"{}\": {}", file_path.display(), err), );
); } else {
} else { self.log(
self.log( LogLevel::Info,
LogLevel::Info, format!("Created file \"{}\"", file_path.display()).as_str(),
format!("Created file \"{}\"", file_path.display()).as_str(), );
);
}
// Reload files
let path: PathBuf = self.local.wrkdir.clone();
self.local_scan(path.as_path());
} }
// Reload files
let path: PathBuf = self.local.wrkdir.clone();
self.local_scan(path.as_path());
} }
pub(super) fn action_remote_newfile(&mut self, input: String) { pub(super) fn action_remote_newfile(&mut self, input: String) {
@@ -516,46 +500,39 @@ impl FileTransferActivity {
), ),
Ok(tfile) => { Ok(tfile) => {
// Stat tempfile // Stat tempfile
if let Some(ctx) = self.context.as_mut() { let local_file: FsEntry = match self.host.stat(tfile.path()) {
let local_file: FsEntry = match ctx.local.stat(tfile.path()) { Err(err) => {
Err(err) => { self.log_and_alert(
self.log_and_alert( LogLevel::Error,
LogLevel::Error, format!("Could not stat tempfile: {}", err),
format!("Could not stat tempfile: {}", err), );
); return;
return; }
} Ok(f) => f,
Ok(f) => f, };
}; if let FsEntry::File(local_file) = local_file {
if let FsEntry::File(local_file) = local_file { // Create file
// Create file match self.client.send_file(&local_file, file_path.as_path()) {
match self.client.send_file(&local_file, file_path.as_path()) { Err(err) => self.log_and_alert(
Err(err) => self.log_and_alert( LogLevel::Error,
LogLevel::Error, format!("Could not create file \"{}\": {}", file_path.display(), err),
format!( ),
"Could not create file \"{}\": {}", Ok(writer) => {
file_path.display(), // Finalize write
err if let Err(err) = self.client.on_sent(writer) {
), self.log_and_alert(
), LogLevel::Warn,
Ok(writer) => { format!("Could not finalize file: {}", err),
// Finalize write );
if let Err(err) = self.client.on_sent(writer) { } else {
self.log_and_alert( self.log(
LogLevel::Warn, LogLevel::Info,
format!("Could not finalize file: {}", err), format!("Created file \"{}\"", file_path.display()).as_str(),
); );
} else {
self.log(
LogLevel::Info,
format!("Created file \"{}\"", file_path.display())
.as_str(),
);
}
// Reload files
let path: PathBuf = self.remote.wrkdir.clone();
self.remote_scan(path.as_path());
} }
// Reload files
let path: PathBuf = self.remote.wrkdir.clone();
self.remote_scan(path.as_path());
} }
} }
} }
@@ -564,7 +541,7 @@ impl FileTransferActivity {
} }
pub(super) fn action_local_exec(&mut self, input: String) { pub(super) fn action_local_exec(&mut self, input: String) {
match self.context.as_mut().unwrap().local.exec(input.as_str()) { match self.host.exec(input.as_str()) {
Ok(output) => { Ok(output) => {
// Reload files // Reload files
self.log( self.log(
@@ -605,7 +582,7 @@ impl FileTransferActivity {
} }
pub(super) fn action_local_find(&mut self, input: String) -> Result<Vec<FsEntry>, String> { pub(super) fn action_local_find(&mut self, input: String) -> Result<Vec<FsEntry>, String> {
match self.context.as_mut().unwrap().local.find(input.as_str()) { match self.host.find(input.as_str()) {
Ok(entries) => Ok(entries), Ok(entries) => Ok(entries),
Err(err) => Err(format!("Could not search for files: {}", err)), Err(err) => Err(format!("Could not search for files: {}", err)),
} }
@@ -666,7 +643,7 @@ impl FileTransferActivity {
FileExplorerTab::FindLocal | FileExplorerTab::Local => { FileExplorerTab::FindLocal | FileExplorerTab::Local => {
let full_path: PathBuf = entry.get_abs_path(); let full_path: PathBuf = entry.get_abs_path();
// Delete file or directory and report status as popup // Delete file or directory and report status as popup
match self.context.as_mut().unwrap().local.remove(&entry) { match self.host.remove(&entry) {
Ok(_) => { Ok(_) => {
// Reload files // Reload files
let p: PathBuf = self.local.wrkdir.clone(); let p: PathBuf = self.local.wrkdir.clone();

View File

@@ -46,6 +46,7 @@ use crate::filetransfer::sftp_transfer::SftpFileTransfer;
use crate::filetransfer::{FileTransfer, FileTransferProtocol}; use crate::filetransfer::{FileTransfer, FileTransferProtocol};
use crate::fs::explorer::FileExplorer; use crate::fs::explorer::FileExplorer;
use crate::fs::FsEntry; use crate::fs::FsEntry;
use crate::host::Localhost;
use crate::system::config_client::ConfigClient; use crate::system::config_client::ConfigClient;
// Includes // Includes
@@ -234,6 +235,7 @@ pub struct FileTransferActivity {
exit_reason: Option<ExitReason>, // Exit reason exit_reason: Option<ExitReason>, // Exit reason
context: Option<Context>, // Context holder context: Option<Context>, // Context holder
view: View, // View view: View, // View
host: Localhost, // Localhost
client: Box<dyn FileTransfer>, // File transfer client client: Box<dyn FileTransfer>, // File transfer client
local: FileExplorer, // Local File explorer state local: FileExplorer, // Local File explorer state
remote: FileExplorer, // Remote File explorer state remote: FileExplorer, // Remote File explorer state
@@ -249,13 +251,14 @@ impl FileTransferActivity {
/// ### new /// ### new
/// ///
/// Instantiates a new FileTransferActivity /// Instantiates a new FileTransferActivity
pub fn new(protocol: FileTransferProtocol) -> FileTransferActivity { pub fn new(host: Localhost, protocol: FileTransferProtocol) -> FileTransferActivity {
// Get config client // Get config client
let config_client: Option<ConfigClient> = Self::init_config_client(); let config_client: Option<ConfigClient> = Self::init_config_client();
FileTransferActivity { FileTransferActivity {
exit_reason: None, exit_reason: None,
context: None, context: None,
view: View::init(), view: View::init(),
host,
client: match protocol { client: match protocol {
FileTransferProtocol::Sftp => Box::new(SftpFileTransfer::new( FileTransferProtocol::Sftp => Box::new(SftpFileTransfer::new(
Self::make_ssh_storage(config_client.as_ref()), Self::make_ssh_storage(config_client.as_ref()),
@@ -296,7 +299,7 @@ impl Activity for FileTransferActivity {
// Put raw mode on enabled // Put raw mode on enabled
let _ = enable_raw_mode(); let _ = enable_raw_mode();
// Set working directory // Set working directory
let pwd: PathBuf = self.context.as_ref().unwrap().local.pwd(); let pwd: PathBuf = self.host.pwd();
// Get files at current wd // Get files at current wd
self.local_scan(pwd.as_path()); self.local_scan(pwd.as_path());
self.local.wrkdir = pwd; self.local.wrkdir = pwd;

View File

@@ -221,13 +221,7 @@ impl FileTransferActivity {
format!("Created directory \"{}\"", remote_path.display()).as_ref(), format!("Created directory \"{}\"", remote_path.display()).as_ref(),
); );
// Get files in dir // Get files in dir
match self match self.host.scan_dir(dir.abs_path.as_path()) {
.context
.as_ref()
.unwrap()
.local
.scan_dir(dir.abs_path.as_path())
{
Ok(entries) => { Ok(entries) => {
// Iterate over files // Iterate over files
for entry in entries.iter() { for entry in entries.iter() {
@@ -322,9 +316,8 @@ impl FileTransferActivity {
err, err,
TransferErrorReason::Abrupted | TransferErrorReason::LocalIoError(_) TransferErrorReason::Abrupted | TransferErrorReason::LocalIoError(_)
) { ) {
let local = &mut self.context.as_mut().unwrap().local;
// Stat file // Stat file
match local.stat(local_file_path.as_path()) { match self.host.stat(local_file_path.as_path()) {
Err(err) => self.log( Err(err) => self.log(
LogLevel::Error, LogLevel::Error,
format!( format!(
@@ -335,7 +328,7 @@ impl FileTransferActivity {
.as_str(), .as_str(),
), ),
Ok(entry) => { Ok(entry) => {
if let Err(err) = local.remove(&entry) { if let Err(err) = self.host.remove(&entry) {
self.log( self.log(
LogLevel::Error, LogLevel::Error,
format!( format!(
@@ -359,24 +352,12 @@ impl FileTransferActivity {
None => local_dir_path.push(dir.name.as_str()), None => local_dir_path.push(dir.name.as_str()),
} }
// Create directory on local // Create directory on local
match self match self.host.mkdir_ex(local_dir_path.as_path(), true) {
.context
.as_mut()
.unwrap()
.local
.mkdir_ex(local_dir_path.as_path(), true)
{
Ok(_) => { Ok(_) => {
// Apply file mode to directory // Apply file mode to directory
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
if let Some(pex) = dir.unix_pex { if let Some(pex) = dir.unix_pex {
if let Err(err) = self if let Err(err) = self.host.chmod(local_dir_path.as_path(), pex) {
.context
.as_ref()
.unwrap()
.local
.chmod(local_dir_path.as_path(), pex)
{
self.log( self.log(
LogLevel::Error, LogLevel::Error,
format!( format!(
@@ -464,13 +445,7 @@ impl FileTransferActivity {
) -> Result<(), TransferErrorReason> { ) -> Result<(), TransferErrorReason> {
// Upload file // Upload file
// Try to open local file // Try to open local file
match self match self.host.open_file_read(local.abs_path.as_path()) {
.context
.as_ref()
.unwrap()
.local
.open_file_read(local.abs_path.as_path())
{
Ok(mut fhnd) => match self.client.send_file(local, remote) { Ok(mut fhnd) => match self.client.send_file(local, remote) {
Ok(mut rhnd) => { Ok(mut rhnd) => {
// Write file // Write file
@@ -580,7 +555,7 @@ impl FileTransferActivity {
file_name: String, file_name: String,
) -> Result<(), TransferErrorReason> { ) -> Result<(), TransferErrorReason> {
// Try to open local file // Try to open local file
match self.context.as_ref().unwrap().local.open_file_write(local) { match self.host.open_file_write(local) {
Ok(mut local_file) => { Ok(mut local_file) => {
// Download file from remote // Download file from remote
match self.client.recv_file(remote) { match self.client.recv_file(remote) {
@@ -657,8 +632,7 @@ impl FileTransferActivity {
// Apply file mode to file // Apply file mode to file
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
if let Some(pex) = remote.unix_pex { if let Some(pex) = remote.unix_pex {
if let Err(err) = self.context.as_ref().unwrap().local.chmod(local, pex) if let Err(err) = self.host.chmod(local, pex) {
{
self.log( self.log(
LogLevel::Error, LogLevel::Error,
format!( format!(
@@ -696,7 +670,7 @@ impl FileTransferActivity {
/// ///
/// Scan current local directory /// Scan current local directory
pub(super) fn local_scan(&mut self, path: &Path) { pub(super) fn local_scan(&mut self, path: &Path) {
match self.context.as_ref().unwrap().local.scan_dir(path) { match self.host.scan_dir(path) {
Ok(files) => { Ok(files) => {
// Set files and sort (sorting is implicit) // Set files and sort (sorting is implicit)
self.local.set_files(files); self.local.set_files(files);
@@ -735,7 +709,7 @@ impl FileTransferActivity {
// Get current directory // Get current directory
let prev_dir: PathBuf = self.local.wrkdir.clone(); let prev_dir: PathBuf = self.local.wrkdir.clone();
// Change directory // Change directory
match self.context.as_mut().unwrap().local.change_wrkdir(path) { match self.host.change_wrkdir(path) {
Ok(_) => { Ok(_) => {
self.log( self.log(
LogLevel::Info, LogLevel::Info,
@@ -858,8 +832,7 @@ impl FileTransferActivity {
return Err(format!("Could not open file {}: {}", file.name, err)); return Err(format!("Could not open file {}: {}", file.name, err));
} }
// Get current file modification time // Get current file modification time
let prev_mtime: SystemTime = match self.context.as_ref().unwrap().local.stat(tmpfile.path()) let prev_mtime: SystemTime = match self.host.stat(tmpfile.path()) {
{
Ok(e) => e.get_last_change_time(), Ok(e) => e.get_last_change_time(),
Err(err) => { Err(err) => {
return Err(format!( return Err(format!(
@@ -874,8 +847,7 @@ impl FileTransferActivity {
return Err(err); return Err(err);
} }
// Get local fs entry // Get local fs entry
let tmpfile_entry: FsEntry = match self.context.as_ref().unwrap().local.stat(tmpfile.path()) let tmpfile_entry: FsEntry = match self.host.stat(tmpfile.path()) {
{
Ok(e) => e, Ok(e) => e,
Err(err) => { Err(err) => {
return Err(format!( return Err(format!(
@@ -897,17 +869,16 @@ impl FileTransferActivity {
.as_ref(), .as_ref(),
); );
// Get local fs entry // Get local fs entry
let tmpfile_entry: FsEntry = let tmpfile_entry: FsEntry = match self.host.stat(tmpfile.path()) {
match self.context.as_ref().unwrap().local.stat(tmpfile.path()) { Ok(e) => e,
Ok(e) => e, Err(err) => {
Err(err) => { return Err(format!(
return Err(format!( "Could not stat \"{}\": {}",
"Could not stat \"{}\": {}", tmpfile.path().display(),
tmpfile.path().display(), err
err ))
)) }
} };
};
// Write file // Write file
let tmpfile_entry: &FsFile = match &tmpfile_entry { let tmpfile_entry: &FsFile = match &tmpfile_entry {
FsEntry::Directory(_) => panic!("tempfile is a directory for some reason"), FsEntry::Directory(_) => panic!("tempfile is a directory for some reason"),

View File

@@ -33,7 +33,6 @@ extern crate tuirealm;
use super::input::InputHandler; use super::input::InputHandler;
use super::store::Store; use super::store::Store;
use crate::filetransfer::FileTransferProtocol; use crate::filetransfer::FileTransferProtocol;
use crate::host::Localhost;
use crate::system::config_client::ConfigClient; use crate::system::config_client::ConfigClient;
// Includes // Includes
@@ -49,7 +48,6 @@ use tuirealm::tui::Terminal;
/// ///
/// Context holds data structures used by the ui /// Context holds data structures used by the ui
pub struct Context { pub struct Context {
pub local: Localhost,
pub ft_params: Option<FileTransferParams>, pub ft_params: Option<FileTransferParams>,
pub(crate) config_client: Option<ConfigClient>, pub(crate) config_client: Option<ConfigClient>,
pub(crate) store: Store, pub(crate) store: Store,
@@ -74,16 +72,11 @@ impl Context {
/// ### new /// ### new
/// ///
/// Instantiates a new Context /// Instantiates a new Context
pub fn new( pub fn new(config_client: Option<ConfigClient>, error: Option<String>) -> Context {
local: Localhost,
config_client: Option<ConfigClient>,
error: Option<String>,
) -> Context {
// Create terminal // Create terminal
let mut stdout = stdout(); let mut stdout = stdout();
assert!(execute!(stdout, EnterAlternateScreen).is_ok()); assert!(execute!(stdout, EnterAlternateScreen).is_ok());
Context { Context {
local,
ft_params: None, ft_params: None,
config_client, config_client,
store: Store::init(), store: Store::init(),
@@ -93,14 +86,12 @@ impl Context {
} }
} }
/* NOTE: in case is necessary
/// ### set_error /// ### set_error
/// ///
/// Set context error /// Set context error
pub fn set_error(&mut self, err: String) { pub fn set_error(&mut self, err: String) {
self.error = Some(err); self.error = Some(err);
} }
*/
/// ### get_error /// ### get_error
/// ///
@@ -165,7 +156,6 @@ mod tests {
use super::*; use super::*;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use std::path::PathBuf;
#[test] #[test]
fn test_ui_context_ft_params() { fn test_ui_context_ft_params() {
@@ -181,16 +171,15 @@ mod tests {
#[cfg(not(feature = "githubActions"))] #[cfg(not(feature = "githubActions"))]
fn test_ui_context() { fn test_ui_context() {
// Prepare stuff // Prepare stuff
let wrkdir: PathBuf = std::env::current_dir().unwrap_or(PathBuf::from("/")); let mut ctx: Context = Context::new(None, Some(String::from("alles kaput")));
let mut ctx: Context = Context::new(
Localhost::new(wrkdir).ok().unwrap(),
None,
Some(String::from("alles kaput")),
);
assert!(ctx.error.is_some()); assert!(ctx.error.is_some());
assert_eq!(ctx.get_error().unwrap().as_str(), "alles kaput"); assert_eq!(ctx.get_error().unwrap().as_str(), "alles kaput");
assert!(ctx.error.is_none()); assert!(ctx.error.is_none());
assert!(ctx.get_error().is_none()); assert!(ctx.get_error().is_none());
ctx.set_error(String::from("err"));
assert!(ctx.error.is_some());
assert!(ctx.get_error().is_some());
assert!(ctx.get_error().is_none());
// Try other methods // Try other methods
ctx.enter_alternate_screen(); ctx.enter_alternate_screen();
ctx.clear_screen(); ctx.clear_screen();