mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 01:04:43 +01:00
std: add changing cur dir back
There's a good argument to not have this in the std lib but it's more work to remove it than to leave it in, and this branch is already 20,000+ lines changed.
This commit is contained in:
parent
98e9716c08
commit
fa79d34674
12 changed files with 229 additions and 116 deletions
|
|
@ -718,6 +718,7 @@ pub const VTable = struct {
|
|||
lockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!LockedStderr,
|
||||
tryLockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!?LockedStderr,
|
||||
unlockStderr: *const fn (?*anyopaque) void,
|
||||
processSetCurrentDir: *const fn (?*anyopaque, Dir) std.process.SetCurrentDirError!void,
|
||||
|
||||
now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,
|
||||
sleep: *const fn (?*anyopaque, Timeout) SleepError!void,
|
||||
|
|
|
|||
|
|
@ -648,7 +648,7 @@ pub fn init(
|
|||
.main_thread = .{
|
||||
.signal_id = Thread.currentSignalId(),
|
||||
.current_closure = null,
|
||||
.cancel_protection = undefined,
|
||||
.cancel_protection = .unblocked,
|
||||
},
|
||||
.argv0 = options.argv0,
|
||||
.environ = options.environ,
|
||||
|
|
@ -689,7 +689,7 @@ pub const init_single_threaded: Threaded = .{
|
|||
.main_thread = .{
|
||||
.signal_id = undefined,
|
||||
.current_closure = null,
|
||||
.cancel_protection = undefined,
|
||||
.cancel_protection = .unblocked,
|
||||
},
|
||||
.robust_cancel = .disabled,
|
||||
.argv0 = .{},
|
||||
|
|
@ -742,7 +742,7 @@ fn worker(t: *Threaded) void {
|
|||
var thread: Thread = .{
|
||||
.signal_id = Thread.currentSignalId(),
|
||||
.current_closure = null,
|
||||
.cancel_protection = undefined,
|
||||
.cancel_protection = .unblocked,
|
||||
};
|
||||
Thread.current = &thread;
|
||||
|
||||
|
|
@ -844,6 +844,7 @@ pub fn io(t: *Threaded) Io {
|
|||
.lockStderr = lockStderr,
|
||||
.tryLockStderr = tryLockStderr,
|
||||
.unlockStderr = unlockStderr,
|
||||
.processSetCurrentDir = processSetCurrentDir,
|
||||
|
||||
.now = now,
|
||||
.sleep = sleep,
|
||||
|
|
@ -979,6 +980,7 @@ pub fn ioBasic(t: *Threaded) Io {
|
|||
.lockStderr = lockStderr,
|
||||
.tryLockStderr = tryLockStderr,
|
||||
.unlockStderr = unlockStderr,
|
||||
.processSetCurrentDir = processSetCurrentDir,
|
||||
|
||||
.now = now,
|
||||
.sleep = sleep,
|
||||
|
|
@ -7370,6 +7372,7 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex
|
|||
};
|
||||
defer w.CloseHandle(h_file);
|
||||
|
||||
// TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks
|
||||
const wide_slice = try w.GetFinalPathNameByHandle(h_file, .{}, &path_name_w_buf.data);
|
||||
|
||||
const len = std.unicode.calcWtf8Len(wide_slice);
|
||||
|
|
@ -10796,6 +10799,71 @@ fn unlockStderr(userdata: ?*anyopaque) void {
|
|||
std.process.stderr_thread_mutex.unlock();
|
||||
}
|
||||
|
||||
fn processSetCurrentDir(userdata: ?*anyopaque, dir: Dir) std.process.SetCurrentDirError!void {
|
||||
if (native_os == .wasi) return error.OperationUnsupported;
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
const current_thread = Thread.getCurrent(t);
|
||||
|
||||
if (is_windows) {
|
||||
try current_thread.checkCancel();
|
||||
var dir_path_buffer: [windows.PATH_MAX_WIDE]u16 = undefined;
|
||||
// TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks
|
||||
const dir_path = try windows.GetFinalPathNameByHandle(dir.handle, .{}, &dir_path_buffer);
|
||||
const path_len_bytes = std.math.cast(u16, dir_path.len * 2) orelse return error.NameTooLong;
|
||||
try current_thread.checkCancel();
|
||||
var nt_name: windows.UNICODE_STRING = .{
|
||||
.Length = path_len_bytes,
|
||||
.MaximumLength = path_len_bytes,
|
||||
.Buffer = @constCast(dir_path.ptr),
|
||||
};
|
||||
switch (windows.ntdll.RtlSetCurrentDirectory_U(&nt_name)) {
|
||||
.SUCCESS => return,
|
||||
.OBJECT_NAME_INVALID => return error.BadPathName,
|
||||
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
|
||||
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
|
||||
.NO_MEDIA_IN_DEVICE => return error.NoDevice,
|
||||
.INVALID_PARAMETER => |err| return windows.statusBug(err),
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.OBJECT_PATH_SYNTAX_BAD => |err| return windows.statusBug(err),
|
||||
.NOT_A_DIRECTORY => return error.NotDir,
|
||||
else => |status| return windows.unexpectedStatus(status),
|
||||
}
|
||||
}
|
||||
|
||||
if (dir.handle == posix.AT.FDCWD) return;
|
||||
|
||||
try current_thread.beginSyscall();
|
||||
while (true) {
|
||||
switch (posix.errno(posix.system.fchdir(dir.handle))) {
|
||||
.SUCCESS => return current_thread.endSyscall(),
|
||||
.INTR => {
|
||||
try current_thread.checkCancel();
|
||||
continue;
|
||||
},
|
||||
.ACCES => {
|
||||
current_thread.endSyscall();
|
||||
return error.AccessDenied;
|
||||
},
|
||||
.BADF => |err| {
|
||||
current_thread.endSyscall();
|
||||
return errnoBug(err);
|
||||
},
|
||||
.NOTDIR => {
|
||||
current_thread.endSyscall();
|
||||
return error.NotDir;
|
||||
},
|
||||
.IO => {
|
||||
current_thread.endSyscall();
|
||||
return error.FileSystem;
|
||||
},
|
||||
else => |err| {
|
||||
current_thread.endSyscall();
|
||||
return posix.unexpectedErrno(err);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const PosixAddress = extern union {
|
||||
any: posix.sockaddr,
|
||||
in: posix.sockaddr.in,
|
||||
|
|
|
|||
|
|
@ -2939,40 +2939,6 @@ pub fn WriteFile(
|
|||
return bytes_written;
|
||||
}
|
||||
|
||||
pub const SetCurrentDirectoryError = error{
|
||||
NameTooLong,
|
||||
FileNotFound,
|
||||
NotDir,
|
||||
AccessDenied,
|
||||
NoDevice,
|
||||
BadPathName,
|
||||
Unexpected,
|
||||
};
|
||||
|
||||
pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void {
|
||||
const path_len_bytes = math.cast(u16, path_name.len * 2) orelse return error.NameTooLong;
|
||||
|
||||
var nt_name: UNICODE_STRING = .{
|
||||
.Length = path_len_bytes,
|
||||
.MaximumLength = path_len_bytes,
|
||||
.Buffer = @constCast(path_name.ptr),
|
||||
};
|
||||
|
||||
const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);
|
||||
switch (rc) {
|
||||
.SUCCESS => {},
|
||||
.OBJECT_NAME_INVALID => return error.BadPathName,
|
||||
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
|
||||
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
|
||||
.NO_MEDIA_IN_DEVICE => return error.NoDevice,
|
||||
.INVALID_PARAMETER => unreachable,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.OBJECT_PATH_SYNTAX_BAD => unreachable,
|
||||
.NOT_A_DIRECTORY => return error.NotDir,
|
||||
else => return unexpectedStatus(rc),
|
||||
}
|
||||
}
|
||||
|
||||
pub const GetCurrentDirectoryError = error{
|
||||
NameTooLong,
|
||||
Unexpected,
|
||||
|
|
|
|||
|
|
@ -1171,11 +1171,9 @@ pub const ChangeCurDirError = error{
|
|||
/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
|
||||
pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
|
||||
if (native_os == .wasi and !builtin.link_libc) {
|
||||
@compileError("WASI does not support os.chdir");
|
||||
@compileError("unsupported OS");
|
||||
} else if (native_os == .windows) {
|
||||
var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;
|
||||
const len = try windows.wtf8ToWtf16Le(&wtf16_dir_path, dir_path);
|
||||
return chdirW(wtf16_dir_path[0..len]);
|
||||
@compileError("unsupported OS");
|
||||
} else {
|
||||
const dir_path_c = try toPosixPath(dir_path);
|
||||
return chdirZ(&dir_path_c);
|
||||
|
|
@ -1188,12 +1186,9 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
|
|||
/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
|
||||
pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
|
||||
if (native_os == .windows) {
|
||||
const dir_path_span = mem.span(dir_path);
|
||||
var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;
|
||||
const len = try windows.wtf8ToWtf16Le(&wtf16_dir_path, dir_path_span);
|
||||
return chdirW(wtf16_dir_path[0..len]);
|
||||
@compileError("unsupported OS");
|
||||
} else if (native_os == .wasi and !builtin.link_libc) {
|
||||
return chdir(mem.span(dir_path));
|
||||
@compileError("unsupported OS");
|
||||
}
|
||||
switch (errno(system.chdir(dir_path))) {
|
||||
.SUCCESS => return,
|
||||
|
|
@ -1210,14 +1205,6 @@ pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
|
|||
}
|
||||
}
|
||||
|
||||
/// Windows-only. Same as `chdir` except the parameter is WTF16 LE encoded.
|
||||
pub fn chdirW(dir_path: []const u16) ChangeCurDirError!void {
|
||||
windows.SetCurrentDirectory(dir_path) catch |err| switch (err) {
|
||||
error.NoDevice => return error.FileSystem,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
pub const FchdirError = error{
|
||||
AccessDenied,
|
||||
NotDir,
|
||||
|
|
|
|||
|
|
@ -2304,3 +2304,28 @@ pub fn exit(status: u8) noreturn {
|
|||
else => posix.system.exit(status),
|
||||
}
|
||||
}
|
||||
|
||||
pub const SetCurrentDirError = error{
|
||||
AccessDenied,
|
||||
BadPathName,
|
||||
FileNotFound,
|
||||
FileSystem,
|
||||
NameTooLong,
|
||||
NoDevice,
|
||||
NotDir,
|
||||
OperationUnsupported,
|
||||
UnrecognizedVolume,
|
||||
} || Io.Cancelable || Io.UnexpectedError;
|
||||
|
||||
/// Changes the current working directory to the open directory handle.
|
||||
/// Corresponds to "fchdir" in libc.
|
||||
///
|
||||
/// This modifies global process state and can have surprising effects in
|
||||
/// multithreaded applications. Most applications and especially libraries
|
||||
/// should not call this function as a general rule, however it can have use
|
||||
/// cases in, for example, implementing a shell, or child process execution.
|
||||
///
|
||||
/// Calling this function makes code less portable and less reusable.
|
||||
pub fn setCurrentDir(io: Io, dir: Io.Dir) !void {
|
||||
return io.vtable.processSetCurrentDir(io.userdata, dir);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -629,6 +629,7 @@ pub const TmpDir = struct {
|
|||
};
|
||||
|
||||
pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir {
|
||||
comptime assert(builtin.is_test);
|
||||
var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
|
||||
std.crypto.random.bytes(&random_bytes);
|
||||
var sub_path: [TmpDir.sub_path_len]u8 = undefined;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const path_max = std.fs.max_path_bytes;
|
||||
|
||||
pub fn main() !void {
|
||||
|
|
@ -9,13 +13,17 @@ pub fn main() !void {
|
|||
return;
|
||||
}
|
||||
|
||||
var Allocator = std.heap.DebugAllocator(.{}){};
|
||||
const a = Allocator.allocator();
|
||||
defer std.debug.assert(Allocator.deinit() == .ok);
|
||||
var debug_allocator: std.heap.DebugAllocator(.{}) = .{};
|
||||
defer assert(debug_allocator.deinit() == .ok);
|
||||
const gpa = debug_allocator.allocator();
|
||||
|
||||
var threaded: std.Io.Threaded = .init(gpa, .{});
|
||||
defer threaded.deinit();
|
||||
const io = threaded.io();
|
||||
|
||||
try test_chdir_self();
|
||||
try test_chdir_absolute();
|
||||
try test_chdir_relative(a);
|
||||
try test_chdir_relative(gpa, io);
|
||||
}
|
||||
|
||||
// get current working directory and expect it to match given path
|
||||
|
|
@ -46,20 +54,20 @@ fn test_chdir_absolute() !void {
|
|||
try expect_cwd(parent);
|
||||
}
|
||||
|
||||
fn test_chdir_relative(a: std.mem.Allocator) !void {
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
fn test_chdir_relative(gpa: Allocator, io: Io) !void {
|
||||
var tmp = tmpDir(io, .{});
|
||||
defer tmp.cleanup(io);
|
||||
|
||||
// Use the tmpDir parent_dir as the "base" for the test. Then cd into the child
|
||||
try tmp.parent_dir.setAsCwd();
|
||||
try std.process.setCurrentDir(io, tmp.parent_dir);
|
||||
|
||||
// Capture base working directory path, to build expected full path
|
||||
var base_cwd_buf: [path_max]u8 = undefined;
|
||||
const base_cwd = try std.posix.getcwd(base_cwd_buf[0..]);
|
||||
|
||||
const relative_dir_name = &tmp.sub_path;
|
||||
const expected_path = try std.fs.path.resolve(a, &.{ base_cwd, relative_dir_name });
|
||||
defer a.free(expected_path);
|
||||
const expected_path = try std.fs.path.resolve(gpa, &.{ base_cwd, relative_dir_name });
|
||||
defer gpa.free(expected_path);
|
||||
|
||||
// change current working directory to new test directory
|
||||
try std.posix.chdir(relative_dir_name);
|
||||
|
|
@ -68,8 +76,46 @@ fn test_chdir_relative(a: std.mem.Allocator) !void {
|
|||
const new_cwd = try std.posix.getcwd(new_cwd_buf[0..]);
|
||||
|
||||
// On Windows, fs.path.resolve returns an uppercase drive letter, but the drive letter returned by getcwd may be lowercase
|
||||
const resolved_cwd = try std.fs.path.resolve(a, &.{new_cwd});
|
||||
defer a.free(resolved_cwd);
|
||||
const resolved_cwd = try std.fs.path.resolve(gpa, &.{new_cwd});
|
||||
defer gpa.free(resolved_cwd);
|
||||
|
||||
try std.testing.expectEqualStrings(expected_path, resolved_cwd);
|
||||
}
|
||||
|
||||
pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir {
|
||||
var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
|
||||
std.crypto.random.bytes(&random_bytes);
|
||||
var sub_path: [TmpDir.sub_path_len]u8 = undefined;
|
||||
_ = std.fs.base64_encoder.encode(&sub_path, &random_bytes);
|
||||
|
||||
const cwd = Io.Dir.cwd();
|
||||
var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch
|
||||
@panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir");
|
||||
defer cache_dir.close(io);
|
||||
const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch
|
||||
@panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir");
|
||||
const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch
|
||||
@panic("unable to make tmp dir for testing: unable to make and open the tmp dir");
|
||||
|
||||
return .{
|
||||
.dir = dir,
|
||||
.parent_dir = parent_dir,
|
||||
.sub_path = sub_path,
|
||||
};
|
||||
}
|
||||
|
||||
pub const TmpDir = struct {
|
||||
dir: Io.Dir,
|
||||
parent_dir: Io.Dir,
|
||||
sub_path: [sub_path_len]u8,
|
||||
|
||||
const random_bytes_count = 12;
|
||||
const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count);
|
||||
|
||||
pub fn cleanup(self: *TmpDir, io: Io) void {
|
||||
self.dir.close(io);
|
||||
self.parent_dir.deleteTree(io, &self.sub_path) catch {};
|
||||
self.parent_dir.close(io);
|
||||
self.* = undefined;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,21 +14,21 @@ pub fn main() !void {
|
|||
const gpa = debug_allocator.allocator();
|
||||
defer std.debug.assert(debug_allocator.deinit() == .ok);
|
||||
|
||||
const io = std.Io.Threaded.global_single_threaded.ioBasic();
|
||||
var threaded: std.Io.Threaded = .init(gpa, .{});
|
||||
defer threaded.deinit();
|
||||
const io = threaded.io();
|
||||
|
||||
// TODO this API isn't supposed to be used outside of unit testing. make it compilation error if used
|
||||
// outside of unit testing.
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var tmp = tmpDir(io, .{});
|
||||
defer tmp.cleanup(io);
|
||||
|
||||
// Want to test relative paths, so cd into the tmpdir for these tests
|
||||
try tmp.dir.setAsCwd();
|
||||
try std.process.setCurrentDir(io, tmp.dir);
|
||||
|
||||
try test_symlink(gpa, io, tmp);
|
||||
try test_link(io, tmp);
|
||||
}
|
||||
|
||||
fn test_symlink(gpa: Allocator, io: Io, tmp: std.testing.TmpDir) !void {
|
||||
fn test_symlink(gpa: Allocator, io: Io, tmp: TmpDir) !void {
|
||||
const target_name = "symlink-target";
|
||||
const symlink_name = "symlinker";
|
||||
|
||||
|
|
@ -47,32 +47,15 @@ fn test_symlink(gpa: Allocator, io: Io, tmp: std.testing.TmpDir) !void {
|
|||
else => return err,
|
||||
};
|
||||
} else {
|
||||
try std.posix.symlink(target_name, symlink_name);
|
||||
try Io.Dir.cwd().symLink(io, target_name, symlink_name, .{});
|
||||
}
|
||||
|
||||
var buffer: [std.fs.max_path_bytes]u8 = undefined;
|
||||
const given = try std.posix.readlink(symlink_name, buffer[0..]);
|
||||
const given = buffer[0..try Io.Dir.cwd().readLink(io, symlink_name, &buffer)];
|
||||
try std.testing.expectEqualStrings(target_name, given);
|
||||
}
|
||||
|
||||
fn getLinkInfo(fd: std.posix.fd_t) !struct { std.posix.ino_t, std.posix.nlink_t } {
|
||||
if (builtin.target.os.tag == .linux) {
|
||||
const stx = try std.os.linux.wrapped.statx(
|
||||
fd,
|
||||
"",
|
||||
std.posix.AT.EMPTY_PATH,
|
||||
.{ .INO = true, .NLINK = true },
|
||||
);
|
||||
std.debug.assert(stx.mask.INO);
|
||||
std.debug.assert(stx.mask.NLINK);
|
||||
return .{ stx.ino, stx.nlink };
|
||||
}
|
||||
|
||||
const st = try std.posix.fstat(fd);
|
||||
return .{ st.ino, st.nlink };
|
||||
}
|
||||
|
||||
fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
|
||||
fn test_link(io: Io, tmp: TmpDir) !void {
|
||||
switch (builtin.target.os.tag) {
|
||||
.linux, .illumos => {},
|
||||
else => return,
|
||||
|
|
@ -84,7 +67,7 @@ fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
|
|||
try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" });
|
||||
|
||||
// Test 1: create the relative link from inside tmp
|
||||
try std.posix.link(target_name, link_name);
|
||||
try Io.Dir.hardLink(.cwd(), target_name, .cwd(), link_name, io, .{});
|
||||
|
||||
// Verify
|
||||
const efd = try tmp.dir.openFile(io, target_name, .{});
|
||||
|
|
@ -94,16 +77,54 @@ fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
|
|||
defer nfd.close(io);
|
||||
|
||||
{
|
||||
const eino, _ = try getLinkInfo(efd.handle);
|
||||
const nino, const nlink = try getLinkInfo(nfd.handle);
|
||||
try std.testing.expectEqual(eino, nino);
|
||||
try std.testing.expectEqual(@as(std.posix.nlink_t, 2), nlink);
|
||||
const e_stat = try efd.stat(io);
|
||||
const n_stat = try nfd.stat(io);
|
||||
try std.testing.expectEqual(e_stat.inode, n_stat.inode);
|
||||
try std.testing.expectEqual(2, n_stat.nlink);
|
||||
}
|
||||
|
||||
// Test 2: Remove the link and see the stats update
|
||||
try std.posix.unlink(link_name);
|
||||
try Io.Dir.cwd().deleteFile(io, link_name);
|
||||
{
|
||||
_, const elink = try getLinkInfo(efd.handle);
|
||||
try std.testing.expectEqual(@as(std.posix.nlink_t, 1), elink);
|
||||
const e_stat = try efd.stat(io);
|
||||
try std.testing.expectEqual(1, e_stat.nlink);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir {
|
||||
var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
|
||||
std.crypto.random.bytes(&random_bytes);
|
||||
var sub_path: [TmpDir.sub_path_len]u8 = undefined;
|
||||
_ = std.fs.base64_encoder.encode(&sub_path, &random_bytes);
|
||||
|
||||
const cwd = Io.Dir.cwd();
|
||||
var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch
|
||||
@panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir");
|
||||
defer cache_dir.close(io);
|
||||
const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch
|
||||
@panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir");
|
||||
const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch
|
||||
@panic("unable to make tmp dir for testing: unable to make and open the tmp dir");
|
||||
|
||||
return .{
|
||||
.dir = dir,
|
||||
.parent_dir = parent_dir,
|
||||
.sub_path = sub_path,
|
||||
};
|
||||
}
|
||||
|
||||
pub const TmpDir = struct {
|
||||
dir: Io.Dir,
|
||||
parent_dir: Io.Dir,
|
||||
sub_path: [sub_path_len]u8,
|
||||
|
||||
const random_bytes_count = 12;
|
||||
const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count);
|
||||
|
||||
pub fn cleanup(self: *TmpDir, io: Io) void {
|
||||
self.dir.close(io);
|
||||
self.parent_dir.deleteTree(io, &self.sub_path) catch {};
|
||||
self.parent_dir.close(io);
|
||||
self.* = undefined;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ pub fn main() anyerror!void {
|
|||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
|
||||
try tmp.dir.setAsCwd();
|
||||
defer tmp.parent_dir.setAsCwd() catch {};
|
||||
try std.process.setCurrentDir(io, tmp.dir);
|
||||
defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
|
||||
|
||||
// `child_exe_path_orig` might be relative; make it relative to our new cwd.
|
||||
const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig });
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ pub fn main() anyerror!void {
|
|||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
|
||||
try tmp.dir.setAsCwd();
|
||||
defer tmp.parent_dir.setAsCwd() catch {};
|
||||
try std.process.setCurrentDir(io, tmp.dir);
|
||||
defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
|
||||
|
||||
// `child_exe_path_orig` might be relative; make it relative to our new cwd.
|
||||
const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig });
|
||||
|
|
|
|||
|
|
@ -127,8 +127,8 @@ pub fn main() anyerror!void {
|
|||
try testExecError(error.FileNotFound, gpa, "goodbye");
|
||||
|
||||
// Now let's set the tmp dir as the cwd and set the path only include the "something" sub dir
|
||||
try tmp.dir.setAsCwd();
|
||||
defer tmp.parent_dir.setAsCwd() catch {};
|
||||
try std.process.setCurrentDir(io, tmp.dir);
|
||||
defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
|
||||
const something_subdir_abs_path = try std.mem.concatWithSentinel(gpa, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0);
|
||||
defer gpa.free(something_subdir_abs_path);
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ pub fn main() anyerror!void {
|
|||
defer subdir_cwd.close(io);
|
||||
|
||||
try renameExe(tmp.dir, "something/goodbye.exe", "hello.exe");
|
||||
try subdir_cwd.setAsCwd();
|
||||
try std.process.setCurrentDir(io, subdir_cwd);
|
||||
|
||||
// clear the PATH again
|
||||
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ const Dir = std.Io.Dir;
|
|||
const mem = std.mem;
|
||||
const process = std.process;
|
||||
const assert = std.debug.assert;
|
||||
const tmpDir = std.testing.tmpDir;
|
||||
const fatal = std.process.fatal;
|
||||
const info = std.log.info;
|
||||
|
||||
|
|
@ -111,15 +110,14 @@ pub fn main() anyerror!void {
|
|||
const os_ver: OsVer = @enumFromInt(version.major);
|
||||
info("found SDK deployment target macOS {f} aka '{t}'", .{ version, os_ver });
|
||||
|
||||
var tmp = tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
const tmp_dir: Io.Dir = .cwd();
|
||||
|
||||
for (&[_]Arch{ .aarch64, .x86_64 }) |arch| {
|
||||
const target: Target = .{
|
||||
.arch = arch,
|
||||
.os_ver = os_ver,
|
||||
};
|
||||
try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp);
|
||||
try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,11 +128,11 @@ fn fetchTarget(
|
|||
sysroot: []const u8,
|
||||
target: Target,
|
||||
ver: Version,
|
||||
tmp: std.testing.TmpDir,
|
||||
tmp_dir: Io.Dir,
|
||||
) !void {
|
||||
const tmp_filename = "macos-headers";
|
||||
const headers_list_filename = "macos-headers.o.d";
|
||||
const tmp_path = try tmp.dir.realPathFileAlloc(io, ".", arena);
|
||||
const tmp_path = try tmp_dir.realPathFileAlloc(io, ".", arena);
|
||||
const tmp_file_path = try Dir.path.join(arena, &[_][]const u8{ tmp_path, tmp_filename });
|
||||
const headers_list_path = try Dir.path.join(arena, &[_][]const u8{ tmp_path, headers_list_filename });
|
||||
|
||||
|
|
@ -173,7 +171,7 @@ fn fetchTarget(
|
|||
}
|
||||
|
||||
// Read in the contents of `macos-headers.o.d`
|
||||
const headers_list_file = try tmp.dir.openFile(io, headers_list_filename, .{});
|
||||
const headers_list_file = try tmp_dir.openFile(io, headers_list_filename, .{});
|
||||
defer headers_list_file.close(io);
|
||||
|
||||
var headers_dir = Dir.cwd().openDir(io, headers_source_prefix, .{}) catch |err| switch (err) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue