feat(cli): add functionality to cli

added implementations of "add" "use" and "list"
This commit is contained in:
2026-09-01 16:47:46 -05:00
parent 029fc48b53
commit 2be76c5f65
6 changed files with 206 additions and 2 deletions
Generated
+97
View File
@@ -52,6 +52,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.6.6" version = "4.6.6"
@@ -98,11 +104,44 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" 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]] [[package]]
name = "git-su" name = "git-su"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"dirs",
"serde", "serde",
"serde_json", "serde_json",
] ]
@@ -125,6 +164,21 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" 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]] [[package]]
name = "memchr" name = "memchr"
version = "2.8.3" version = "2.8.3"
@@ -137,6 +191,12 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.107" version = "1.0.107"
@@ -155,6 +215,17 @@ dependencies = [
"proc-macro2", "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]] [[package]]
name = "serde" name = "serde"
version = "1.0.229" version = "1.0.229"
@@ -215,6 +286,26 @@ dependencies = [
"unicode-ident", "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]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.24" version = "1.0.24"
@@ -227,6 +318,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 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]] [[package]]
name = "windows-link" name = "windows-link"
version = "0.2.1" version = "0.2.1"
+1
View File
@@ -5,5 +5,6 @@ edition = "2024"
[dependencies] [dependencies]
clap = { version = "4.6.6", features = ["derive"] } clap = { version = "4.6.6", features = ["derive"] }
dirs = "6.0.0"
serde = { version = "1.0.229", features = ["derive"] } serde = { version = "1.0.229", features = ["derive"] }
serde_json = "1.0.151" serde_json = "1.0.151"
+1 -1
View File
@@ -4,7 +4,7 @@ use clap::{Args, Parser, Subcommand};
#[command(version, about = "a cli to change git users")] #[command(version, about = "a cli to change git users")]
pub struct Cli { pub struct Cli {
#[command(subcommand)] #[command(subcommand)]
command: Commands, pub command: Commands,
} }
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
+51
View File
@@ -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<Vec<Profile>, 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::<BufReader<File>, Vec<Profile>>(reader)
.expect("unable to parse json"),
)
}
pub fn write_profile_list(profiles: Vec<Profile>) -> 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(())
}
+46 -1
View File
@@ -1,8 +1,53 @@
use clap::Parser; use clap::Parser;
use crate::cli::Commands;
use crate::config::Profile;
mod cli; mod cli;
mod config;
mod utils;
fn main() { fn main() {
let args = cli::Cli::parse(); 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")
}
}
} }
+10
View File
@@ -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");
}