Skip to content

Commit c3ae924

Browse files
committed
Turbopack: Create junction points instead of symlinks on Windows
1 parent 7fb2aa9 commit c3ae924

File tree

7 files changed

+203
-82
lines changed

7 files changed

+203
-82
lines changed

packages/next/src/build/utils.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,9 +1274,29 @@ export async function copyTracedFiles(
12741274
if (symlink) {
12751275
try {
12761276
await fs.symlink(symlink, fileOutputPath)
1277-
} catch (e: any) {
1278-
if (e.code !== 'EEXIST') {
1279-
throw e
1277+
} catch (err: any) {
1278+
// Windows doesn't support creating symlinks without elevated privileges, unless
1279+
// "Developer Mode" is turned on. If we failed to crate a symlink due to EPERM, try
1280+
// creating a junction point instead.
1281+
//
1282+
// Ideally we'd just preserve the input file type (junction point or symlink), but
1283+
// there's no API in node.js to differentiate between a junction point and a symlink,
1284+
// so we just try making a symlink first. Symlinks are preferred because they support
1285+
// relative paths and non-directory (file) targets.
1286+
if (
1287+
process.platform === 'win32' &&
1288+
err.code === 'EPERM' &&
1289+
path.isAbsolute(symlink)
1290+
) {
1291+
try {
1292+
await fs.symlink(symlink, fileOutputPath, 'junction')
1293+
} catch (junctionErr: any) {
1294+
if (junctionErr.code !== 'EEXIST') {
1295+
throw junctionErr
1296+
}
1297+
}
1298+
} else if (err.code !== 'EEXIST') {
1299+
throw err
12801300
}
12811301
}
12821302
} else {

turbopack/crates/turbo-tasks-fs/src/attach.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,15 @@ impl FileSystem for AttachedFileSystem {
125125
}
126126

127127
#[turbo_tasks::function(fs)]
128-
async fn write_link(
128+
async fn write_symbolic_link_dir(
129129
self: Vc<Self>,
130130
path: FileSystemPath,
131131
target: Vc<LinkContent>,
132132
) -> Result<Vc<()>> {
133-
Ok(self.get_inner_fs_path(path).await?.write_link(target))
133+
Ok(self
134+
.get_inner_fs_path(path)
135+
.await?
136+
.write_symbolic_link_dir(target))
134137
}
135138

136139
#[turbo_tasks::function]

turbopack/crates/turbo-tasks-fs/src/embed/fs.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,11 @@ impl FileSystem for EmbeddedFileSystem {
7575
}
7676

7777
#[turbo_tasks::function]
78-
fn write_link(&self, _path: FileSystemPath, _target: Vc<LinkContent>) -> Result<Vc<()>> {
78+
fn write_symbolic_link_dir(
79+
&self,
80+
_path: FileSystemPath,
81+
_target: Vc<LinkContent>,
82+
) -> Result<Vc<()>> {
7983
bail!("Writing is not possible to the embedded filesystem")
8084
}
8185

0 commit comments

Comments
 (0)