From d42f7d328c53e010cf28153a25168368b8b0376c Mon Sep 17 00:00:00 2001 From: rabite Date: Fri, 2 Aug 2019 15:51:47 +0200 Subject: config updater (auto and manual) --- src/config_installer.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++----- src/file_browser.rs | 8 ----- src/main.rs | 31 +++++++++++++++---- 3 files changed, 98 insertions(+), 21 deletions(-) diff --git a/src/config_installer.rs b/src/config_installer.rs index 5ca9282..4a2ca76 100644 --- a/src/config_installer.rs +++ b/src/config_installer.rs @@ -4,7 +4,7 @@ use std::process::Command; use std::ffi::OsStr; use std::path::Path; -use crate::fail::{HError, HResult}; +use crate::fail::{HError, HResult, ErrorLog}; use crate::widget::WidgetCore; @@ -77,16 +77,18 @@ fn install_config_all() -> HResult<()> { Ok(()) } -fn move_dir(from: &str, to: &Path) -> HResult<()> { - let success = Command::new("mv") +fn copy(from: &Path, to: &Path) -> HResult<()> { + // Uses -a flag to preserve symlinks + let success = Command::new("cp") + .arg("-a") .arg(from) .arg(to.as_os_str()) .status() .map(|s| s.success()); if success.is_err() || !success.unwrap() { - HError::log(&format!("Couldn't move {} to {} !", - from, + HError::log(&format!("Couldn't copy {} to {} !", + from.to_string_lossy(), to.to_string_lossy())) } else { Ok(()) @@ -97,7 +99,7 @@ fn install_config_previewers() -> HResult<()> { let hunter_dir = crate::paths::hunter_path()?; let archive_path = create_archive()?; extract_archive(Path::new("/tmp"), &archive_path)?; - move_dir("/tmp/hunter/previewers", &hunter_dir)?; + copy(Path::new("/tmp/hunter/previewers"), &hunter_dir)?; delete_archive(&archive_path) } @@ -105,10 +107,74 @@ fn install_config_actions() -> HResult<()> { let hunter_dir = crate::paths::hunter_path()?; let archive_path = create_archive()?; extract_archive(Path::new("/tmp"), &archive_path)?; - move_dir("/tmp/hunter/actions", &hunter_dir)?; + copy(Path::new("/tmp/hunter/actions"), &hunter_dir)?; delete_archive(&archive_path) } +fn update_previewer() -> HResult<()> { + let previewer_dir = crate::paths::previewers_path()?; + let archive_path = create_archive()?; + + extract_archive(Path::new("/tmp"), &archive_path)?; + + update_dir(Path::new("/tmp/hunter/previewers"), &previewer_dir).log(); + + delete_archive(&archive_path)?; + + Ok(()) +} + +fn update_actions() -> HResult<()> { + let actions_dir = crate::paths::actions_path()?; + let archive_path = create_archive()?; + + extract_archive(Path::new("/tmp"), &archive_path)?; + + update_dir(Path::new("/tmp/hunter/actions"), &actions_dir).log(); + + delete_archive(&archive_path)?; + + Ok(()) +} + +pub fn update_config(core: WidgetCore, force: bool) -> HResult<()> { + // First install whatever might be missing, makes sure all dirs are there + ensure_config(core).log(); + + // Just overwrite everything except core config/keys with the latest version + if force { + install_config_previewers().log(); + install_config_actions().log(); + return Ok(()) + } + + let archive_path = create_archive()?; + extract_archive(Path::new("/tmp"), &archive_path)?; + Ok(()) +} + +fn update_dir>(source: P, target: P) -> HResult<()> { + for file in std::fs::read_dir(source)? { + let file_path = file?.path(); + let file_name = file_path.file_name()?; + let target_path = target.as_ref().join(file_name); + + if file_path.is_dir() { + // Check subdirectories recursively + update_dir(&file_path, &target_path).log(); + } else { + if !target_path.exists() { + HError::log::<()>(&format!("Installing additional config file: {}", + file_path.to_string_lossy())).ok(); + copy(&file_path, &target_path).log(); + } + } + } + + Ok(()) +} + + fn create_archive() -> HResult<&'static str> { let archive_path = "/tmp/hunter-config.tar.gz"; let def_config = default_config_archive(); diff --git a/src/file_browser.rs b/src/file_browser.rs index 73e8e1f..1a57c8a 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -87,14 +87,6 @@ pub struct FileBrowser { } impl Tabbable for TabView { - fn on_new(&mut self) -> HResult<()> { - let core = self.core.clone(); - std::thread::spawn(move || { - crate::config_installer::ensure_config(core).log(); - }); - Ok(()) - } - fn new_tab(&mut self) -> HResult<()> { let cur_tab = self.active_tab_(); diff --git a/src/main.rs b/src/main.rs index a89fe4c..1304c49 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,7 +72,7 @@ mod keybind; use widget::{Widget, WidgetCore}; use term::ScreenExt; -use fail::{HResult, HError, MimeError}; +use fail::{HResult, HError, MimeError, ErrorLog}; use file_browser::FileBrowser; use tabview::TabView; use trait_ext::PathBufMime; @@ -97,10 +97,10 @@ fn main() -> HResult<()> { // do this early so it might be ready when needed crate::files::load_tags().ok(); - parse_args().ok(); - let mut core = WidgetCore::new().expect("Can't create WidgetCore!"); + parse_args(core.clone()).log(); + // Resets terminal when hunter crashes :( die_gracefully(&core); @@ -117,6 +117,13 @@ fn main() -> HResult<()> { fn run(mut core: WidgetCore) -> HResult<()> { core.screen.clear()?; + let core2 = core.clone(); + + // I hate waiting!!! + std::thread::spawn(move || { + crate::config_installer::ensure_config(core2).log(); + }); + let filebrowser = FileBrowser::new(&core, None)?; let mut tabview = TabView::new(&core); tabview.push_widget(filebrowser)?; @@ -130,11 +137,17 @@ fn run(mut core: WidgetCore) -> HResult<()> { } -fn parse_args() -> HResult<()> { +fn parse_args(core: WidgetCore) -> HResult<()> { let args = App::new("Lag-free terminal file browser") .version(clap::crate_version!()) .author(clap::crate_authors!("\n")) .about("Hunt your files at light-speed, armed with full $SHELL integration") + .arg( + Arg::with_name("update") + .short("u") + .long("update-conf") + .help("Update configuration (WARNING: Overwrites modified previewers/actions with default names! Main config/keys are safe!)") + .takes_value(false)) .arg( Arg::with_name("animation-off") .short("a") @@ -185,11 +198,17 @@ fn parse_args() -> HResult<()> { std::process::exit(1) } + if args.is_present("update") { + crate::config_installer::update_config(core, true).log(); + } + if let Some(path) = path { - std::env::set_current_dir(&path).ok(); + std::env::set_current_dir(&path) + .map_err(HError::from) + .log(); } - crate::config::set_argv_config(args).ok(); + crate::config::set_argv_config(args).log(); Ok(()) } -- cgit v1.2.3