| ... | ... | @@ -2,6 +2,18 @@ |
| 2 | 2 | //! This is not a general-purpose cache. It is designed to be fast and simple, |
| 3 | 3 | //! not to withstand attacks using specially-crafted input. |
| 4 | 4 | |
| 5 | const Cache = @This(); |
| 6 | const std = @import("std"); |
| 7 | const builtin = @import("builtin"); |
| 8 | const crypto = std.crypto; |
| 9 | const fs = std.fs; |
| 10 | const assert = std.debug.assert; |
| 11 | const testing = std.testing; |
| 12 | const mem = std.mem; |
| 13 | const fmt = std.fmt; |
| 14 | const Allocator = std.mem.Allocator; |
| 15 | const log = std.log.scoped(.cache); |
| 16 | |
| 5 | 17 | gpa: Allocator, |
| 6 | 18 | manifest_dir: fs.Dir, |
| 7 | 19 | hash: HashHelper = .{}, |
| ... | ... | @@ -21,18 +33,6 @@ pub const Path = @import("Cache/Path.zig"); |
| 21 | 33 | pub const Directory = @import("Cache/Directory.zig"); |
| 22 | 34 | pub const DepTokenizer = @import("Cache/DepTokenizer.zig"); |
| 23 | 35 | |
| 24 | | const Cache = @This(); |
| 25 | | const std = @import("std"); |
| 26 | | const builtin = @import("builtin"); |
| 27 | | const crypto = std.crypto; |
| 28 | | const fs = std.fs; |
| 29 | | const assert = std.debug.assert; |
| 30 | | const testing = std.testing; |
| 31 | | const mem = std.mem; |
| 32 | | const fmt = std.fmt; |
| 33 | | const Allocator = std.mem.Allocator; |
| 34 | | const log = std.log.scoped(.cache); |
| 35 | | |
| 36 | 36 | pub fn addPrefix(cache: *Cache, directory: Directory) void { |
| 37 | 37 | cache.prefixes_buffer[cache.prefixes_len] = directory; |
| 38 | 38 | cache.prefixes_len += 1; |
| ... | ... | @@ -1118,25 +1118,12 @@ pub const Manifest = struct { |
| 1118 | 1118 | if (self.manifest_dirty) { |
| 1119 | 1119 | self.manifest_dirty = false; |
| 1120 | 1120 | |
| 1121 | | const gpa = self.cache.gpa; |
| 1122 | | var contents: std.ArrayListUnmanaged(u8) = .empty; |
| 1123 | | defer contents.deinit(gpa); |
| 1124 | | |
| 1125 | | try contents.appendSlice(gpa, manifest_header ++ "\n"); |
| 1126 | | for (self.files.keys()) |file| { |
| 1127 | | try contents.print(gpa, "{d} {d} {d} {x} {d} {s}\n", .{ |
| 1128 | | file.stat.size, |
| 1129 | | file.stat.inode, |
| 1130 | | file.stat.mtime, |
| 1131 | | &file.bin_digest, |
| 1132 | | file.prefixed_path.prefix, |
| 1133 | | file.prefixed_path.sub_path, |
| 1134 | | }); |
| 1135 | | } |
| 1136 | | |
| 1137 | | try manifest_file.setEndPos(contents.items.len); |
| 1138 | | var pos: usize = 0; |
| 1139 | | while (pos < contents.items.len) pos += try manifest_file.pwrite(contents.items[pos..], pos); |
| 1121 | var buffer: [4000]u8 = undefined; |
| 1122 | var fw = manifest_file.writer(&buffer); |
| 1123 | writeDirtyManifestToStream(self, &fw) catch |err| switch (err) { |
| 1124 | error.WriteFailed => return fw.err.?, |
| 1125 | else => |e| return e, |
| 1126 | }; |
| 1140 | 1127 | } |
| 1141 | 1128 | |
| 1142 | 1129 | if (self.want_shared_lock) { |
| ... | ... | @@ -1144,6 +1131,21 @@ pub const Manifest = struct { |
| 1144 | 1131 | } |
| 1145 | 1132 | } |
| 1146 | 1133 | |
| 1134 | fn writeDirtyManifestToStream(self: *Manifest, fw: *fs.File.Writer) !void { |
| 1135 | try fw.interface.writeAll(manifest_header ++ "\n"); |
| 1136 | for (self.files.keys()) |file| { |
| 1137 | try fw.interface.print("{d} {d} {d} {x} {d} {s}\n", .{ |
| 1138 | file.stat.size, |
| 1139 | file.stat.inode, |
| 1140 | file.stat.mtime, |
| 1141 | &file.bin_digest, |
| 1142 | file.prefixed_path.prefix, |
| 1143 | file.prefixed_path.sub_path, |
| 1144 | }); |
| 1145 | } |
| 1146 | try fw.end(); |
| 1147 | } |
| 1148 | |
| 1147 | 1149 | fn downgradeToSharedLock(self: *Manifest) !void { |
| 1148 | 1150 | if (!self.have_exclusive_lock) return; |
| 1149 | 1151 | |