update platform-specific uninstall fns

This commit is contained in:
llama 2025-10-24 19:35:32 +08:00
parent 8f1a3dca94
commit dd0a676fcd
No known key found for this signature in database
GPG key ID: 0B7543854B9413C3
3 changed files with 27 additions and 36 deletions

View file

@ -5,6 +5,7 @@ use std::path::Path;
use std::process::Command; use std::process::Command;
use anki_process::CommandExt as AnkiCommandExt; use anki_process::CommandExt as AnkiCommandExt;
use anki_proto::launcher::uninstall_response::ActionNeeded;
use anyhow::Result; use anyhow::Result;
pub fn prepare_for_launch_after_update(mut cmd: Command, root: &Path) -> Result<()> { pub fn prepare_for_launch_after_update(mut cmd: Command, root: &Path) -> Result<()> {
@ -34,7 +35,7 @@ pub fn prepare_for_launch_after_update(mut cmd: Command, root: &Path) -> Result<
Ok(()) Ok(())
} }
pub fn finalize_uninstall() { pub fn finalize_uninstall() -> Result<Option<ActionNeeded>> {
if let Ok(exe_path) = std::env::current_exe() { if let Ok(exe_path) = std::env::current_exe() {
// Find the .app bundle by walking up the directory tree // Find the .app bundle by walking up the directory tree
let mut app_bundle_path = exe_path.as_path(); let mut app_bundle_path = exe_path.as_path();
@ -43,22 +44,17 @@ pub fn finalize_uninstall() {
if name.to_string_lossy().ends_with(".app") { if name.to_string_lossy().ends_with(".app") {
let result = Command::new("trash").arg(parent).output(); let result = Command::new("trash").arg(parent).output();
match result { return Ok(match result {
Ok(output) if output.status.success() => { Ok(output) if output.status.success() => None,
println!("Anki has been uninstalled.");
return;
}
_ => { _ => {
// Fall back to manual instructions // Fall back to manual instructions
println!( Some(ActionNeeded::MacManual(()))
"Please manually drag Anki.app to the trash to complete uninstall."
);
} }
} });
return;
} }
} }
app_bundle_path = parent; app_bundle_path = parent;
} }
} }
Ok(None)
} }

View file

@ -1,24 +1,17 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use anki_proto::launcher::uninstall_response::ActionNeeded;
use anyhow::Result; use anyhow::Result;
pub fn finalize_uninstall() { pub fn finalize_uninstall() -> Result<Option<ActionNeeded>> {
use std::io::stdin;
use std::io::stdout;
use std::io::Write;
let uninstall_script = std::path::Path::new("/usr/local/share/anki/uninstall.sh"); let uninstall_script = std::path::Path::new("/usr/local/share/anki/uninstall.sh");
if uninstall_script.exists() { Ok(uninstall_script
println!("To finish uninstalling, run 'sudo /usr/local/share/anki/uninstall.sh'"); .exists()
} else { .then_some(ActionNeeded::UnixScript(
println!("Anki has been uninstalled."); uninstall_script.display().to_string(),
} )))
println!("Press enter to quit.");
let _ = stdout().flush();
let mut input = String::new();
let _ = stdin().read_line(&mut input);
} }
pub fn ensure_glibc_supported() -> Result<()> { pub fn ensure_glibc_supported() -> Result<()> {

View file

@ -4,7 +4,8 @@
use std::io::stdin; use std::io::stdin;
use std::process::Command; use std::process::Command;
use anyhow::Context; use anki_proto::launcher::uninstall_response::ActionNeeded;
use anki_proto::launcher::uninstall_response::WindowsInstallerError;
use anyhow::Result; use anyhow::Result;
use widestring::u16cstr; use widestring::u16cstr;
use windows::core::PCWSTR; use windows::core::PCWSTR;
@ -58,33 +59,34 @@ pub fn ensure_windows_version_supported() -> Result<()> {
} }
} }
pub fn finalize_uninstall() { pub fn finalize_uninstall() -> Result<Option<ActionNeeded>> {
let uninstaller_path = get_uninstaller_path(); let uninstaller_path = get_uninstaller_path();
match uninstaller_path { Ok(match uninstaller_path {
Some(path) => { Some(path) => {
println!("Launching Windows uninstaller..."); println!("Launching Windows uninstaller...");
let result = Command::new(&path).env("ANKI_LAUNCHER", "1").spawn(); let result = Command::new(&path).env("ANKI_LAUNCHER", "1").spawn();
match result { match result {
Ok(_) => { Ok(_) => None,
println!("Uninstaller launched successfully.");
return;
}
Err(e) => { Err(e) => {
println!("Failed to launch uninstaller: {e}"); println!("Failed to launch uninstaller: {e}");
println!("You can manually run: {}", path.display()); println!("You can manually run: {}", path.display());
Some(ActionNeeded::WindowsInstallerFailed(
WindowsInstallerError {
error: format!("{e:?}"),
path: path.display().to_string(),
},
))
} }
} }
} }
None => { None => {
println!("Windows uninstaller not found."); println!("Windows uninstaller not found.");
println!("You may need to uninstall via Windows Settings > Apps."); println!("You may need to uninstall via Windows Settings > Apps.");
Some(ActionNeeded::WindowsInstallerNotFound(()))
} }
} })
println!("Press enter to close...");
let mut input = String::new();
let _ = stdin().read_line(&mut input);
} }
fn get_uninstaller_path() -> Option<std::path::PathBuf> { fn get_uninstaller_path() -> Option<std::path::PathBuf> {