debug log belongs in cache directory not config directory (#179)

* log files are now written to cache dir instead of config dir

* lint

* fmt
This commit is contained in:
Christian Visintin
2023-05-09 15:32:42 +02:00
committed by GitHub
parent 9bf23b3f6b
commit 9009002b6e
26 changed files with 96 additions and 160 deletions

View File

@@ -482,9 +482,9 @@ Just a reminder: **you can edit only textual file**; binary files are not suppor
termscp writes a log file for each session, which is written at
- `$HOME/.config/termscp/termscp.log` on Linux/BSD
- `$HOME/Library/Application Support/termscp/termscp.log` on MacOs
- `FOLDERID_RoamingAppData\termscp\termscp.log` on Windows
- `$HOME/.cache/termscp/termscp.log` on Linux/BSD
- `$HOME/Library/Caches/termscp/termscp.log` on MacOs
- `FOLDERID_LocalAppData\termscp\termscp.log` on Windows
the log won't be rotated, but will just be truncated after each launch of termscp, so if you want to report an issue and you want to attach your log file, keep in mind to save the log file in a safe place before using termscp again.
The logging by default reports in *INFO* level, so it is not very verbose.

View File

@@ -481,9 +481,9 @@ En caso de que el archivo esté ubicado en un host remoto, el archivo se descarg
termscp escribe un archivo de registro para cada sesión, que se escribe en
- `$HOME/.config/termscp/termscp.log` en Linux/BSD
- `$HOME/Library/Application Support/termscp/termscp.log` en MacOs
- `FOLDERID_RoamingAppData\termscp\termscp.log` en Windows
- `$HOME/.cache/termscp/termscp.log` en Linux/BSD
- `$HOME/Library/Caches/termscp/termscp.log` en MacOs
- `FOLDERID_LocalAppData\termscp\termscp.log` en Windows
el registro no se rotará, sino que se truncará después de cada lanzamiento de termscp, por lo que si desea informar un problema y desea adjuntar su archivo de registro, recuerde guardar el archivo de registro en un lugar seguro antes de usar termscp de nuevo.
El registro por defecto informa en el nivel *INFO*, por lo que no es muy detallado.

View File

@@ -479,9 +479,9 @@ Si le fichier se trouve sur l'hôte distant, le fichier sera d'abord télécharg
termscp écrit un fichier journal pour chaque session, qui est écrit à
- `$HOME/.config/termscp/termscp.log` sous Linux/BSD
- `$HOME/Library/Application Support/termscp/termscp.log` sous MacOs
- `FOLDERID_RoamingAppData\termscp\termscp.log` sous Windows
- `$HOME/.cache/termscp/termscp.log` sous Linux/BSD
- `$HOME/Library/Caches/termscp/termscp.log` sous MacOs
- `FOLDERID_LocalAppData\termscp\termscp.log` sous Windows
le journal ne sera pas tourné, mais sera simplement tronqué après chaque lancement de termscp, donc si vous souhaitez signaler un problème et que vous souhaitez joindre votre fichier journal, n'oubliez pas de sauvegarder le fichier journal dans un endroit sûr avant de l'utiliser termescp à nouveau.

View File

@@ -478,9 +478,9 @@ Nel caso il file si trovi su host remoto, il file verrà prima scaricato tempora
termscp scrive un file di log per ogni sessione, nel percorso seguente:
- `$HOME/.config/termscp/termscp.log` su Linux/BSD
- `$HOME/Library/Application Support/termscp/termscp.log` su MacOs
- `FOLDERID_RoamingAppData\termscp\termscp.log` su Windows
- `$HOME/.cache/termscp/termscp.log` su Linux/BSD
- `$HOME/Library/Caches/termscp/termscp.log` su MacOs
- `FOLDERID_LocalAppData\termscp\termscp.log` su Windows
Il log non viene ruotato, ma viene troncato ad ogni lancio di termscp, quindi se devi riportare un issue, non avviare termscp fino a che non avrai salvato il file di log.
I log sono di default riportati a livello *INFO*, quindi non sono particolarmente parlanti.

View File

@@ -480,9 +480,9 @@ In case the file is located on remote host, the file will be first downloaded in
termscp writes a log file for each session, which is written at
- `$HOME/.config/termscp/termscp.log` on Linux/BSD
- `$HOME/Library/Application Support/termscp/termscp.log` on MacOs
- `FOLDERID_RoamingAppData\termscp\termscp.log` on Windows
- `$HOME/.cache/termscp/termscp.log` on Linux/BSD
- `$HOME/Library/Caches/termscp/termscp.log` on MacOs
- `FOLDERID_LocalAppData\termscp\termscp.log` on Windows
the log won't be rotated, but will just be truncated after each launch of termscp, so if you want to report an issue and you want to attach your log file, keep in mind to save the log file in a safe place before using termscp again.
The logging by default reports in *INFO* level, so it is not very verbose.

View File

@@ -472,9 +472,9 @@ Termscp有很多功能你可能已经注意到了其中之一就是可以
termscp会为每个会话创建一个日志文件该文件在
- `$HOME/.config/termscp/termscp.log` -- Linux/BSD
- `$HOME/Library/Application Support/termscp/termscp.log` -- MacOs
- `FOLDERID_RoamingAppData\termscp\termscp.log` -- Windows
- `$HOME/.cache/termscp/termscp.log` -- Linux/BSD
- `$HOME/Library/Caches/termscp/termscp.log` -- MacOs
- `FOLDERID_LocalAppData\termscp\termscp.log` -- Windows
日志不会被轮换,但只会在每次启动 termcp 后被截断,因此如果您想报告问题并希望附加您的日志文件,请记住在使用前将日志文件保存在安全的地方 再次termscp。
默认情况下,日志记录在 *INFO* 级别报告,因此它不是很详细。

View File

@@ -21,8 +21,6 @@ use crate::utils::tty;
use std::path::{Path, PathBuf};
use std::time::Duration;
/// ### NextActivity
///
/// NextActivity identifies the next identity to run once the current has ended
pub enum NextActivity {
Authentication,
@@ -30,8 +28,6 @@ pub enum NextActivity {
SetupActivity,
}
/// ### ActivityManager
///
/// The activity manager takes care of running activities and handling them until the application has ended
pub struct ActivityManager {
context: Option<Context>,

View File

@@ -49,8 +49,6 @@ impl std::fmt::Display for SerializerError {
}
}
/// ### serialize
///
/// Serialize `UserHosts` into TOML and write content to writable
pub fn serialize<S>(serializable: &S, mut writable: Box<dyn Write>) -> Result<(), SerializerError>
where
@@ -77,8 +75,6 @@ where
}
}
/// ### deserialize
///
/// Read data from readable and deserialize its content as TOML
pub fn deserialize<S>(mut readable: Box<dyn Read>) -> Result<S, SerializerError>
where

