Skip to content

Commit

Permalink
Fix Sys.rename under Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
vouillon committed Jan 27, 2025
1 parent f9ad3ac commit dd56ae9
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 29 deletions.
44 changes: 20 additions & 24 deletions runtime/js/fs_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,33 +144,29 @@ if (globalThis.process?.platform === "win32") {
try {
var target = this.nm(n);
var source = this.nm(o);
var target_stats = this.fs.existsSync(target)
? this.fs.statSync(target)
: null;
var source_stats = this.fs.existsSync(source)
? this.fs.statSync(source)
: null;
var target_stats, source_stats;
if (
source_stats &&
source_stats.isDirectory() &&
target_stats &&
!target_stats.isDirectory()
(target_stats = this.fs.statSync(target, { throwIfNoEntry: 0 })) &&
(source_stats = this.fs.statSync(source, { throwIfNoEntry: 0 })) &&
source_stats.isDirectory()
) {
var err = new Error("rename");
err.code = 26;
err.path = n;
this.raise_nodejs_error(err, raise_unix);
if (target_stats.isDirectory()) {
if (!target.startsWith(source))
try {
this.fs.rmdirSync(target);
} catch {}
} else {
var err = new Error(
`ENOTDIR: not a directory, rename '${source}' -> '${target}'`,
);
throw Object.assign(err, {
errno: -20,
code: "ENOTDIR",
syscall: "rename",
path: target,
});
}
}
if (
source_stats &&
source_stats.isDirectory() &&
target_stats &&
target_stats.isDirectory() &&
!target.startsWith(source)
)
try {
this.fs.rmdirSync(target);
} catch {}
this.fs.renameSync(this.nm(o), this.nm(n));
} catch (err) {
this.raise_nodejs_error(err, raise_unix);
Expand Down
35 changes: 30 additions & 5 deletions runtime/wasm/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
return h ^ s.length;
}

const on_windows = isNode && process.platform === "win32";
const bindings = {
jstag:
WebAssembly.JSTag ||
Expand Down Expand Up @@ -398,7 +399,7 @@
channel_list,
exit: (n) => isNode && process.exit(n),
argv: () => (isNode ? process.argv.slice(1) : ["a.out"]),
on_windows: () => isNode && process.platform === "win32",
on_windows: () => on_windows,
getenv: (n) => (isNode ? process.env[n] : null),
system: (c) => {
var res = require("node:child_process").spawnSync(c, {
Expand All @@ -417,7 +418,32 @@
readdir: (p) => fs.readdirSync(p),
file_exists: (p) => +fs.existsSync(p),
is_directory: (p) => +fs.lstatSync(p).isDirectory(),
rename: (o, n) => fs.renameSync(o, n),
rename: (o, n) => {
var n_stat;
if (
on_windows &&
(n_stat = fs.statSync(n, { throwIfNoEntry: 0 })) &&
fs.statSync(o, { throwIfNoEntry: 0 })?.isDirectory()
) {
if (n_stat.isDirectory()) {
if (!n.startsWith(o))
try {
fs.rmdirSync(target);
} catch {}
} else {
var e = new Error(
`ENOTDIR: not a directory, rename '${o}' -> '${n}'`,
);
throw Object.assign(e, {
errno: -20,
code: "ENOTDIR",
syscall: "rename",
path: n,
});
}
}
fs.renameSync(o, n);
},
throw: (e) => {
throw e;
},
Expand Down Expand Up @@ -529,9 +555,8 @@

start_fiber = make_promising(caml_start_fiber);
var _initialize = make_promising(_initialize);
var process = globalThis.process;
if (process && process.on) {
process.on("uncaughtException", (err, origin) =>
if (globalThis.process && globalThis.process.on) {
globalThis.process.on("uncaughtException", (err, origin) =>
caml_handle_uncaught_exception(err),
);
} else if (globalThis.addEventListener) {
Expand Down

0 comments on commit dd56ae9

Please sign in to comment.