summaryrefslogtreecommitdiff
path: root/cli/npm
diff options
context:
space:
mode:
authorNathan Whitaker <17734409+nathanwhit@users.noreply.github.com>2024-08-22 14:55:17 -0700
committerGitHub <noreply@github.com>2024-08-22 21:55:17 +0000
commitf60640267776638d4699fbf05095dc6d1a9016f0 (patch)
treecbe7d284738cf1aed511f3ad3432444ceab573b6 /cli/npm
parentb6475d0f36a0476d95f1a0749f9db33b5aa73ecf (diff)
fix(install): Use relative symlinks in deno install (#25164)
Fixes https://github.com/denoland/deno/issues/25161
Diffstat (limited to 'cli/npm')
-rw-r--r--cli/npm/managed/resolvers/local.rs56
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"),
+ ),
}
}