View File

@@ -9,8 +9,6 @@ use crate::utils::parser::parse_color;
use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer};
use tuirealm::tui::style::Color;
/// ### Theme
///
/// Theme contains all the colors lookup table for termscp
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct Theme {

View File

@@ -6,8 +6,6 @@ use super::FileTransferProtocol;
use std::path::{Path, PathBuf};
/// ### FileTransferParams
///
/// Holds connection parameters for file transfers
#[derive(Debug, Clone)]
pub struct FileTransferParams {

View File

@@ -41,8 +41,6 @@ pub enum HostErrorType {
DeleteFailed,
}
/// ### HostError
///
/// HostError is a wrapper for the error type and the exact io error
#[derive(Debug)]
pub struct HostError {

View File

@@ -136,8 +136,6 @@ fn parse_remote_address(remote: &str) -> Result<FileTransferParams, String> {
utils::parser::parse_remote_opt(remote).map_err(|e| format!("Bad address option: {e}"))
}
/// ### run
///
/// Run task and return rc
fn run(run_opts: RunOpts) -> i32 {
match run_opts.task {

View File

@@ -13,8 +13,6 @@ use crate::system::{
use std::fs;
use std::path::{Path, PathBuf};
/// ### import_theme
///
/// Import theme at provided path into termscp
pub fn import_theme(p: &Path) -> Result<(), String> {
if !p.exists() {
@@ -34,8 +32,6 @@ pub fn import_theme(p: &Path) -> Result<(), String> {
.map_err(|e| format!("Could not import theme: {e}"))
}
/// ### install_update
///
/// Install latest version of termscp if an update is available
pub fn install_update() -> Result<String, String> {
match Update::default()
@@ -65,8 +61,6 @@ pub fn install_update() -> Result<String, String> {
}
}
/// ### get_config_dir
///
/// Get configuration directory
fn get_config_dir() -> Result<PathBuf, String> {
match environment::init_config_dir() {
@@ -80,8 +74,6 @@ fn get_config_dir() -> Result<PathBuf, String> {
}
}
/// ### get_config_client
///
/// Get configuration client
fn get_config_client() -> Option<ConfigClient> {
match get_config_dir() {

View File

@@ -10,8 +10,6 @@ use self_update::{
Status,
};
/// ### UpdateStatus
///
/// The status of the update in case of success
#[derive(Debug, Eq, PartialEq)]
pub enum UpdateStatus {

View File

@@ -730,7 +730,7 @@ mod tests {
// Limit is 2
assert_eq!(client.iter_recents().count(), 2);
// Check that 192.168.1.1 has been removed
let key: String = client.iter_recents().nth(0).unwrap().to_string();
let key: String = client.iter_recents().next().unwrap().to_string();
assert!(matches!(
client
.hosts

View File

@@ -5,10 +5,8 @@
// Ext
use std::path::{Path, PathBuf};
/// ### get_config_dir
///
/// Get termscp configuration directory path.
/// Returns None, if it's not possible to get it
/// Get termscp config directory path and initialize it.
/// Returns None if it's not possible to initialize it
pub fn init_config_dir() -> Result<Option<PathBuf>, String> {
// Get file
#[cfg(not(test))]
@@ -19,27 +17,51 @@ pub fn init_config_dir() -> Result<Option<PathBuf>, String> {
lazy_static! {
static ref CONF_DIR: Option<PathBuf> = Some(std::env::temp_dir());
}
if CONF_DIR.is_some() {
// Get path of bookmarks
let mut p: PathBuf = CONF_DIR.as_ref().unwrap().clone();
// Append termscp dir
p.push("termscp/");
// If directory doesn't exist, create it
if p.exists() {
return Ok(Some(p));
}
// directory doesn't exist; create dir recursively
match std::fs::create_dir_all(p.as_path()) {
Ok(_) => Ok(Some(p)),
Err(err) => Err(err.to_string()),
}
if let Some(dir) = CONF_DIR.as_deref() {
init_dir(dir).map(Option::Some)
} else {
Ok(None)
}
}
/// ### get_bookmarks_paths
///
/// Get termscp cache directory path and initialize it.
/// Returns None if it's not possible to initialize it
pub fn init_cache_dir() -> Result<Option<PathBuf>, String> {
// Get file
#[cfg(not(test))]
lazy_static! {
static ref CACHE_DIR: Option<PathBuf> = dirs::cache_dir();
}
#[cfg(test)]
lazy_static! {
static ref CACHE_DIR: Option<PathBuf> = Some(std::env::temp_dir());
}
if let Some(dir) = CACHE_DIR.as_deref() {
init_dir(dir).map(Option::Some)
} else {
Ok(None)
}
}
/// Init a termscp env dir
fn init_dir(p: &Path) -> Result<PathBuf, String> {
// Get path of bookmarks
let mut p: PathBuf = p.to_path_buf();
// Append termscp dir
p.push("termscp/");
// If directory doesn't exist, create it
if p.exists() {
return Ok(p);
}
// directory doesn't exist; create dir recursively
match std::fs::create_dir_all(p.as_path()) {
Ok(_) => Ok(p),
Err(err) => Err(err.to_string()),
}
}
/// Get paths for bookmarks client
/// Returns: path of bookmarks.toml
pub fn get_bookmarks_paths(config_dir: &Path) -> PathBuf {
@@ -49,8 +71,6 @@ pub fn get_bookmarks_paths(config_dir: &Path) -> PathBuf {
bookmarks_file
}
/// ### get_config_paths
///
/// Returns paths for config client
/// Returns: path of config.toml and path for ssh keys
pub fn get_config_paths(config_dir: &Path) -> (PathBuf, PathBuf) {
@@ -62,17 +82,13 @@ pub fn get_config_paths(config_dir: &Path) -> (PathBuf, PathBuf) {
(bookmarks_file, keys_dir)
}
/// ### get_log_paths
///
/// Returns the path for the supposed log file
pub fn get_log_paths(config_dir: &Path) -> PathBuf {
let mut log_file: PathBuf = PathBuf::from(config_dir);
pub fn get_log_paths(cache_dir: &Path) -> PathBuf {
let mut log_file: PathBuf = PathBuf::from(cache_dir);
log_file.push("termscp.log");
log_file
}
/// ### get_theme_path
///
/// Get paths for theme provider
/// Returns: path of theme.toml
pub fn get_theme_path(config_dir: &Path) -> PathBuf {
@@ -101,6 +117,15 @@ mod tests {
assert!(std::fs::remove_dir_all(conf_dir.as_path()).is_ok());
}
#[test]
#[serial]
fn should_get_cache_dir() {
// Create and get cache_dir
let cache_dir: PathBuf = init_cache_dir().ok().unwrap().unwrap();
// Remove dir
assert!(std::fs::remove_dir_all(cache_dir.as_path()).is_ok());
}
#[test]
#[serial]
fn test_system_environment_get_config_dir_err() {
@@ -148,8 +173,8 @@ mod tests {
#[serial]
fn test_system_environment_get_log_paths() {
assert_eq!(
get_log_paths(Path::new("/home/omar/.config/termscp/")),
PathBuf::from("/home/omar/.config/termscp/termscp.log"),
get_log_paths(Path::new("/home/omar/.cache/termscp/")),
PathBuf::from("/home/omar/.cache/termscp/termscp.log"),
);
}

View File

@@ -2,32 +2,26 @@
//!
//! `logging` is the module which initializes the logging system for termscp
// locals
use crate::system::environment::{get_log_paths, init_config_dir};
use super::environment::{get_log_paths, init_cache_dir};
use crate::utils::file::open_file;
// ext
pub use simplelog::LevelFilter as LogLevel;
use simplelog::{ConfigBuilder, WriteLogger};
use std::fs::File;
use std::path::PathBuf;
/// ### init
///
/// Initialize logger
pub fn init(level: LogLevel) -> Result<(), String> {
// Init config dir
let config_dir: PathBuf = match init_config_dir() {
// Init cache dir
let cache_dir = match init_cache_dir() {
Ok(Some(p)) => p,
Ok(None) => {
return Err(String::from(
"This system doesn't seem to support CONFIG_DIR",
"This system doesn't seem to support CACHE_DIR",
))
}
Err(err) => return Err(err),
};
let log_file_path: PathBuf = get_log_paths(config_dir.as_path());
let log_file_path = get_log_paths(cache_dir.as_path());
// Open log file
let file: File = open_file(log_file_path.as_path(), true, true, false)
let file = open_file(log_file_path.as_path(), true, true, false)
.map_err(|e| format!("Failed to open file {}: {}", log_file_path.display(), e))?;
// Prepare log config
let config = ConfigBuilder::new().set_time_format_rfc3339().build();

View File

@@ -147,8 +147,6 @@ enum InputMask {
const STORE_KEY_LATEST_VERSION: &str = "AUTH_LATEST_VERSION";
const STORE_KEY_RELEASE_NOTES: &str = "AUTH_RELEASE_NOTES";
/// ### AuthActivity
///
/// AuthActivity is the data holder for the authentication activity
pub struct AuthActivity {
app: Application<Id, Msg, NoUserEvent>,

View File

@@ -8,8 +8,6 @@ use std::time::Instant;
// -- States and progress
/// ### TransferStates
///
/// TransferStates contains the states related to the transfer process
pub struct TransferStates {
aborted: bool, // Describes whether the transfer process has been aborted
@@ -17,8 +15,6 @@ pub struct TransferStates {
pub partial: ProgressStates, // Partial transfer states
}
/// ### ProgressStates
///
/// Progress states describes the states for the progress of a single transfer part
pub struct ProgressStates {
started: Instant,

View File

@@ -227,8 +227,6 @@ pub enum ThemeMsg {
// -- store
const STORE_CONFIG_CHANGED: &str = "SETUP_CONFIG_CHANGED";
/// ### ViewLayout
///
/// Current view layout
#[derive(PartialEq, Eq)]
pub enum ViewLayout {

View File

@@ -5,16 +5,12 @@
// Ext
use magic_crypt::MagicCryptTrait;
/// ### aes128_b64_crypt
///
/// Crypt a string using AES128; output is returned as a BASE64 string
pub fn aes128_b64_crypt(key: &str, input: &str) -> String {
let crypter = new_magic_crypt!(key, 128);
crypter.encrypt_str_to_base64(input)
}
/// ### aes128_b64_decrypt
///
/// Decrypt a string using AES128
pub fn aes128_b64_decrypt(key: &str, secret: &str) -> Result<String, magic_crypt::MagicCryptError> {
let crypter = new_magic_crypt!(key, 128);

View File

@@ -7,8 +7,6 @@ use std::fs::OpenOptions;
use std::io;
use std::path::Path;
/// ### open_file
///
/// Open file provided as parameter
pub fn open_file<P>(filename: P, create: bool, write: bool, append: bool) -> io::Result<File>
where

View File

@@ -10,8 +10,6 @@ use std::time::{Duration, SystemTime};
use tuirealm::tui::style::Color;
use unicode_width::UnicodeWidthStr;
/// ### fmt_pex
///
/// Convert permissions bytes of permissions value into ls notation (e.g. rwx,-wx,--x)
pub fn fmt_pex(pex: UnixPexClass) -> String {
format!(
@@ -31,16 +29,12 @@ pub fn fmt_pex(pex: UnixPexClass) -> String {
)
}
/// ### instant_to_str
///
/// Format a `Instant` into a time string
pub fn fmt_time(time: SystemTime, fmt: &str) -> String {
let datetime: DateTime<Local> = time.into();
format!("{}", datetime.format(fmt))
}
/// ### fmt_millis
///
/// Format duration as {secs}.{millis}
pub fn fmt_millis(duration: Duration) -> String {
let seconds: u128 = duration.as_millis() / 1000;
@@ -48,16 +42,12 @@ pub fn fmt_millis(duration: Duration) -> String {
format!("{}.{:0width$}", seconds, millis, width = 3)
}
/// ### elide_path
///
/// Elide a path if longer than width
/// In this case, the path is formatted to {ANCESTOR[0]}/…/{PARENT[0]}/{BASENAME}
pub fn fmt_path_elide(p: &Path, width: usize) -> String {
fmt_path_elide_ex(p, width, 0)
}
/// ### fmt_path_elide_ex
///
/// Elide a path if longer than width
/// In this case, the path is formatted to {ANCESTOR[0]}/…/{PARENT[0]}/{BASENAME}
/// This function allows to specify an extra length to consider to elide path
@@ -90,8 +80,6 @@ pub fn fmt_path_elide_ex(p: &Path, width: usize, extra_len: usize) -> String {
}
}
/// ### fmt_color
///
/// Format color
pub fn fmt_color(color: &Color) -> String {
match color {
@@ -258,15 +246,11 @@ pub fn fmt_color(color: &Color) -> String {
}
}
/// ### shadow_password
///
/// Return a string with the same length of input string, but each character is replaced by '*'
pub fn shadow_password(s: &str) -> String {
(0..s.len()).map(|_| '*').collect()
}
/// ### fmt_bytes
///
/// Format bytes
pub fn fmt_bytes(v: u64) -> String {
if v >= 1125899906842624 {

View File

@@ -68,8 +68,6 @@ static BYTESIZE_REGEX: Lazy<Regex> = lazy_regex!(r"(:?([0-9])+)( )*(:?[KMGTP])?B
// -- remote opts
/// ### parse_remote_opt
///
/// Parse remote option string. Returns in case of success a RemoteOptions struct
/// For ssh if username is not provided, current user will be used.
/// In case of error, message is returned
@@ -115,8 +113,6 @@ pub fn parse_remote_opt(s: &str) -> Result<FileTransferParams, String> {
}
}
/// ### parse_remote_opt_protocol
///
/// Parse protocol from CLI option. In case of success, return the protocol to be used and the remaining arguments
fn parse_remote_opt_protocol(
s: &str,
@@ -147,8 +143,6 @@ fn parse_remote_opt_protocol(
}
}
/// ### parse_generic_remote_opt
///
/// Parse generic remote options
fn parse_generic_remote_opt(
s: &str,
@@ -202,8 +196,6 @@ fn parse_generic_remote_opt(
}
}
/// ### parse_s3_remote_opt
///
/// Parse remote options for s3 protocol
fn parse_s3_remote_opt(s: &str) -> Result<FileTransferParams, String> {
match REMOTE_S3_OPT_REGEX.captures(s) {
@@ -229,8 +221,6 @@ fn parse_s3_remote_opt(s: &str) -> Result<FileTransferParams, String> {
}
}
/// ### parse_semver
///
/// Parse semver string
pub fn parse_semver(haystack: &str) -> Option<String> {
match SEMVER_REGEX.captures(haystack) {
@@ -239,8 +229,6 @@ pub fn parse_semver(haystack: &str) -> Option<String> {
}
}
/// ### parse_color
///
/// Parse color from string into a `Color` enum.
///
/// Color may be in different format:
@@ -300,8 +288,6 @@ impl FromStr for ByteUnit {
}
}
/// ### parse_bytesize
///
/// Parse bytes repr (e.g. `24 MB`) into `ByteSize`
pub fn parse_bytesize<S: AsRef<str>>(bytes: S) -> Option<ByteSize> {
match BYTESIZE_REGEX.captures(bytes.as_ref()) {

View File

@@ -4,8 +4,6 @@
use std::path::{Component, Path, PathBuf};
/// ### absolutize
///
/// Absolutize target path if relative.
/// For example:
///
@@ -24,8 +22,6 @@ pub fn absolutize(wrkdir: &Path, target: &Path) -> PathBuf {
}
}
/// ### diff_paths
///
/// This function will get the difference from path `path` to `base`. Basically will remove `base` from `path`
///
/// For example:
@@ -127,24 +123,21 @@ mod test {
#[test]
fn should_tell_whether_path_is_child_of() {
assert_eq!(
is_child_of(Path::new("/home/foo/foo.txt"), Path::new("/home"),),
true
);
assert_eq!(
is_child_of(Path::new("/home/foo/foo.txt"), Path::new("/home/foo/"),),
true
);
assert_eq!(
is_child_of(
Path::new("/home/foo/foo.txt"),
Path::new("/home/foo/foo.txt"),
),
true
);
assert_eq!(
is_child_of(Path::new("/home/foo/foo.txt"), Path::new("/tmp"),),
false
);
assert!(is_child_of(
Path::new("/home/foo/foo.txt"),
Path::new("/home"),
));
assert!(is_child_of(
Path::new("/home/foo/foo.txt"),
Path::new("/home/foo/"),
));
assert!(is_child_of(
Path::new("/home/foo/foo.txt"),
Path::new("/home/foo/foo.txt"),
));
assert!(!is_child_of(
Path::new("/home/foo/foo.txt"),
Path::new("/tmp"),
));
}
}

View File

@@ -33,8 +33,6 @@ pub fn create_sample_file_with_content(content: impl std::fmt::Display) -> Named
tmpfile
}
/// ### make_file_at
///
/// Make a file with `name` at specified path
pub fn make_file_at(dir: &Path, filename: &str) -> std::io::Result<PathBuf> {
let mut p: PathBuf = PathBuf::from(dir);
@@ -47,8 +45,6 @@ pub fn make_file_at(dir: &Path, filename: &str) -> std::io::Result<PathBuf> {
Ok(p)
}
/// ### make_dir_at
///
/// Make a directory in `dir`
pub fn make_dir_at(dir: &Path, dirname: &str) -> std::io::Result<()> {
let mut p: PathBuf = PathBuf::from(dir);
@@ -69,8 +65,6 @@ pub fn make_fsentry<P: AsRef<Path>>(path: P, is_dir: bool) -> File {
}
}
/// ### create_file_ioers
///
/// Open a file with two handlers, the first is to read, the second is to write
pub fn create_file_ioers(p: &Path) -> (StdFile, StdFile) {
(