auths_cli/commands/
reset.rs1use anyhow::{Context, Result};
2use clap::Parser;
3
4use crate::adapters::git_config::SystemGitConfigProvider;
5use crate::commands::executable::ExecutableCommand;
6use crate::config::CliConfig;
7use crate::ux::format::Output;
8use auths_sdk::ports::git_config::GitConfigProvider;
9
10const GIT_SIGNING_CONFIG_KEYS: &[&str] = &[
12 "gpg.format",
13 "gpg.ssh.program",
14 "user.signingkey",
15 "commit.gpgsign",
16 "tag.gpgsign",
17 "gpg.ssh.allowedSignersFile",
18];
19
20#[derive(Parser, Debug, Clone)]
32#[command(
33 name = "reset",
34 about = "Remove Auths identity and git signing configuration"
35)]
36pub struct ResetCommand {
37 #[arg(long)]
39 force: bool,
40}
41
42impl ExecutableCommand for ResetCommand {
43 fn execute(&self, ctx: &CliConfig) -> Result<()> {
44 let out = Output::new();
45
46 if !self.force {
47 let confirmed = dialoguer::Confirm::new()
48 .with_prompt("This will remove ~/.auths and git signing config. Continue? [y/N]")
49 .default(false)
50 .interact()
51 .context("Failed to read confirmation")?;
52
53 if !confirmed {
54 out.println("Aborted.");
55 return Ok(());
56 }
57 }
58
59 out.newline();
60 out.print_heading("Resetting Auths...");
61 out.newline();
62
63 remove_auths_directory(&out, ctx.repo_path.clone())?;
64 clear_keychain_keys(&out, &ctx.env_config);
65 unset_git_signing_config(&out)?;
66
67 out.newline();
68 out.print_success("Reset complete. Run 'auths init' to set up again.");
69
70 Ok(())
71 }
72}
73
74fn remove_auths_directory(out: &Output, repo: Option<std::path::PathBuf>) -> Result<()> {
81 let auths_dir = auths_sdk::storage_layout::resolve_repo_path(repo)
82 .context("Failed to resolve the repository path to reset")?;
83
84 if auths_dir.exists() {
85 std::fs::remove_dir_all(&auths_dir)
86 .with_context(|| format!("Failed to remove {}", auths_dir.display()))?;
87 out.print_success(&format!("Removed {}", auths_dir.display()));
88 } else {
89 out.print_info(&format!("{} does not exist, skipping", auths_dir.display()));
90 }
91
92 Ok(())
93}
94
95fn unset_git_signing_config(out: &Output) -> Result<()> {
96 let provider = SystemGitConfigProvider::global();
97
98 for key in GIT_SIGNING_CONFIG_KEYS {
99 match provider.unset(key) {
100 Ok(()) => out.print_success(&format!("Unset git config {key}")),
101 Err(e) => out.print_warn(&format!("Could not unset {key}: {e}")),
102 }
103 }
104
105 Ok(())
106}
107
108fn clear_keychain_keys(out: &Output, env_config: &auths_sdk::core_config::EnvironmentConfig) {
110 let keychain = match auths_sdk::keychain::get_platform_keychain_with_config(env_config) {
111 Ok(k) => k,
112 Err(e) => {
113 out.print_warn(&format!("Could not access keychain to clear keys: {e}"));
114 return;
115 }
116 };
117
118 let aliases = match keychain.list_aliases() {
119 Ok(a) => a,
120 Err(e) => {
121 out.print_warn(&format!("Could not list keychain keys: {e}"));
122 return;
123 }
124 };
125
126 if aliases.is_empty() {
127 return;
128 }
129
130 for alias in &aliases {
131 match keychain.delete_key(alias) {
132 Ok(()) => {}
133 Err(e) => {
134 out.print_warn(&format!("Could not delete key '{}': {e}", alias.as_str()));
135 }
136 }
137 }
138
139 out.print_success(&format!(
140 "Cleared {} key(s) from {} keychain",
141 aliases.len(),
142 keychain.backend_name()
143 ));
144}