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:
Ai Hoshino
2023-08-22 09:22:37 +08:00
committed by GitHub
parent f629365cb7
commit a61953bbfd
3 changed files with 49 additions and 7 deletions

View File

@@ -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

View File

@@ -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)});

View File

@@ -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 });
}
});
});