diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-10 10:57:58 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-15 17:24:42 -0300 |
| commit | 6878e1c309172d624c0d7a3555f6f0217ae6770e (patch) | |
| tree | 1331379616ecee3dc4da2b735ccf27c33e3a3817 /src/fs.zig | |
| parent | bba412a3b2c83b4c6935baeaac979ead46c0a5dc (diff) | |
| download | pardes-6878e1c309172d624c0d7a3555f6f0217ae6770e.tar.gz pardes-6878e1c309172d624c0d7a3555f6f0217ae6770e.zip | |
Resolve relative restores in the dump directory and propagate LSP probe errors
Diffstat (limited to 'src/fs.zig')
| -rw-r--r-- | src/fs.zig | 57 |
1 files changed, 57 insertions, 0 deletions
@@ -1200,6 +1200,63 @@ pub fn readFile(gpa: std.mem.Allocator, path: []const u8) ![]u8 { return readFileLimit(gpa, path, limits.max_file_bytes); } +/// Restore first tries a relative argument under the default dump directory, +/// then preserves the ordinary file lookup. Absolute paths remain verbatim. +pub fn readRestore(gpa: std.mem.Allocator, path: []const u8) ![]u8 { + var dir_buf: [4096]u8 = undefined; + const dir = @import("dump.zig").defaultDirectory(&dir_buf); + return readRestoreIn(gpa, path, dir); +} + +fn readRestoreIn(gpa: std.mem.Allocator, path: []const u8, dir: ?[]const u8) ![]u8 { + if (!std.fs.path.isAbsolute(path)) { + if (dir) |base| { + var buf: [4096]u8 = undefined; + if (std.fmt.bufPrint(&buf, "{s}/{s}", .{ base, path })) |candidate| { + if (readFile(gpa, candidate)) |bytes| return bytes else |err| switch (err) { + error.FileNotFound => {}, + else => return err, + } + } else |_| {} + } + } + return readFile(gpa, path); +} + +test "Restore prefers default directory then falls back to original path" { + if (!platform_has_fs) return error.SkipZigTest; + const gpa = std.testing.allocator; + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + const relative = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/a.dump", .{tmp.sub_path}); + defer gpa.free(relative); + const base = try std.fmt.allocPrint(gpa, ".zig-cache/tmp/{s}/dumps", .{tmp.sub_path}); + defer gpa.free(base); + const nested = try std.fmt.allocPrint(gpa, "dumps/.zig-cache/tmp/{s}", .{tmp.sub_path}); + defer gpa.free(nested); + try tmp.dir.createDirPath(std.testing.io, nested); + try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "dumps/a.dump", .data = "short name" }); + const short = try readRestoreIn(gpa, "a.dump", base); + defer gpa.free(short); + try std.testing.expectEqualStrings("short name", short); + try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "a.dump", .data = "original" }); + const fallback = try readRestoreIn(gpa, relative, base); + defer gpa.free(fallback); + try std.testing.expectEqualStrings("original", fallback); + const candidate = try std.fmt.allocPrint(gpa, "{s}/{s}", .{ base, relative }); + defer gpa.free(candidate); + try writeFile(candidate, "default"); + const preferred = try readRestoreIn(gpa, relative, base); + defer gpa.free(preferred); + try std.testing.expectEqualStrings("default", preferred); + const absolute = try tmp.dir.realPathFileAlloc(std.testing.io, "a.dump", gpa); + defer gpa.free(absolute); + const direct = try readRestoreIn(gpa, absolute, base); + defer gpa.free(direct); + try std.testing.expectEqualStrings("original", direct); + try std.testing.expectError(error.FileNotFound, readRestoreIn(gpa, "missing-restore-test.dump", base)); +} + fn readFileLimit(gpa: std.mem.Allocator, path: []const u8, limit: usize) ![]u8 { if (std.mem.indexOfScalar(u8, path, 0) != null) return error.OpenFailed; if (!platform_has_fs or std.mem.startsWith(u8, path, "/virtual/")) { |
