improved command interface

This commit is contained in:
Joshua Perry 2024-01-01 14:59:32 +00:00
parent 18594ceade
commit b90697486d
9 changed files with 120 additions and 27 deletions

60
Cargo.lock generated
View File

@ -96,6 +96,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "copy_dir"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "543d1dd138ef086e2ff05e3a48cf9da045da2033d16f8538fd76b86cd49b2ca3"
dependencies = [
"walkdir",
]
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.4.1"
@ -131,6 +140,7 @@ name = "rusty-dotfiles"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"copy_dir",
"serde_json", "serde_json",
] ]
@ -140,6 +150,15 @@ version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.193" version = "1.0.193"
@ -200,6 +219,47 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "walkdir"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"

View File

@ -8,8 +8,9 @@ publish = ["gitea"]
[dependencies] [dependencies]
clap = { version = "4.4.12", features = ["derive"] } clap = { version = "4.4.12", features = ["derive"] }
copy_dir = "0.1.3"
serde_json = "1.0.108" serde_json = "1.0.108"
[[bin]] [[bin]]
name = "dotfiles-collect" name = "dotfiles"
path = "src/bin/collect.rs" path = "src/bin/main.rs"

View File

@ -51,8 +51,7 @@
{"systemd": [ {"systemd": [
{"user": ["spotifyd.service"]} {"user": ["spotifyd.service"]}
]}, ]},
"nvim", "nvim"
{".vpn": ["templates"]}
]} ]}
]} ]}
]} ]}

View File

@ -1,3 +0,0 @@
fn main() {
rusty_dotfiles::collect::run();
}

10
src/bin/main.rs Normal file
View File

@ -0,0 +1,10 @@
fn main() {
use clap::Parser;
use rusty_dotfiles::config;
let args = config::Args::parse();
match args.cmd {
config::Commands::Collect => rusty_dotfiles::collect::run(&args),
config::Commands::Install{ .. } => rusty_dotfiles::install::run(&args),
};
}

View File

