diff options
| author | Robert Günzler <r@gnzler.io> | 2026-09-18 04:00:18 +0200 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2026-09-22 22:37:51 +0200 |
| commit | 5bc242742e1225c7c3b87a31c2c2a3998ac18685 (patch) | |
| tree | baae923037b49ba31bb0a15ece2eec4bea13ab25 /src/FileSwapper.zig | |
| parent | c677e8873e0eae790a1b8b07844a10efa9f63a1e (diff) | |
| download | site-5bc242742e1225c7c3b87a31c2c2a3998ac18685.tar.gz | |
v2
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to 'src/FileSwapper.zig')
| -rw-r--r-- | src/FileSwapper.zig | 101 |
1 files changed, 0 insertions, 101 deletions
diff --git a/src/FileSwapper.zig b/src/FileSwapper.zig deleted file mode 100644 index 13bafe4..0000000 --- a/src/FileSwapper.zig +++ /dev/null @@ -1,101 +0,0 @@ -const std = @import("std"); - -const FileSwapper = @This(); -const log = std.log.scoped(.FileSwapper); - -io: std.Io, -arena: *std.heap.ArenaAllocator, -dir: std.Io.Dir, -target_path: []const u8, -tmp_path: []const u8, -tmp: std.Io.File, - -pub fn createAt(io: std.Io, allocator: std.mem.Allocator, dir: std.Io.Dir, sub_path: []const u8) !FileSwapper { - const arena = try allocator.create(std.heap.ArenaAllocator); - errdefer allocator.destroy(arena); - arena.* = std.heap.ArenaAllocator.init(allocator); - - const tmp_path = try std.fmt.allocPrint( - arena.allocator(), - ".{s}", - .{sub_path}, - ); - - log.debug("Creating {s}", .{tmp_path}); - - const f = try dir.createFile(io, tmp_path, .{}); - - return .{ - .io = io, - .arena = arena, - .dir = dir, - .target_path = try arena.allocator().dupe(u8, sub_path), - .tmp_path = tmp_path, - .tmp = f, - }; -} - -fn deinit(self: FileSwapper) void { - self.tmp.close(self.io); - const allocator = self.arena.child_allocator; - self.arena.deinit(); - allocator.destroy(self.arena); -} - -pub fn file(self: FileSwapper) std.fs.File { - return self.tmp; -} - -pub fn writer(self: FileSwapper) std.Io.File.Writer { - const buf = self.arena.allocator().alloc(u8, 1024) catch - @panic("oom"); - return self.tmp.writer(self.io, buf); -} - -pub fn swap(self: FileSwapper) !void { - log.debug("Swapping {s} -> {s}", .{ self.tmp_path, self.target_path }); - - // flush writes - try self.tmp.sync(self.io); - - // swap file into final location - // NOTE: the tmp fd is still valid after this - try std.Io.Dir.rename( - self.dir, - self.tmp_path, - self.dir, - self.target_path, - self.io, - ); -} - -pub fn close(self: FileSwapper) void { - self.swap() catch - @panic("failed to swap target file"); - - self.deinit(); -} - -test "smoke" { - std.testing.log_level = .debug; - - const alloc = std.testing.allocator; - - var tmp = std.testing.tmpDir(.{}); - defer tmp.cleanup(); - - const fileswapper = try FileSwapper.createAt(std.testing.io, alloc, tmp.dir, "test.txt"); - errdefer fileswapper.deinit(); - - var w = fileswapper.writer(); - try w.interface.writeAll("hi"); - - try tmp.dir.access(std.testing.io, fileswapper.tmp_path, .{ .read = true, .write = true }); - - try fileswapper.swap(); - - const err = tmp.dir.access(std.testing.io, fileswapper.tmp_path, .{ .read = true, .write = true }); - try std.testing.expectError(error.FileNotFound, err); - - fileswapper.deinit(); -} |