Skip to content

Commit 7a5a961

Browse files
committed
Add uninstall
1 parent d69576b commit 7a5a961

5 files changed

Lines changed: 90 additions & 2 deletions

File tree

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ curl --proto '=https' --tlsv1.2 -LsSf \
3131

3232
The installer places `rgpt` in `$CARGO_HOME/bin` (normally `~/.cargo/bin`). Add that directory to your `PATH` if it is not already present. You can also download an archive for a specific release from the [Releases page](https://github.com/ShaderCompilation/rgpt/releases).
3333

34+
### Uninstall
35+
36+
Run the installed command and confirm the prompt:
37+
38+
```sh
39+
rgpt --uninstall
40+
```
41+
42+
This removes the executable plus rgpt's configuration, saved chats, roles, and response cache. For a non-interactive uninstall, use `rgpt --uninstall --yes`.
43+
3444
### Build from source
3545

3646
To build locally, install a current stable Rust toolchain, then run:

src/cli.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ pub struct Cli {
2727
#[arg(long, help_heading = "Assistance Options")]
2828
pub editor: bool,
2929

30+
/// Remove rgpt, including its saved configuration, chats, roles, and cache.
31+
#[arg(long, help_heading = "Application Options")]
32+
pub uninstall: bool,
33+
34+
/// Do not ask for confirmation when uninstalling.
35+
#[arg(long, requires = "uninstall", help_heading = "Application Options")]
36+
pub yes: bool,
37+
3038
/// Large language model to use.
3139
#[arg(long)]
3240
pub model: Option<String>,

src/config.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,11 @@ impl Config {
134134
}
135135
}
136136

137-
fn config_path() -> Result<PathBuf> {
137+
pub fn app_dir() -> Result<PathBuf> {
138138
let base = dirs::config_dir().context("could not determine config directory")?;
139-
Ok(base.join("rgpt").join(".rgptrc"))
139+
Ok(base.join("rgpt"))
140+
}
141+
142+
fn config_path() -> Result<PathBuf> {
143+
Ok(app_dir()?.join(".rgptrc"))
140144
}

src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod render;
99
mod role;
1010
mod shell_cmd;
1111
mod tools;
12+
mod uninstall;
1213

1314
use anyhow::{Context, Result};
1415
use clap::Parser;
@@ -23,6 +24,10 @@ fn main() -> Result<()> {
2324
let cli = cli::Cli::parse();
2425
cli.validate()?;
2526

27+
if cli.uninstall {
28+
return uninstall::run(cli.yes);
29+
}
30+
2631
let config = Config::load(cli.ollama).context("loading config")?;
2732
SystemRole::ensure_defaults(&config).context("creating default roles")?;
2833

src/uninstall.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use std::fs;
2+
use std::io::{self, Write};
3+
use std::path::Path;
4+
5+
use anyhow::{Context, Result, bail};
6+
7+
use crate::config;
8+
9+
pub fn run(assume_yes: bool) -> Result<()> {
10+
let binary = std::env::current_exe().context("locating the rgpt executable")?;
11+
let data_dir = config::app_dir()?;
12+
13+
if !assume_yes {
14+
println!("This will remove:");
15+
println!(" {}", binary.display());
16+
println!(
17+
" {} (configuration, chats, roles, and cache)",
18+
data_dir.display()
19+
);
20+
print!("Continue? [y/N] ");
21+
io::stdout().flush().ok();
22+
23+
let mut answer = String::new();
24+
io::stdin()
25+
.read_line(&mut answer)
26+
.context("reading uninstall confirmation")?;
27+
if !matches!(answer.trim().to_ascii_lowercase().as_str(), "y" | "yes") {
28+
bail!("Uninstall cancelled.");
29+
}
30+
}
31+
32+
remove_data_dir(&data_dir)?;
33+
fs::remove_file(&binary)
34+
.with_context(|| format!("removing executable {}", binary.display()))?;
35+
println!("rgpt has been uninstalled.");
36+
Ok(())
37+
}
38+
39+
fn remove_data_dir(path: &Path) -> Result<()> {
40+
if path.exists() {
41+
fs::remove_dir_all(path)
42+
.with_context(|| format!("removing application data directory {}", path.display()))?;
43+
}
44+
Ok(())
45+
}
46+
47+
#[cfg(test)]
48+
mod tests {
49+
use super::remove_data_dir;
50+
51+
#[test]
52+
fn removes_application_data_directory() {
53+
let dir = std::env::temp_dir().join(format!("rgpt-uninstall-test-{}", std::process::id()));
54+
std::fs::create_dir_all(&dir).unwrap();
55+
std::fs::write(dir.join("config"), "secret").unwrap();
56+
57+
remove_data_dir(&dir).unwrap();
58+
59+
assert!(!dir.exists());
60+
}
61+
}

0 commit comments

Comments
 (0)