| ... | ... | @@ -13,6 +13,7 @@ const os = @import("os.zig"); |
| 13 | 13 | const base64_encoder = fs.base64_encoder; |
| 14 | 14 | const base64_decoder = fs.base64_decoder; |
| 15 | 15 | const BIN_DIGEST_LEN = 32; |
| 16 | const BASE64_DIGEST_LEN = base64.Base64Encoder.calcSize(BIN_DIGEST_LEN); |
| 16 | 17 | |
| 17 | 18 | pub const File = struct { |
| 18 | 19 | path: ?[]const u8, |
| ... | ... | @@ -41,7 +42,7 @@ pub const CacheHash = struct { |
| 41 | 42 | manifest_dirty: bool, |
| 42 | 43 | force_check_manifest: bool, |
| 43 | 44 | files: ArrayList(File), |
| 44 | | b64_digest: ArrayList(u8), |
| 45 | b64_digest: [BASE64_DIGEST_LEN]u8, |
| 45 | 46 | |
| 46 | 47 | pub fn init(alloc: *Allocator, manifest_dir_path: []const u8) !@This() { |
| 47 | 48 | try fs.cwd().makePath(manifest_dir_path); |
| ... | ... | @@ -55,7 +56,7 @@ pub const CacheHash = struct { |
| 55 | 56 | .manifest_dirty = false, |
| 56 | 57 | .force_check_manifest = false, |
| 57 | 58 | .files = ArrayList(File).init(alloc), |
| 58 | | .b64_digest = ArrayList(u8).init(alloc), |
| 59 | .b64_digest = undefined, |
| 59 | 60 | }; |
| 60 | 61 | } |
| 61 | 62 | |
| ... | ... | @@ -126,27 +127,23 @@ pub const CacheHash = struct { |
| 126 | 127 | self.addSlice(cache_hash_file.path.?); |
| 127 | 128 | } |
| 128 | 129 | |
| 129 | | pub fn hit(self: *@This(), out_digest: *ArrayList(u8)) !bool { |
| 130 | pub fn hit(self: *@This()) !?[BASE64_DIGEST_LEN]u8 { |
| 130 | 131 | debug.assert(self.manifest_file == null); |
| 131 | 132 | |
| 132 | 133 | var bin_digest: [BIN_DIGEST_LEN]u8 = undefined; |
| 133 | 134 | self.blake3.final(&bin_digest); |
| 134 | 135 | |
| 135 | | const OUT_DIGEST_LEN = base64.Base64Encoder.calcSize(BIN_DIGEST_LEN); |
| 136 | | try self.b64_digest.resize(OUT_DIGEST_LEN); |
| 137 | | base64_encoder.encode(self.b64_digest.toSlice(), &bin_digest); |
| 136 | base64_encoder.encode(self.b64_digest[0..], &bin_digest); |
| 138 | 137 | |
| 139 | 138 | if (self.files.toSlice().len == 0 and !self.force_check_manifest) { |
| 140 | | try out_digest.resize(OUT_DIGEST_LEN); |
| 141 | | mem.copy(u8, out_digest.toSlice(), self.b64_digest.toSlice()); |
| 142 | | return true; |
| 139 | return self.b64_digest; |
| 143 | 140 | } |
| 144 | 141 | |
| 145 | 142 | self.blake3 = Blake3.init(); |
| 146 | 143 | self.blake3.update(&bin_digest); |
| 147 | 144 | |
| 148 | 145 | { |
| 149 | | const manifest_file_path = try fmt.allocPrint(self.alloc, "{}.txt", .{self.b64_digest.toSlice()}); |
| 146 | const manifest_file_path = try fmt.allocPrint(self.alloc, "{}.txt", .{self.b64_digest}); |
| 150 | 147 | defer self.alloc.free(manifest_file_path); |
| 151 | 148 | |
| 152 | 149 | self.manifest_file = try self.manifest_dir.createFile(manifest_file_path, .{ .read = true, .truncate = false }); |
| ... | ... | @@ -231,7 +228,7 @@ pub const CacheHash = struct { |
| 231 | 228 | for (self.files.toSlice()) |file| { |
| 232 | 229 | self.blake3.update(&file.bin_digest); |
| 233 | 230 | } |
| 234 | | return false; |
| 231 | return null; |
| 235 | 232 | } |
| 236 | 233 | |
| 237 | 234 | if (idx < input_file_count or idx == 0) { |
| ... | ... | @@ -244,11 +241,10 @@ pub const CacheHash = struct { |
| 244 | 241 | return error.CacheUnavailable; |
| 245 | 242 | }; |
| 246 | 243 | } |
| 247 | | return false; |
| 244 | return null; |
| 248 | 245 | } |
| 249 | 246 | |
| 250 | | try self.final(out_digest); |
| 251 | | return true; |
| 247 | return try self.final(); |
| 252 | 248 | } |
| 253 | 249 | |
| 254 | 250 | pub fn populate_file_hash(self: *@This(), cache_hash_file: *File) !void { |
| ... | ... | @@ -265,22 +261,22 @@ pub const CacheHash = struct { |
| 265 | 261 | self.blake3.update(&cache_hash_file.bin_digest); |
| 266 | 262 | } |
| 267 | 263 | |
| 268 | | pub fn final(self: *@This(), out_digest: *ArrayList(u8)) !void { |
| 264 | pub fn final(self: *@This()) ![BASE64_DIGEST_LEN]u8 { |
| 269 | 265 | debug.assert(self.manifest_file != null); |
| 270 | 266 | |
| 271 | 267 | var bin_digest: [BIN_DIGEST_LEN]u8 = undefined; |
| 272 | 268 | self.blake3.final(&bin_digest); |
| 273 | 269 | |
| 274 | | const OUT_DIGEST_LEN = base64.Base64Encoder.calcSize(BIN_DIGEST_LEN); |
| 275 | | try out_digest.resize(OUT_DIGEST_LEN); |
| 276 | | base64_encoder.encode(out_digest.toSlice(), &bin_digest); |
| 270 | var out_digest: [BASE64_DIGEST_LEN]u8 = undefined; |
| 271 | base64_encoder.encode(&out_digest, &bin_digest); |
| 272 | |
| 273 | return out_digest; |
| 277 | 274 | } |
| 278 | 275 | |
| 279 | 276 | pub fn write_manifest(self: *@This()) !void { |
| 280 | 277 | debug.assert(self.manifest_file != null); |
| 281 | 278 | |
| 282 | | const OUT_DIGEST_LEN = base64.Base64Encoder.calcSize(BIN_DIGEST_LEN); |
| 283 | | var encoded_digest = try Buffer.initSize(self.alloc, OUT_DIGEST_LEN); |
| 279 | var encoded_digest = try Buffer.initSize(self.alloc, BASE64_DIGEST_LEN); |
| 284 | 280 | defer encoded_digest.deinit(); |
| 285 | 281 | var contents = try Buffer.init(self.alloc, ""); |
| 286 | 282 | defer contents.deinit(); |
| ... | ... | @@ -308,7 +304,6 @@ pub const CacheHash = struct { |
| 308 | 304 | file.deinit(self.alloc); |
| 309 | 305 | } |
| 310 | 306 | self.files.deinit(); |
| 311 | | self.b64_digest.deinit(); |
| 312 | 307 | self.manifest_dir.close(); |
| 313 | 308 | } |
| 314 | 309 | }; |
| ... | ... | @@ -332,10 +327,8 @@ test "cache file and the recall it" { |
| 332 | 327 | |
| 333 | 328 | try cwd.writeFile("test.txt", "Hello, world!\n"); |
| 334 | 329 | |
| 335 | | var digest1 = try ArrayList(u8).initCapacity(testing.allocator, 32); |
| 336 | | defer digest1.deinit(); |
| 337 | | var digest2 = try ArrayList(u8).initCapacity(testing.allocator, 32); |
| 338 | | defer digest2.deinit(); |
| 330 | var digest1: [BASE64_DIGEST_LEN]u8 = undefined; |
| 331 | var digest2: [BASE64_DIGEST_LEN]u8 = undefined; |
| 339 | 332 | |
| 340 | 333 | { |
| 341 | 334 | var ch = try CacheHash.init(testing.allocator, temp_manifest_dir); |
| ... | ... | @@ -347,9 +340,9 @@ test "cache file and the recall it" { |
| 347 | 340 | try ch.addFile("test.txt"); |
| 348 | 341 | |
| 349 | 342 | // There should be nothing in the cache |
| 350 | | debug.assert((try ch.hit(&digest1)) == false); |
| 343 | debug.assert((try ch.hit()) == null); |
| 351 | 344 | |
| 352 | | try ch.final(&digest1); |
| 345 | digest1 = try ch.final(); |
| 353 | 346 | } |
| 354 | 347 | { |
| 355 | 348 | var ch = try CacheHash.init(testing.allocator, temp_manifest_dir); |
| ... | ... | @@ -361,10 +354,10 @@ test "cache file and the recall it" { |
| 361 | 354 | try ch.addFile("test.txt"); |
| 362 | 355 | |
| 363 | 356 | // Cache hit! We just "built" the same file |
| 364 | | debug.assert((try ch.hit(&digest2)) == true); |
| 357 | digest2 = (try ch.hit()).?; |
| 365 | 358 | } |
| 366 | 359 | |
| 367 | | debug.assert(mem.eql(u8, digest1.toSlice(), digest2.toSlice())); |
| 360 | debug.assert(mem.eql(u8, digest1[0..], digest2[0..])); |
| 368 | 361 | |
| 369 | 362 | try cwd.deleteTree(temp_manifest_dir); |
| 370 | 363 | } |