@ -1,8 +1,7 @@
pub fn run() { use crate::config;
use clap::Parser; ///TODO: Docs
pub fn run(args: &config::Args) {
let args = super::Args::parse(); let mut config = config::Config::new(args);
let mut config = super::Config::new(args);
config.run(); config.run();
@ -11,13 +10,13 @@ pub fn run() {
destination.push_str(path.as_str()); destination.push_str(path.as_str());
match path.chars().last() { match path.chars().last() {
Some('/') => create_dir(&config.destination_path), Some('/') => create_dir(&destination),
Some(_) => copy_file(path.as_str(), &destination), Some(_) => copy_file(path.as_str(), &destination),
None => super::errors::empty_path_error(), None => super::errors::empty_path_error(),
} }
}); });
} }
///TODO: Docs
fn create_dir(destination: &str) { fn create_dir(destination: &str) {
use std::fs; use std::fs;
@ -26,11 +25,9 @@ fn create_dir(destination: &str) {
Err(_) => super::errors::create_dir_error(&destination), Err(_) => super::errors::create_dir_error(&destination),
} }
} }
///TODO: Docs
fn copy_file(path: &str, destination: &str) { fn copy_file(path: &str, destination: &str) {
use std::fs; match copy_dir::copy_dir(path, &destination) {
match fs::copy(path, &destination) {
Ok(_) => (), Ok(_) => (),
Err(_) => super::errors::copy_file_error(path), Err(_) => super::errors::copy_file_error(path),
} }

View File

@ -1,5 +1,6 @@
use clap::Parser; use crate::errors;
/// Defines the arguments passed to the program. use clap::{Parser, Subcommand};
/// CLI utility to help with managing user dotfiles.
/// ///
/// # Examples /// # Examples
/// ///
@ -13,14 +14,31 @@ use clap::Parser;
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
pub struct Args { pub struct Args {
/// The file path to the config file /// The file path to the config file
#[arg(short, long, default_value = "config.json")] #[arg(short, long = "config", default_value = "config.json")]
pub config_file_path: String, pub config_file_path: String,
/// The path to the directory to do work in /// The path to the directory to do work in
#[arg(short, long, default_value = "~/dotfiles")] #[arg(short, long = "destination", default_value = "~/dotfiles")]
pub destination_dir_path: String, pub destination_dir_path: String,
/// Whether to treat the user's home folder as their username or "$USER" /// Whether to treat the user's home folder as their username or "$USER"
#[arg(short, long, default_value_t = false)] #[arg(short, long, default_value_t = false)]
pub use_username: bool, pub use_username: bool,
/// The command to be ran
#[command(subcommand)]
pub cmd: Commands,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
/// Collect files into a destination file
Collect,
/// Installs dotfiles from a git url.
///
/// The repo either needs to have:
/// 1)a config contained in the root directory
/// 2)a config written to match the file structure of the repo
Install {
#[arg(required = true)]
url: String,
},
} }
/// The root of a Linux System /// The root of a Linux System
const ROOT: &str = "/"; const ROOT: &str = "/";
@ -42,7 +60,7 @@ impl Config {
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `config_file_path` - The file path to the config file /// * `args` - The arguments parsed from the command called
/// ///
/// # Examples /// # Examples
/// ///
@ -50,7 +68,7 @@ impl Config {
/// let config = Config::new("config.json"); /// let config = Config::new("config.json");
/// assert_eq!(ROOT, config.root); /// assert_eq!(ROOT, config.root);
/// ``` /// ```
pub fn new(args: Args) -> Self { pub fn new(args: &Args) -> Self {
let root = "/"; let root = "/";
let paths = vec![root.to_string()]; let paths = vec![root.to_string()];
let config = parse_config(&args.config_file_path); let config = parse_config(&args.config_file_path);
@ -60,7 +78,7 @@ impl Config {
config, config,
root: root.to_string(), root: root.to_string(),
use_username: args.use_username, use_username: args.use_username,
destination_path: args.destination_dir_path, destination_path: args.destination_dir_path.to_string(),
} }
} }
/// Initializes the Config instance /// Initializes the Config instance
@ -83,6 +101,7 @@ impl Config {
/// # Arguments /// # Arguments
/// ///
/// * `json_file_tree` - The file_tree of paths to generate as a JSON Object /// * `json_file_tree` - The file_tree of paths to generate as a JSON Object
/// * `current_root` - The current operating directory path /// * `current_root` - The current operating directory path
fn generate_paths(&mut self, json_file_tree: &serde_json::Value, current_root: &mut String) { fn generate_paths(&mut self, json_file_tree: &serde_json::Value, current_root: &mut String) {
match json_file_tree { match json_file_tree {
@ -128,6 +147,7 @@ impl Config {
self.generate_paths(dir, &mut current_root) self.generate_paths(dir, &mut current_root)
); );
} }
/// Parses a file from a JSON String /// Parses a file from a JSON String
/// ///
/// # Arguments /// # Arguments
@ -188,6 +208,7 @@ fn read_file_from_path(file_path: &str) -> String {
}, },
} }
} }
///TODO: Docs
fn convert_if_user_folder(dirname: &str, want_username: bool) -> String { fn convert_if_user_folder(dirname: &str, want_username: bool) -> String {
use std::env; use std::env;

View File

@ -1,13 +1,17 @@
///TODO: Docs
pub fn json_parsing_error() -> ! { pub fn json_parsing_error() -> ! {
eprintln!("Error parsing JSON String. Check to see if your syntax is valid."); eprintln!("Error parsing JSON String. Check to see if your syntax is valid.");
std::process::exit(1) std::process::exit(1)
} }
///TODO: Docs
pub fn create_dir_error(dir: &str) { pub fn create_dir_error(dir: &str) {
eprintln!("There was an issue creating the directory {}. It may already exist.", dir); eprintln!("There was an issue creating the directory {}. It may already exist.", dir);
} }
///TODO: Docs
pub fn copy_file_error(path: &str) { pub fn copy_file_error(path: &str) {
eprintln!("There was an issue copying the path {}", path); eprintln!("There was an issue copying the path {}", path);
} }
///TODO: Docs
pub fn empty_path_error() { pub fn empty_path_error() {
eprintln!("A path seems to be empty"); eprintln!("A path seems to be empty");
} }

View File

@ -1,4 +1,8 @@
//TODO: mod install use crate::config;
//TODO: mod install
//TODO: clone dotfiles //TODO: clone dotfiles
//TODO: copy dotfiles to location in config //TODO: copy dotfiles to location in config
pub fn run(args: &config::Args) {
()
}