summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/npm/managed/resolvers/local.rs56
-rw-r--r--cli/util/fs.rs2
-rw-r--r--tests/specs/install/move_after_install/__test__.jsonc28
-rw-r--r--tests/specs/install/move_after_install/test-project/main.mjs4
-rw-r--r--tests/specs/install/move_after_install/test-project/package.json5
5 files changed, 70 insertions, 25 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"),
+ ),
}
}
diff --git a/cli/util/fs.rs b/cli/util/fs.rs
index c414abd59..145f9c83b 100644
--- a/cli/util/fs.rs
+++ b/cli/util/fs.rs
@@ -509,7 +509,7 @@ pub fn hard_link_dir_recursive(from: &Path, to: &Path) -> Result<(), AnyError> {
Ok(())
}
-pub fn symlink_dir(oldpath: &Path, newpath: &Path) -> Result<(), AnyError> {
+pub fn symlink_dir(oldpath: &Path, newpath: &Path) -> Result<(), Error> {
let err_mapper = |err: Error| {
Error::new(
err.kind(),
diff --git a/tests/specs/install/move_after_install/__test__.jsonc b/tests/specs/install/move_after_install/__test__.jsonc
new file mode 100644
index 000000000..1699e9f6f
--- /dev/null
+++ b/tests/specs/install/move_after_install/__test__.jsonc
@@ -0,0 +1,28 @@
+{
+ "tempDir": true,
+ "envs": {
+ "DENO_FUTURE": "1"
+ },
+ "steps": [
+ {
+ "cwd": "./test-project",
+ "args": "install",
+ "output": "[WILDCARD]"
+ },
+ {
+ "cwd": "./test-project",
+ "args": "run -A main.mjs",
+ "output": "5\n"
+ },
+ {
+ "commandName": "mv",
+ "args": "test-project test-project-moved",
+ "output": ""
+ },
+ {
+ "cwd": "./test-project-moved",
+ "args": "run -A main.mjs",
+ "output": "5\n"
+ }
+ ]
+}
diff --git a/tests/specs/install/move_after_install/test-project/main.mjs b/tests/specs/install/move_after_install/test-project/main.mjs
new file mode 100644
index 000000000..1beed6ef4
--- /dev/null
+++ b/tests/specs/install/move_after_install/test-project/main.mjs
@@ -0,0 +1,4 @@
+import { getValue, setValue } from "@denotest/esm-basic";
+
+setValue(5);
+console.log(getValue());
diff --git a/tests/specs/install/move_after_install/test-project/package.json b/tests/specs/install/move_after_install/test-project/package.json
new file mode 100644
index 000000000..54ca824d6
--- /dev/null
+++ b/tests/specs/install/move_after_install/test-project/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "@denotest/esm-basic": "*"
+ }
+}