use crate::command::{CommandExecutor, CommandOutput, GitCommand};
use crate::error::{Error, Result};
use async_trait::async_trait;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConfigScope {
Local,
Global,
System,
Worktree,
}
#[derive(Debug, Clone)]
pub enum ConfigAction {
Get {
key: String,
},
GetAll {
key: String,
},
Set {
key: String,
value: String,
},
Unset {
key: String,
},
UnsetAll {
key: String,
},
Add {
key: String,
value: String,
},
List,
}
#[derive(Debug, Clone)]
pub struct ConfigCommand {
pub executor: CommandExecutor,
pub action: ConfigAction,
pub scope: Option<ConfigScope>,
}
impl ConfigCommand {
pub fn get(key: impl Into<String>) -> Self {
Self {
executor: CommandExecutor::default(),
action: ConfigAction::Get { key: key.into() },
scope: None,
}
}
pub fn get_all(key: impl Into<String>) -> Self {
Self {
executor: CommandExecutor::default(),
action: ConfigAction::GetAll { key: key.into() },
scope: None,
}
}
pub fn set(key: impl Into<String>, value: impl Into<String>) -> Self {
Self {
executor: CommandExecutor::default(),
action: ConfigAction::Set {
key: key.into(),
value: value.into(),
},
scope: None,
}
}
pub fn unset(key: impl Into<String>) -> Self {
Self {
executor: CommandExecutor::default(),
action: ConfigAction::Unset { key: key.into() },
scope: None,
}
}
pub fn unset_all(key: impl Into<String>) -> Self {
Self {
executor: CommandExecutor::default(),
action: ConfigAction::UnsetAll { key: key.into() },
scope: None,
}
}
pub fn add(key: impl Into<String>, value: impl Into<String>) -> Self {
Self {
executor: CommandExecutor::default(),
action: ConfigAction::Add {
key: key.into(),
value: value.into(),
},
scope: None,
}
}
#[must_use]
pub fn list() -> Self {
Self {
executor: CommandExecutor::default(),
action: ConfigAction::List,
scope: None,
}
}
#[must_use]
pub fn scope(mut self, s: ConfigScope) -> Self {
self.scope = Some(s);
self
}
}
#[async_trait]
impl GitCommand for ConfigCommand {
type Output = CommandOutput;
fn get_executor(&self) -> &CommandExecutor {
&self.executor
}
fn get_executor_mut(&mut self) -> &mut CommandExecutor {
&mut self.executor
}
fn build_command_args(&self) -> Vec<String> {
let mut args = vec!["config".to_string()];
match self.scope {
Some(ConfigScope::Local) => args.push("--local".into()),
Some(ConfigScope::Global) => args.push("--global".into()),
Some(ConfigScope::System) => args.push("--system".into()),
Some(ConfigScope::Worktree) => args.push("--worktree".into()),
None => {}
}
match &self.action {
ConfigAction::Get { key } => args.push(key.clone()),
ConfigAction::GetAll { key } => {
args.push("--get-all".into());
args.push(key.clone());
}
ConfigAction::Set { key, value } => {
args.push(key.clone());
args.push(value.clone());
}
ConfigAction::Unset { key } => {
args.push("--unset".into());
args.push(key.clone());
}
ConfigAction::UnsetAll { key } => {
args.push("--unset-all".into());
args.push(key.clone());
}
ConfigAction::Add { key, value } => {
args.push("--add".into());
args.push(key.clone());
args.push(value.clone());
}
ConfigAction::List => args.push("--list".into()),
}
args
}
async fn execute(&self) -> Result<CommandOutput> {
self.execute_raw().await
}
}
impl ConfigCommand {
pub async fn execute_value(&self) -> Result<String> {
match self.action {
ConfigAction::Get { .. } | ConfigAction::GetAll { .. } => {
let out = self.execute_raw().await?;
Ok(out.stdout_trimmed().to_string())
}
_ => Err(Error::invalid_config(
"execute_value only applies to get / get-all actions",
)),
}
}
}