mirror of
https://github.com/denoland/deno
synced 2024-09-13 13:21:50 +00:00
fix(upgrade/windows): show informative message on access denied error (#16887)
Closes #16886
This commit is contained in:
parent
c3b75c692c
commit
83bc8c473d
|
@ -8,6 +8,7 @@ use crate::util::progress_bar::ProgressBar;
|
|||
use crate::version;
|
||||
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::future::BoxFuture;
|
||||
use deno_core::futures::FutureExt;
|
||||
|
@ -234,14 +235,14 @@ async fn fetch_and_store_latest_version<
|
|||
}
|
||||
|
||||
pub async fn upgrade(upgrade_flags: UpgradeFlags) -> Result<(), AnyError> {
|
||||
let old_exe_path = std::env::current_exe()?;
|
||||
let metadata = fs::metadata(&old_exe_path)?;
|
||||
let current_exe_path = std::env::current_exe()?;
|
||||
let metadata = fs::metadata(¤t_exe_path)?;
|
||||
let permissions = metadata.permissions();
|
||||
|
||||
if permissions.readonly() {
|
||||
bail!(
|
||||
"You do not have write permission to {}",
|
||||
old_exe_path.display()
|
||||
current_exe_path.display()
|
||||
);
|
||||
}
|
||||
#[cfg(unix)]
|
||||
|
@ -252,7 +253,7 @@ pub async fn upgrade(upgrade_flags: UpgradeFlags) -> Result<(), AnyError> {
|
|||
"You don't have write permission to {} because it's owned by root.\n",
|
||||
"Consider updating deno through your package manager if its installed from it.\n",
|
||||
"Otherwise run `deno upgrade` as root.",
|
||||
), old_exe_path.display());
|
||||
), current_exe_path.display());
|
||||
}
|
||||
|
||||
let client = build_http_client(upgrade_flags.ca_file)?;
|
||||
|
@ -348,12 +349,33 @@ pub async fn upgrade(upgrade_flags: UpgradeFlags) -> Result<(), AnyError> {
|
|||
check_exe(&new_exe_path)?;
|
||||
|
||||
if !upgrade_flags.dry_run {
|
||||
match upgrade_flags.output {
|
||||
Some(path) => {
|
||||
fs::rename(&new_exe_path, &path)
|
||||
.or_else(|_| fs::copy(&new_exe_path, &path).map(|_| ()))?;
|
||||
let output_exe_path =
|
||||
upgrade_flags.output.as_ref().unwrap_or(¤t_exe_path);
|
||||
let output_result = if *output_exe_path == current_exe_path {
|
||||
replace_exe(&new_exe_path, output_exe_path)
|
||||
} else {
|
||||
fs::rename(&new_exe_path, output_exe_path)
|
||||
.or_else(|_| fs::copy(&new_exe_path, output_exe_path).map(|_| ()))
|
||||
};
|
||||
if let Err(err) = output_result {
|
||||
const WIN_ERROR_ACCESS_DENIED: i32 = 5;
|
||||
if cfg!(windows) && err.raw_os_error() == Some(WIN_ERROR_ACCESS_DENIED) {
|
||||
return Err(err).with_context(|| {
|
||||
format!(
|
||||
concat!(
|
||||
"Access denied: Could not replace the deno executable. This may be ",
|
||||
"because an existing deno process is running. Please ensure there ",
|
||||
"are no running deno processes (ex. Stop-Process -Name deno ; deno {}), ",
|
||||
"close any editors before upgrading, and ensure you have sufficient ",
|
||||
"permission to '{}'."
|
||||
),
|
||||
std::env::args().collect::<Vec<_>>().join(" "),
|
||||
output_exe_path.display(),
|
||||
)
|
||||
});
|
||||
} else {
|
||||
return Err(err.into());
|
||||
}
|
||||
None => replace_exe(&new_exe_path, &old_exe_path)?,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,17 +541,17 @@ pub fn unpack(
|
|||
Ok(exe_path)
|
||||
}
|
||||
|
||||
fn replace_exe(new: &Path, old: &Path) -> Result<(), std::io::Error> {
|
||||
fn replace_exe(from: &Path, to: &Path) -> Result<(), std::io::Error> {
|
||||
if cfg!(windows) {
|
||||
// On windows you cannot replace the currently running executable.
|
||||
// so first we rename it to deno.old.exe
|
||||
fs::rename(old, old.with_extension("old.exe"))?;
|
||||
fs::rename(to, to.with_extension("old.exe"))?;
|
||||
} else {
|
||||
fs::remove_file(old)?;
|
||||
fs::remove_file(to)?;
|
||||
}
|
||||
// Windows cannot rename files across device boundaries, so if rename fails,
|
||||
// we try again with copy.
|
||||
fs::rename(new, old).or_else(|_| fs::copy(new, old).map(|_| ()))?;
|
||||
fs::rename(from, to).or_else(|_| fs::copy(from, to).map(|_| ()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue