From b88e5e4206aa10eb4ead6e768ab9b58d26c91262 Mon Sep 17 00:00:00 2001 From: Rasmus Rosengren Date: Fri, 12 Nov 2021 19:10:22 +0100 Subject: [PATCH] completion generation, anyhow, and bug fixes --- Cargo.lock | 17 +++++++++++++++++ Cargo.toml | 2 ++ src/build.rs | 2 +- src/diff.rs | 2 +- src/install.rs | 19 +++++++++++-------- src/main.rs | 15 +++++++++++++-- src/opts.rs | 19 +++++++++++++++++-- src/utils.rs | 9 +++------ 8 files changed, 65 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e16da90..ac4f78b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anyhow" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7" + [[package]] name = "async-recursion" version = "0.3.2" @@ -79,12 +85,23 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_generate" +version = "3.0.0-beta.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "097ab5db1c3417442270cd57c8dd39f6c3114d3ce09d595f9efddbb1fcfaa799" +dependencies = [ + "clap", +] + [[package]] name = "dfm" version = "0.1.0" dependencies = [ + "anyhow", "async-recursion", "clap", + "clap_generate", "directories", "futures", "terminal_size", diff --git a/Cargo.toml b/Cargo.toml index 98fa364..9eac8ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1.0" async-recursion = "0.3" clap = "3.0.0-beta.5" +clap_generate = "3.0.0-beta.5" directories = "4.0" futures = "0.3" terminal_size = "0.1" diff --git a/src/build.rs b/src/build.rs index 39ed799..f3d4ca8 100644 --- a/src/build.rs +++ b/src/build.rs @@ -3,7 +3,7 @@ use crate::{ utils::{get_tree_files, remove_dir_if_empty}, }; -pub async fn build(config: &Config) -> std::io::Result<()> { +pub async fn build(config: &Config) -> anyhow::Result<()> { let source_files = get_tree_files(config, &config.source_dir).await?; let build_files = get_tree_files(config, &config.build_dir).await?; diff --git a/src/diff.rs b/src/diff.rs index 97a34d3..7bdd6c4 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -4,7 +4,7 @@ use terminal_size::{terminal_size, Width}; use crate::{config::Config, utils::get_tree_files}; -pub async fn diff(config: &Config, diff_command: String) -> std::io::Result<()> { +pub async fn diff(config: &Config, diff_command: String) -> anyhow::Result<()> { let built_files = get_tree_files(config, &config.build_dir).await?; let installed_files = get_tree_files(config, &config.install_dir).await?; diff --git a/src/install.rs b/src/install.rs index 2672227..cf35cfa 100644 --- a/src/install.rs +++ b/src/install.rs @@ -3,7 +3,7 @@ use crate::{ utils::{get_tree_files, remove_dir_if_empty}, }; -pub async fn install(config: &Config) -> std::io::Result<()> { +pub async fn install(config: &Config) -> anyhow::Result<()> { let built_files = get_tree_files(config, &config.build_dir).await?; let installed_files = get_tree_files(config, &config.install_dir).await?; @@ -13,8 +13,8 @@ pub async fn install(config: &Config) -> std::io::Result<()> { tokio::fs::create_dir_all(dir).await?; } - let from = config.source_dir.join(file_path); - let to = config.build_dir.join(file_path); + let from = config.build_dir.join(file_path); + let to = config.install_dir.join(file_path); tokio::fs::copy(from, to).await?; if let Some(folder_path) = file_path.parent() { @@ -22,11 +22,14 @@ pub async fn install(config: &Config) -> std::io::Result<()> { tokio::fs::create_dir_all(dir).await?; } - tokio::fs::symlink( - config.install_dir.join(&file_path), - config.link_dir.join(&file_path), - ) - .await?; + // Make sure symlink doesn't exist before attempting to symlink + let link_target = config.link_dir.join(&file_path); + match tokio::fs::remove_file(&link_target).await { + Ok(_) => {} + Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} + Err(e) => anyhow::bail!(e), + }; + tokio::fs::symlink(config.install_dir.join(&file_path), link_target).await?; } for file_path in installed_files { diff --git a/src/main.rs b/src/main.rs index 3afd855..538b187 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,8 @@ mod utils; use std::path::PathBuf; -use clap::Parser; +use clap::{IntoApp, Parser}; +use clap_generate::generate; use directories::{ProjectDirs, UserDirs}; use crate::{ @@ -16,9 +17,19 @@ use crate::{ }; #[tokio::main] -async fn main() -> std::io::Result<()> { +async fn main() -> anyhow::Result<()> { let opts = Opts::parse(); + if let Some(generator) = opts.generate { + generate( + generator, + &mut Opts::into_app(), + "dfm", + &mut std::io::stdout(), + ); + return Ok(()); + } + let user_dirs = UserDirs::new().expect("Could not find user directories"); let project_dirs = ProjectDirs::from("se", "rsrp", "dfm").expect("Could not find project directories"); diff --git a/src/opts.rs b/src/opts.rs index 78dd3b2..ae273b5 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -1,11 +1,13 @@ use std::path::PathBuf; use clap::Parser; +use clap_generate::Shell; use crate::utils::APP_VERSION; #[derive(Debug, Parser)] #[clap( + name = "dfm", version = APP_VERSION, author = "Rasmus Rosengren ", about = "Utility to manage dotfiles" @@ -14,9 +16,22 @@ pub struct Opts { #[clap(short, long)] pub install: bool, - #[clap(short, long, default_value = ".df")] + #[clap( + short, + long, + default_value = ".df", + about = "Absolute path or relative path to $HOME" + )] pub repo_path: PathBuf, - #[clap(short, long, default_value = "delta")] + #[clap( + short, + long, + default_value = "delta", + about = "Command to execute to show diffs" + )] pub diff_command: String, + + #[clap(long, value_name = "SHELL", about = "Generate shell completions")] + pub generate: Option, } diff --git a/src/utils.rs b/src/utils.rs index 3792c56..170538d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,10 +10,7 @@ use crate::config::Config; pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub async fn get_tree_files( - config: &Config, - tree_root: &Path, -) -> std::io::Result> { +pub async fn get_tree_files(config: &Config, tree_root: &Path) -> anyhow::Result> { get_tree_files_recursively(config, tree_root, PathBuf::new()).await } @@ -22,7 +19,7 @@ async fn get_tree_files_recursively( config: &Config, tree_root: &Path, relative_path: PathBuf, -) -> std::io::Result> { +) -> anyhow::Result> { let current_path = tree_root.join(&relative_path); let mut dir_walker = read_dir(¤t_path).await?; @@ -57,7 +54,7 @@ async fn get_tree_files_recursively( Ok(files) } -pub async fn remove_dir_if_empty(path: &Path) -> std::io::Result<()> { +pub async fn remove_dir_if_empty(path: &Path) -> anyhow::Result<()> { let mut dir_walker = tokio::fs::read_dir(path).await?; if dir_walker.next_entry().await?.is_none() {