✨ Feat: Add basic git identity management
This commit is contained in:
parent
b9e346516c
commit
7339f7dfc3
3 changed files with 553 additions and 0 deletions
322
Cargo.lock
generated
Normal file
322
Cargo.lock
generated
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[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 = "equivalent"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "git_config_menu"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"dirs",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.15.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.169"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[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.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libredox",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.217"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.217"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.22.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "git_config_menu"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dirs = "6.0.0"
|
||||||
|
toml = "0.8.20"
|
223
src/main.rs
Normal file
223
src/main.rs
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
use std::fs::{create_dir_all, File};
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let config_file = get_config_file_path();
|
||||||
|
// Load existing config or create a new one with an empty identities table.
|
||||||
|
let mut config = load_config(&config_file).unwrap_or_else(create_empty_config);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
println!("\n=== Git Identity Manager ===\n");
|
||||||
|
|
||||||
|
// Display the available identities.
|
||||||
|
if let Some(identities_table) = config.get("identities").and_then(|v| v.as_table()) {
|
||||||
|
if identities_table.is_empty() {
|
||||||
|
println!("No identities found.");
|
||||||
|
} else {
|
||||||
|
println!("Available identities:");
|
||||||
|
let mut keys: Vec<&String> = identities_table.keys().collect();
|
||||||
|
keys.sort();
|
||||||
|
for (i, key) in keys.iter().enumerate() {
|
||||||
|
if let Some(identity) = identities_table.get(*key) {
|
||||||
|
let name = identity
|
||||||
|
.get("name")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.unwrap_or("N/A");
|
||||||
|
let email = identity
|
||||||
|
.get("email")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.unwrap_or("N/A");
|
||||||
|
println!(" {}. {} <{}>", i + 1, name, email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("Identities configuration missing.");
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\nOptions:");
|
||||||
|
println!(" [number] - Select and set that identity");
|
||||||
|
println!(" a - Add a new identity");
|
||||||
|
println!(" q - Quit");
|
||||||
|
|
||||||
|
print!("\nEnter your choice: ");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
let mut choice = String::new();
|
||||||
|
io::stdin().read_line(&mut choice).unwrap();
|
||||||
|
let choice = choice.trim();
|
||||||
|
|
||||||
|
if choice.eq_ignore_ascii_case("q") {
|
||||||
|
println!("Exiting without changes.");
|
||||||
|
break;
|
||||||
|
} else if choice.eq_ignore_ascii_case("a") {
|
||||||
|
// Add a new identity.
|
||||||
|
let (key, new_identity) = add_new_identity();
|
||||||
|
{
|
||||||
|
let identities_table = config
|
||||||
|
.get_mut("identities")
|
||||||
|
.and_then(|v| v.as_table_mut())
|
||||||
|
.expect("Identities must be a table");
|
||||||
|
//FIX: This will overwrite an existing identity with the same key.
|
||||||
|
identities_table.insert(key.clone(), new_identity.clone());
|
||||||
|
}
|
||||||
|
if let Err(e) = save_config(&config_file, &config) {
|
||||||
|
println!("Error saving config: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if let (Some(name), Some(email)) = (
|
||||||
|
new_identity.get("name").and_then(|v| v.as_str()),
|
||||||
|
new_identity.get("email").and_then(|v| v.as_str()),
|
||||||
|
) {
|
||||||
|
if apply_identity(name, email) {
|
||||||
|
println!("Git identity set to {} <{}>", name, email);
|
||||||
|
} else {
|
||||||
|
println!("Failed to set git identity. Make sure you're in a Git repository.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; // Exit after setting an identity.
|
||||||
|
} else if let Ok(num) = choice.parse::<usize>() {
|
||||||
|
// Selecting an existing identity.
|
||||||
|
let keys: Vec<String> = {
|
||||||
|
if let Some(identities_table) = config.get("identities").and_then(|v| v.as_table())
|
||||||
|
{
|
||||||
|
let mut keys: Vec<String> = identities_table.keys().cloned().collect();
|
||||||
|
keys.sort();
|
||||||
|
keys
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if num > 0 && num <= keys.len() {
|
||||||
|
let key = &keys[num - 1];
|
||||||
|
if let Some(identity) = config
|
||||||
|
.get("identities")
|
||||||
|
.and_then(|v| v.as_table())
|
||||||
|
.and_then(|table| table.get(key))
|
||||||
|
{
|
||||||
|
if let (Some(name), Some(email)) = (
|
||||||
|
identity.get("name").and_then(|v| v.as_str()),
|
||||||
|
identity.get("email").and_then(|v| v.as_str()),
|
||||||
|
) {
|
||||||
|
if apply_identity(name, email) {
|
||||||
|
println!("Git identity set to {} <{}>", name, email);
|
||||||
|
} else {
|
||||||
|
println!(
|
||||||
|
"Failed to set git identity. Make sure you're in a Git repository."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; // Exit after setting an identity.
|
||||||
|
} else {
|
||||||
|
println!("Invalid selection.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("Invalid input.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the path to the configuration file using the dirs crate.
|
||||||
|
/// This places the file under:
|
||||||
|
/// - Linux/Unix: $XDG_CONFIG_HOME/git_identity_manager/git_identities.toml (or $HOME/.config/...)
|
||||||
|
/// - macOS: $HOME/Library/Application Support/git_identity_manager/git_identities.toml
|
||||||
|
/// - Windows: %APPDATA%\git_identity_manager\git_identities.toml
|
||||||
|
fn get_config_file_path() -> PathBuf {
|
||||||
|
let base_dir = dirs::config_dir().unwrap_or_else(|| PathBuf::from("."));
|
||||||
|
let config_path = base_dir.join("git_identity_manager");
|
||||||
|
if let Err(e) = create_dir_all(&config_path) {
|
||||||
|
eprintln!("Failed to create config directory: {}", e);
|
||||||
|
}
|
||||||
|
config_path.join("git_identities.toml")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_config(path: &Path) -> Option<toml::Value> {
|
||||||
|
if !path.exists() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut file = File::open(path).ok()?;
|
||||||
|
let mut contents = String::new();
|
||||||
|
file.read_to_string(&mut contents).ok()?;
|
||||||
|
toml::from_str(&contents).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_config(path: &Path, config: &toml::Value) -> io::Result<()> {
|
||||||
|
let toml_string = format_config(config);
|
||||||
|
let mut file = File::create(path)?;
|
||||||
|
file.write_all(toml_string.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Formats the configuration in a more conventional TOML style.
|
||||||
|
/// For example:
|
||||||
|
///
|
||||||
|
/// [identities.The_Linux_Developer]
|
||||||
|
/// name = "The Linux Developer"
|
||||||
|
/// email = "email@thelinux.dev"
|
||||||
|
fn format_config(config: &toml::Value) -> String {
|
||||||
|
let mut output = String::new();
|
||||||
|
if let Some(identities) = config.get("identities").and_then(|v| v.as_table()) {
|
||||||
|
for (key, value) in identities {
|
||||||
|
output.push_str(&format!("[identities.{}]\n", key));
|
||||||
|
if let Some(inner) = value.as_table() {
|
||||||
|
for (k, v) in inner {
|
||||||
|
if let Some(s) = v.as_str() {
|
||||||
|
output.push_str(&format!("{} = \"{}\"\n", k, s));
|
||||||
|
} else {
|
||||||
|
output.push_str(&format!("{} = {}\n", k, v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_empty_config() -> toml::Value {
|
||||||
|
let mut table = toml::value::Table::new();
|
||||||
|
table.insert(
|
||||||
|
"identities".to_string(),
|
||||||
|
toml::Value::Table(toml::value::Table::new()),
|
||||||
|
);
|
||||||
|
toml::Value::Table(table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interactively prompts the user to add a new identity.
|
||||||
|
/// The entered Git name is used both as the displayed name and, after replacing spaces with underscores,
|
||||||
|
/// as the key in the configuration.
|
||||||
|
fn add_new_identity() -> (String, toml::Value) {
|
||||||
|
println!("\nAdding new identity:");
|
||||||
|
print!("Enter the Git name for this identity: ");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
let mut display_name = String::new();
|
||||||
|
io::stdin().read_line(&mut display_name).unwrap();
|
||||||
|
let display_name = display_name.trim().to_string();
|
||||||
|
|
||||||
|
print!("Enter your Git email: ");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
let mut email = String::new();
|
||||||
|
io::stdin().read_line(&mut email).unwrap();
|
||||||
|
let email = email.trim().to_string();
|
||||||
|
|
||||||
|
//TODO: Sanitize the key by replacing spaces with underscores
|
||||||
|
let key = display_name.replace(" ", "_");
|
||||||
|
let mut id_table = toml::value::Table::new();
|
||||||
|
// Use the full display_name for the "name" field
|
||||||
|
id_table.insert("name".to_string(), toml::Value::String(display_name));
|
||||||
|
id_table.insert("email".to_string(), toml::Value::String(email));
|
||||||
|
|
||||||
|
(key, toml::Value::Table(id_table))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_identity(name: &str, email: &str) -> bool {
|
||||||
|
let status_name = Command::new("git")
|
||||||
|
.args(["config", "user.name", name])
|
||||||
|
.status();
|
||||||
|
let status_email = Command::new("git")
|
||||||
|
.args(["config", "user.email", email])
|
||||||
|
.status();
|
||||||
|
status_name.map(|s| s.success()).unwrap_or(false)
|
||||||
|
&& status_email.map(|s| s.success()).unwrap_or(false)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue