-
Notifications
You must be signed in to change notification settings - Fork 1k
fix: stop remove $CARGO_HOME on uninstallation #4861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ use windows_sys::Win32::Foundation::{ERROR_FILE_NOT_FOUND, ERROR_INVALID_DATA}; | |
|
|
||
| use super::super::errors::CliError; | ||
| use super::common; | ||
| use super::delete_cargo_bin; | ||
| use super::{InstallOpts, install_bins, report_error}; | ||
| use crate::cli::markdown::md; | ||
| use crate::config::Cfg; | ||
|
|
@@ -348,16 +349,25 @@ fn has_windows_sdk_libs(process: &Process) -> bool { | |
| false | ||
| } | ||
|
|
||
| /// Run by rustup-gc-$num.exe to delete CARGO_HOME | ||
| /// Run by rustup-gc-$num.exe to delete rustup binary | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems unrelated, maybe move it into a separate commit?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @djc I think this is relevant though; the new behavior is to remove traces of rustup in the bindir rather than nuking CARGO_HOME. |
||
| #[tracing::instrument(level = "trace")] | ||
| pub fn complete_windows_uninstall(process: &Process) -> Result<utils::ExitCode> { | ||
| use std::process::Stdio; | ||
|
|
||
| wait_for_parent()?; | ||
|
|
||
| // Now that the parent has exited there are hopefully no more files open in CARGO_HOME | ||
| let cargo_home = process.cargo_home()?; | ||
| utils::remove_dir("cargo_home", &cargo_home)?; | ||
| // Now that the parent has exited, rustup.exe is hopefully no longer open. | ||
| let cargo_home_dir = process.cargo_home()?; | ||
| let rustup_bin = cargo_home_dir.join(format!("bin/rustup{EXE_SUFFIX}")); | ||
| utils::remove_file("rustup_bin", &rustup_bin)?; | ||
|
|
||
| // Best effort remove `$CARGO_HOME/bin`. | ||
| let no_modify_path = process.var_os(GC_NO_MODIFY_PATH).as_deref() == Some(OsStr::new("1")); | ||
| let cargo_bin_path = cargo_home_dir.join("bin"); | ||
|
|
||
| // Clean up CARGO_HOME/bin if it's empty now | ||
| // On success, also remove it from $PATH. | ||
| delete_cargo_bin(cargo_bin_path, no_modify_path, process)?; | ||
|
|
||
| // Now, run a *system* binary to inherit the DELETE_ON_CLOSE | ||
| // handle to *this* process, then exit. The OS will delete the gc | ||
|
|
@@ -374,6 +384,8 @@ pub fn complete_windows_uninstall(process: &Process) -> Result<utils::ExitCode> | |
| Ok(utils::ExitCode(0)) | ||
| } | ||
|
|
||
| const GC_NO_MODIFY_PATH: &str = "RUSTUP_GC_NO_MODIFY_PATH"; | ||
|
|
||
| pub(crate) fn wait_for_parent() -> Result<()> { | ||
| use std::io; | ||
| use std::mem; | ||
|
|
@@ -644,9 +656,9 @@ pub(crate) fn self_replace(process: &Process) -> Result<utils::ExitCode> { | |
| Ok(utils::ExitCode(0)) | ||
| } | ||
|
|
||
| // The last step of uninstallation is to delete *this binary*, | ||
| // rustup.exe and the CARGO_HOME that contains it. On Unix, this | ||
| // works fine. On Windows you can't delete files while they are open, | ||
| // The last step of uninstallation is to delete *this binary*, rustup.exe. | ||
| // On Unix, this works fine. | ||
| // On Windows you can't delete files while they are open, | ||
| // like when they are running. | ||
| // | ||
| // Here's what we're going to do: | ||
|
|
@@ -659,7 +671,7 @@ pub(crate) fn self_replace(process: &Process) -> Result<utils::ExitCode> { | |
| // processes created with the option to inherit handles | ||
| // will also keep them open. | ||
| // - Run the gc exe, which waits for the original rustup.exe | ||
| // process to close, then deletes CARGO_HOME. This process | ||
| // process to close, then deletes rustup.exe. This process | ||
| // has inherited a FILE_FLAG_DELETE_ON_CLOSE handle to itself. | ||
| // - Finally, spawn yet another system binary with the inherit handles | ||
| // flag, so *it* inherits the FILE_FLAG_DELETE_ON_CLOSE handle to | ||
|
|
@@ -674,7 +686,7 @@ pub(crate) fn self_replace(process: &Process) -> Result<utils::ExitCode> { | |
| // | ||
| // .. augmented with this SO answer | ||
| // https://stackoverflow.com/questions/10319526/understanding-a-self-deleting-program-in-c | ||
| pub(crate) fn delete_rustup_and_cargo_home(process: &Process) -> Result<()> { | ||
| pub(crate) fn clean_cargo_bin(process: &Process, no_modify_path: bool) -> Result<()> { | ||
| use std::io; | ||
| use std::ptr; | ||
| use std::thread; | ||
|
|
@@ -734,6 +746,7 @@ pub(crate) fn delete_rustup_and_cargo_home(process: &Process) -> Result<()> { | |
| }; | ||
|
|
||
| Command::new(gc_exe) | ||
| .env(GC_NO_MODIFY_PATH, if no_modify_path { "1" } else { "0" }) | ||
| .spawn() | ||
| .context(CliError::WindowsUninstallMadness)?; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.