mod config;
mod connection;
mod storage;
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
pub mod atsh {
use std::io::{Error, ErrorKind};
use std::path::Path;
use tracing::debug;
use crate::connection::Remotes;
use crate::storage::log::setup_logging;
pub use crate::config::CONFIG;
pub use crate::connection::Remote;
pub use crate::Result;
pub fn initialize(work_dir: Option<impl AsRef<Path>>) -> Result<()> {
if let Some(p) = work_dir {
CONFIG.set_work_dir(p)?;
}
let w = CONFIG.get_work_dir();
setup_logging(w)?;
debug!("success initialize at {:?}", w);
Ok(())
}
pub fn add(
user: &str,
password: &str,
ip: &str,
port: u16,
name: &Option<impl AsRef<str>>,
note: &Option<impl AsRef<str>>,
) -> Result<usize> {
Remotes::add(user, password, ip, port, name, note)
}
pub fn add_remote(remote: &Remote) -> Result<usize> {
add(
&remote.user,
&remote.password,
&remote.ip,
remote.port,
&remote.name,
&remote.note,
)
}
pub async fn remove(index: &Vec<usize>) -> Result<usize> {
Remotes::delete(index).await
}
pub fn get(index: usize) -> Result<Option<Remote>> {
Remotes::get(index)
}
pub fn try_get(index: usize) -> Result<Remote> {
Remotes::try_get(index)
}
pub fn get_all() -> Result<Vec<Remote>> {
let remotes = Remotes::get_all()?;
Ok(remotes.0)
}
pub fn pprint(all: bool) -> Result<()> {
let remotes = Remotes::get_all()?;
remotes.pprint(all);
Ok(())
}
pub async fn login(index: usize, auth: bool) -> Result<()> {
let remote = Remotes::try_get(index)?;
remote.login(auth).await
}
pub async fn upload(index: usize, path: &Vec<impl AsRef<str>>) -> Result<()> {
(path.len() == 2).then_some(()).ok_or_else(|| {
Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"path format error, like `upload -p /local/path /remote/path`",
))
})?;
let (local, remote) = (path[0].as_ref(), path[1].as_ref());
Path::new(local).exists().then_some(()).ok_or_else(|| {
Box::new(Error::new(ErrorKind::NotFound, "the upload file not found"))
})?;
Remotes::try_get(index)?.upload(local, remote).await
}
pub async fn download(index: usize, path: &Vec<impl AsRef<str>>) -> Result<()> {
(path.len() == 2).then_some(()).ok_or_else(|| {
Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"path format error, like `download -p /remote/path /local/path`",
))
})?;
let (remote, local) = (path[0].as_ref(), path[1].as_ref());
Remotes::try_get(index)?.download(remote, local).await
}
}