diff options
author | Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> | 2024-08-22 14:55:17 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-22 21:55:17 +0000 |
commit | f60640267776638d4699fbf05095dc6d1a9016f0 (patch) | |
tree | cbe7d284738cf1aed511f3ad3432444ceab573b6 /cli/npm/managed/resolvers/local.rs | |
parent | b6475d0f36a0476d95f1a0749f9db33b5aa73ecf (diff) |
fix(install): Use relative symlinks in deno install (#25164)
Fixes https://github.com/denoland/deno/issues/25161
Diffstat (limited to 'cli/npm/managed/resolvers/local.rs')
-rw-r--r-- | cli/npm/managed/resolvers/local.rs | 56 |
1 files changed, 32 insertions, 24 deletions
diff --git a/cli/npm/managed/resolvers/local.rs b/cli/npm/managed/resolvers/local.rs index 61e50ba8d..8f729d79c 100644 --- a/cli/npm/managed/resolvers/local.rs +++ b/cli/npm/managed/resolvers/local.rs @@ -1048,42 +1048,50 @@ fn symlink_package_dir( // need to delete the previous symlink before creating a new one let _ignore = fs::remove_dir_all(new_path); + let old_path_relative = + crate::util::path::relative_path(new_parent, old_path) + .unwrap_or_else(|| old_path.to_path_buf()); + #[cfg(windows)] - return junction_or_symlink_dir(old_path, new_path); + { + junction_or_symlink_dir(&old_path_relative, old_path, new_path) + } #[cfg(not(windows))] - symlink_dir(old_path, new_path) + { + symlink_dir(&old_path_relative, new_path).map_err(Into::into) + } } #[cfg(windows)] fn junction_or_symlink_dir( + old_path_relative: &Path, old_path: &Path, new_path: &Path, ) -> Result<(), AnyError> { - use deno_core::anyhow::bail; - // Use junctions because they're supported on ntfs file systems without - // needing to elevate privileges on Windows + static USE_JUNCTIONS: std::sync::atomic::AtomicBool = + std::sync::atomic::AtomicBool::new(false); + + if USE_JUNCTIONS.load(std::sync::atomic::Ordering::Relaxed) { + // Use junctions because they're supported on ntfs file systems without + // needing to elevate privileges on Windows. + // Note: junctions don't support relative paths, so we need to use the + // absolute path here. + return junction::create(old_path, new_path) + .context("Failed creating junction in node_modules folder"); + } - match junction::create(old_path, new_path) { + match symlink_dir(old_path_relative, new_path) { Ok(()) => Ok(()), - Err(junction_err) => { - if cfg!(debug_assertions) { - // When running the tests, junctions should be created, but if not then - // surface this error. - log::warn!("Error creating junction. {:#}", junction_err); - } - - match symlink_dir(old_path, new_path) { - Ok(()) => Ok(()), - Err(symlink_err) => bail!( - concat!( - "Failed creating junction and fallback symlink in node_modules folder.\n\n", - "{:#}\n\n{:#}", - ), - junction_err, - symlink_err, - ), - } + Err(symlink_err) + if symlink_err.kind() == std::io::ErrorKind::PermissionDenied => + { + USE_JUNCTIONS.store(true, std::sync::atomic::Ordering::Relaxed); + junction::create(old_path, new_path).map_err(Into::into) } + Err(symlink_err) => Err( + AnyError::from(symlink_err) + .context("Failed creating symlink in node_modules folder"), + ), } } |