diff --git a/Cargo.lock b/Cargo.lock index 51341b4..cf42c1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,6 +52,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + [[package]] name = "clap" version = "4.6.6" @@ -98,11 +104,44 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "git-su" version = "0.1.0" dependencies = [ "clap", + "dirs", "serde", "serde_json", ] @@ -125,6 +164,21 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libredox" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7955dfc218a8afb29dfeffd540e3a6e96baeb94fe7138228dd7cc6937fbbf96" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.8.3" @@ -137,6 +191,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "proc-macro2" version = "1.0.107" @@ -155,6 +215,17 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "serde" version = "1.0.229" @@ -215,6 +286,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.24" @@ -227,6 +318,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + [[package]] name = "windows-link" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index b3043b3..e7510fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ edition = "2024" [dependencies] clap = { version = "4.6.6", features = ["derive"] } +dirs = "6.0.0" serde = { version = "1.0.229", features = ["derive"] } serde_json = "1.0.151" diff --git a/src/cli.rs b/src/cli.rs index b5474f6..6f9b372 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -4,7 +4,7 @@ use clap::{Args, Parser, Subcommand}; #[command(version, about = "a cli to change git users")] pub struct Cli { #[command(subcommand)] - command: Commands, + pub command: Commands, } #[derive(Debug, Subcommand)] diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..98af736 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,51 @@ +use std::{ + fs::{self, File}, + io::{BufReader, BufWriter, Error}, + path::{Path, PathBuf}, +}; + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Profile { + pub name: String, + pub username: String, + pub email: String, +} + +fn get_config_dir() -> PathBuf { + let mut config_dir = dirs::config_dir().expect("unable to find config dir"); + config_dir.push("git-su"); + config_dir +} + +fn create_if_missing(file: &Path, content: &str) -> Result<(), Error> { + if !file.exists() { + fs::write(file, content) + } else { + Ok(()) + } +} + +pub fn get_profile_list() -> Result, String> { + let config_dir = get_config_dir(); + fs::create_dir_all(&config_dir).expect("unable to create config directory"); + let profile_file = config_dir.join("profiles.json"); + create_if_missing(profile_file.as_path(), "[]").expect("unable to create profile file"); + let profile_file = File::open(&profile_file).expect("unable to open profile file"); + let reader = BufReader::new(profile_file); + Ok( + serde_json::from_reader::, Vec>(reader) + .expect("unable to parse json"), + ) +} + +pub fn write_profile_list(profiles: Vec) -> Result<(), String> { + let config_dir = get_config_dir(); + fs::create_dir_all(&config_dir).expect("unable to create config directory"); + let profile_file = config_dir.join("profiles.json"); + let profile_file = File::create(&profile_file).expect("unable to create profile file"); + let writer = BufWriter::new(profile_file); + serde_json::to_writer_pretty(writer, &profiles).expect("unable to write json"); + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index ab49348..5111f8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,53 @@ use clap::Parser; +use crate::cli::Commands; +use crate::config::Profile; + mod cli; +mod config; +mod utils; fn main() { let args = cli::Cli::parse(); - println!("{:?}", args); + + match args.command { + Commands::List => { + let profiles = config::get_profile_list().expect("unable to get list of profiles"); + if profiles.is_empty() { + println!("no profiles found"); + return; + } + + println!("{:<15} {:<20} {:<25}", "profile", "name", "email"); + for profile in profiles { + println!( + "{:<15} {:<20} {:<25}", + profile.name, profile.username, profile.email + ); + } + } + Commands::Use(args) => { + let profiles = config::get_profile_list().expect("unable to get list of profiles"); + let profile = profiles.iter().find(|p| p.name == args.profile_name); + if profile.is_none() { + println!("profile not found"); + return; + } + + let profile = profile.unwrap(); + let global = if args.global { "--global" } else { "" }; + utils::run_command("git", &["config", "user.name", &profile.username, global]); + utils::run_command("git", &["config", "user.email", &profile.email, global]); + } + Commands::Add(args) => { + let mut profiles = config::get_profile_list().expect("unable to get list of profiles"); + profiles.push(Profile { + name: args.profile_name, + username: args.name, + email: args.email, + }); + config::write_profile_list(profiles).expect("unable to write profile file"); + println!("profile added") + } + } } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..1c5f392 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,10 @@ +use std::process::Command; + +pub fn run_command(command: &str, args: &[&str]) { + let mut child = Command::new(command) + .args(args) + .spawn() + .expect("failed to execute process"); + + let _ = child.wait().expect("failed to wait on child"); +}