| ... | ... | @@ -54,6 +54,7 @@ pub const CacheHash = struct { |
| 54 | 54 | }; |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | /// Record a slice of bytes as an dependency of the process being cached |
| 57 | 58 | pub fn addSlice(self: *@This(), val: []const u8) void { |
| 58 | 59 | debug.assert(self.manifest_file == null); |
| 59 | 60 | |
| ... | ... | @@ -61,57 +62,23 @@ pub const CacheHash = struct { |
| 61 | 62 | self.blake3.update(&[_]u8{0}); |
| 62 | 63 | } |
| 63 | 64 | |
| 64 | | pub fn addBool(self: *@This(), val: bool) void { |
| 65 | | debug.assert(self.manifest_file == null); |
| 66 | | self.blake3.update(&[_]u8{@boolToInt(val)}); |
| 67 | | } |
| 68 | | |
| 69 | | pub fn addInt(self: *@This(), val: var) void { |
| 70 | | debug.assert(self.manifest_file == null); |
| 71 | | |
| 72 | | switch (@typeInfo(@TypeOf(val))) { |
| 73 | | .Int => |int_info| { |
| 74 | | if (int_info.bits == 0 or int_info.bits % 8 != 0) { |
| 75 | | @compileError("Unsupported integer size. Please use a multiple of 8, manually convert to a u8 slice."); |
| 76 | | } |
| 77 | | |
| 78 | | const buf_len = @divExact(int_info.bits, 8); |
| 79 | | var buf: [buf_len]u8 = undefined; |
| 80 | | mem.writeIntNative(@TypeOf(val), &buf, val); |
| 81 | | self.addSlice(&buf); |
| 82 | | |
| 83 | | self.blake3.update(&[_]u8{0}); |
| 84 | | }, |
| 85 | | else => @compileError("Type must be an integer."), |
| 86 | | } |
| 87 | | } |
| 88 | | |
| 65 | /// Convert the input value into bytes and record it as a dependency of the |
| 66 | /// process being cached |
| 89 | 67 | pub fn add(self: *@This(), val: var) void { |
| 90 | 68 | debug.assert(self.manifest_file == null); |
| 91 | 69 | |
| 92 | | const val_type = @TypeOf(val); |
| 93 | | switch (@typeInfo(val_type)) { |
| 94 | | .Int => self.addInt(val), |
| 95 | | .Bool => self.addBool(val), |
| 96 | | .Array => |array_info| if (array_info.child == u8) { |
| 97 | | self.addSlice(val[0..]); |
| 98 | | } else { |
| 99 | | @compileError("Unsupported array type"); |
| 100 | | }, |
| 101 | | .Pointer => |ptr_info| switch (ptr_info.size) { |
| 102 | | .Slice => if (ptr_info.child == u8) { |
| 103 | | self.addSlice(val); |
| 104 | | }, |
| 105 | | .One => self.add(val.*), |
| 106 | | else => { |
| 107 | | @compileLog("Pointer type: ", ptr_info.size, ptr_info.child); |
| 108 | | @compileError("Unsupported pointer type"); |
| 109 | | }, |
| 110 | | }, |
| 111 | | else => @compileError("Unsupported type"), |
| 112 | | } |
| 70 | const valPtr = switch (@typeInfo(@TypeOf(val))) { |
| 71 | .Int => &val, |
| 72 | .Pointer => val, |
| 73 | else => &val, |
| 74 | }; |
| 75 | |
| 76 | self.addSlice(mem.asBytes(valPtr)); |
| 113 | 77 | } |
| 114 | 78 | |
| 79 | /// Add a file as a dependency of process being cached. When `CacheHash.hit` is |
| 80 | /// called, the file's contents will be checked to ensure that it matches |
| 81 | /// the contents from previous times. |
| 115 | 82 | pub fn addFile(self: *@This(), file_path: []const u8) !void { |
| 116 | 83 | debug.assert(self.manifest_file == null); |
| 117 | 84 | |
| ... | ... | @@ -121,6 +88,14 @@ pub const CacheHash = struct { |
| 121 | 88 | self.addSlice(cache_hash_file.path.?); |
| 122 | 89 | } |
| 123 | 90 | |
| 91 | /// Check the cache to see if the input exists in it. If it exists, a base64 encoding |
| 92 | /// of it's hash will be returned; otherwise, null will be returned. |
| 93 | /// |
| 94 | /// This function will also acquire an exclusive lock to the manifest file. This means |
| 95 | /// that a process holding a CacheHash will block any other process attempting to |
| 96 | /// acquire the lock. |
| 97 | /// |
| 98 | /// The lock on the manifest file is released when `CacheHash.release` is called. |
| 124 | 99 | pub fn hit(self: *@This()) !?[BASE64_DIGEST_LEN]u8 { |
| 125 | 100 | debug.assert(self.manifest_file == null); |
| 126 | 101 | |
| ... | ... | @@ -269,6 +244,12 @@ pub const CacheHash = struct { |
| 269 | 244 | pub fn final(self: *@This()) [BASE64_DIGEST_LEN]u8 { |
| 270 | 245 | debug.assert(self.manifest_file != null); |
| 271 | 246 | |
| 247 | // We don't close the manifest file yet, because we want to |
| 248 | // keep it locked until the API user is done using it. |
| 249 | // We also don't write out the manifest yet, because until |
| 250 | // cache_release is called we still might be working on creating |
| 251 | // the artifacts to cache. |
| 252 | |
| 272 | 253 | var bin_digest: [BIN_DIGEST_LEN]u8 = undefined; |
| 273 | 254 | self.blake3.final(&bin_digest); |
| 274 | 255 | |