mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Fix(bundler): allow generating exe file in nested path. (#4226)
* Fix(bundler): allow generating binary file in nested path. Close: #4195 * Add read flag for fd. * refactor
This commit is contained in:
@@ -116,7 +116,8 @@ pub fn moveFileZWithHandle(from_handle: std.os.fd_t, from_dir: std.os.fd_t, file
|
||||
std.os.renameatZ(from_dir, filename, to_dir, destination) catch |err| {
|
||||
switch (err) {
|
||||
error.RenameAcrossMountPoints => {
|
||||
try moveFileZSlowWithHandle(from_handle, to_dir, destination);
|
||||
try copyFileZSlowWithHandle(from_handle, to_dir, destination);
|
||||
std.os.unlinkatZ(from_dir, filename, 0) catch {};
|
||||
},
|
||||
else => {
|
||||
return err;
|
||||
@@ -129,10 +130,12 @@ pub fn moveFileZWithHandle(from_handle: std.os.fd_t, from_dir: std.os.fd_t, file
|
||||
// macOS & BSDs will be slow because
|
||||
pub fn moveFileZSlow(from_dir: std.os.fd_t, filename: [*:0]const u8, to_dir: std.os.fd_t, destination: [*:0]const u8) !void {
|
||||
const in_handle = try std.os.openatZ(from_dir, filename, std.os.O.RDONLY | std.os.O.CLOEXEC, 0o600);
|
||||
try moveFileZSlowWithHandle(in_handle, to_dir, destination);
|
||||
defer std.os.close(in_handle);
|
||||
try copyFileZSlowWithHandle(in_handle, to_dir, destination);
|
||||
std.os.unlinkatZ(from_dir, filename, 0) catch {};
|
||||
}
|
||||
|
||||
pub fn moveFileZSlowWithHandle(in_handle: std.os.fd_t, to_dir: std.os.fd_t, destination: [*:0]const u8) !void {
|
||||
pub fn copyFileZSlowWithHandle(in_handle: std.os.fd_t, to_dir: std.os.fd_t, destination: [*:0]const u8) !void {
|
||||
const stat_ = try std.os.fstat(in_handle);
|
||||
// delete if exists, don't care if it fails. it may fail due to the file not existing
|
||||
// delete here because we run into weird truncation issues if we do not
|
||||
|
||||
@@ -257,7 +257,7 @@ pub const StandaloneModuleGraph = struct {
|
||||
// if we're on a mac, use clonefile() if we can
|
||||
// failure is okay, clonefile is just a fast path.
|
||||
if (Syscall.clonefile(self_exeZ, zname) == .result) {
|
||||
switch (Syscall.open(zname, std.os.O.WRONLY | std.os.O.CLOEXEC, 0)) {
|
||||
switch (Syscall.open(zname, std.os.O.RDWR | std.os.O.CLOEXEC, 0)) {
|
||||
.result => |res| break :brk res,
|
||||
.err => {},
|
||||
}
|
||||
@@ -269,7 +269,7 @@ pub const StandaloneModuleGraph = struct {
|
||||
const fd = brk2: {
|
||||
var tried_changing_abs_dir = false;
|
||||
for (0..3) |retry| {
|
||||
switch (Syscall.open(zname, std.os.O.CLOEXEC | std.os.O.WRONLY | std.os.O.CREAT, 0)) {
|
||||
switch (Syscall.open(zname, std.os.O.CLOEXEC | std.os.O.RDWR | std.os.O.CREAT, 0)) {
|
||||
.result => |res| break :brk2 res,
|
||||
.err => |err| {
|
||||
if (retry < 2) {
|
||||
@@ -439,7 +439,7 @@ pub const StandaloneModuleGraph = struct {
|
||||
std.fs.cwd().fd,
|
||||
&(try std.os.toPosixPath(temp_location)),
|
||||
root_dir.dir.fd,
|
||||
&(try std.os.toPosixPath(outfile)),
|
||||
&(try std.os.toPosixPath(std.fs.path.basename(outfile))),
|
||||
) catch |err| {
|
||||
if (err == error.IsDir) {
|
||||
Output.prettyErrorln("<r><red>error<r><d>:<r> {} is a directory. Please choose a different --outfile or delete the directory", .{bun.fmt.quote(outfile)});
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { bunEnv, bunExe } from "harness";
|
||||
import path from "path";
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import fs from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
|
||||
describe("bun build", () => {
|
||||
test("warnings dont return exit code 1", () => {
|
||||
@@ -13,4 +15,41 @@ describe("bun build", () => {
|
||||
'warn: "key" prop before a {...spread} is deprecated in JSX. Falling back to classic runtime.',
|
||||
);
|
||||
});
|
||||
|
||||
test("generating a standalone binary in nested path, issue #4195", () => {
|
||||
function testCompile(outfile: string) {
|
||||
const { exitCode } = Bun.spawnSync({
|
||||
cmd: [
|
||||
bunExe(),
|
||||
"build",
|
||||
path.join(import.meta.dir, "./fixtures/trivial/index.js"),
|
||||
"--compile",
|
||||
"--outfile",
|
||||
outfile,
|
||||
],
|
||||
env: bunEnv,
|
||||
});
|
||||
expect(exitCode).toBe(0);
|
||||
}
|
||||
function testExec(outfile: string) {
|
||||
const { exitCode } = Bun.spawnSync({
|
||||
cmd: [outfile],
|
||||
});
|
||||
expect(exitCode).toBe(0);
|
||||
}
|
||||
{
|
||||
const baseDir = `${tmpdir()}/bun-build-outfile-${Date.now()}`;
|
||||
const outfile = path.join(baseDir, "index.exe");
|
||||
testCompile(outfile);
|
||||
testExec(outfile);
|
||||
fs.rmSync(baseDir, { recursive: true, force: true });
|
||||
}
|
||||
{
|
||||
const baseDir = `${tmpdir()}/bun-build-outfile2-${Date.now()}`;
|
||||
const outfile = path.join(baseDir, "b/u/n", "index.exe");
|
||||
testCompile(outfile);
|
||||
testExec(outfile);
|
||||
fs.rmSync(baseDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user