diff --git a/Cargo.lock b/Cargo.lock
index 398fdeee27..e09eabcf9d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1503,6 +1503,7 @@ dependencies = [
"indexmap 2.2.6",
"insta",
"itertools 0.12.1",
+ "junction",
"litparser",
"litparser-derive",
"log",
@@ -2515,6 +2516,16 @@ dependencies = [
"simple_asn1",
]
+[[package]]
+name = "junction"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72bbdfd737a243da3dfc1f99ee8d6e166480f17ab4ac84d7c34aacd73fc7bd16"
+dependencies = [
+ "scopeguard",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "keccak"
version = "0.1.5"
diff --git a/tsparser/Cargo.toml b/tsparser/Cargo.toml
index 9453f5598c..8e163b4693 100644
--- a/tsparser/Cargo.toml
+++ b/tsparser/Cargo.toml
@@ -41,6 +41,7 @@ serde_yaml = "0.9.32"
symlink = "0.1.0"
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
+junction = "1.2.0"
[build-dependencies]
prost-build = { version = "0.12.1" }
diff --git a/tsparser/src/builder/package_mgmt.rs b/tsparser/src/builder/package_mgmt.rs
index 22ad7d4759..4c93c2255b 100644
--- a/tsparser/src/builder/package_mgmt.rs
+++ b/tsparser/src/builder/package_mgmt.rs
@@ -4,6 +4,7 @@ use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use duct::cmd;
use serde::Deserialize;
+use std::io;
use crate::builder::compile::CmdSpec;
@@ -279,22 +280,20 @@ fn symlink_encore_dev(app_root: &Path, encore_dev_path: &Path) -> Result<()> {
let node_mod_dst = node_modules.join("encore.dev");
// If the node_modules directory exists, symlink the encore.dev package.
- if let Ok(meta) = node_mod_dst.symlink_metadata() {
- // Is this a symlink?
- if meta.is_symlink() {
- // If the symlink is already pointing to our desired target, we're done.
- if let Ok(target) = std::fs::read_link(&node_mod_dst) {
- if target == encore_dev_path {
- log::info!("encore.dev symlink already points to the local runtime, skipping.");
- return Ok(());
- }
+ if let Ok(target) = read_symlink(&node_mod_dst) {
+ if let Some(target) = target {
+ if target == encore_dev_path {
+ log::info!("encore.dev symlink already points to the local runtime, skipping.");
+ return Ok(());
}
// It's a symlink pointing elsewhere. Remove it.
- symlink::remove_symlink_auto(&node_mod_dst).with_context(|| {
+ delete_symlink(&node_mod_dst).with_context(|| {
format!("remove existing encore.dev symlink at {:?}", node_mod_dst)
})?;
- } else {
+ }
+
+ if node_mod_dst.exists() {
// It's not a symlink. Remove the directory so we can add a symlink.
std::fs::remove_dir_all(&node_mod_dst).with_context(|| {
format!("remove existing encore.dev directory at {:?}", node_mod_dst)
@@ -304,9 +303,58 @@ fn symlink_encore_dev(app_root: &Path, encore_dev_path: &Path) -> Result<()> {
// Create the symlink if the node_modules directory exists.
if node_modules.exists() {
- symlink::symlink_dir(encore_dev_path, &node_mod_dst)
+ create_symlink(encore_dev_path, &node_mod_dst)
.with_context(|| format!("symlink encore.dev directory at {:?}", node_mod_dst))?;
}
-
Ok(())
}
+
+#[cfg(not(windows))]
+fn create_symlink(src: &Path, dst: &Path) -> io::Result<()> {
+ symlink::symlink_dir(src, dst)
+}
+
+#[cfg(windows)]
+fn create_symlink(src: &Path, dst: &Path) -> io::Result<()> {
+ symlink::symlink_dir(src, dst).or_else(|_| junction::create(src, &dst))
+}
+
+#[cfg(not(windows))]
+fn read_symlink(src: &Path) -> io::Result