| ... | @@ -241,33 +241,75 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -241,33 +241,75 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 241 | ); | 241 | ); |
| 242 | } | 242 | } |
| 243 | | 243 | |
| 244 | var options_dir = try b.cache_root.handle.makeOpenPath("options", .{}); | 244 | const basename = "options.zig"; |
| 245 | defer options_dir.close(); | 245 | |
| 246 | | 246 | // Hash contents to file name. |
| 247 | const basename = self.hashContentsToFileName(); | 247 | var hash = b.cache.hash; |
| 248 | | 248 | // Random bytes to make unique. Refresh this with new random bytes when |
| 249 | try options_dir.writeFile(&basename, self.contents.items); | 249 | // implementation is modified in a non-backwards-compatible way. |
| 250 | | 250 | hash.add(@as(u32, 0x38845ef8)); |
| 251 | self.generated_file.path = try b.cache_root.join(b.allocator, &.{ "options", &basename }); | 251 | hash.addBytes(self.contents.items); |
| 252 | } | 252 | const sub_path = "c" ++ fs.path.sep_str ++ hash.final() ++ fs.path.sep_str ++ basename; |
| 253 | | 253 | |
| 254 | fn hashContentsToFileName(self: *OptionsStep) [64]u8 { | 254 | self.generated_file.path = try b.cache_root.join(b.allocator, &.{sub_path}); |
| 255 | // TODO update to use the cache system instead of this | 255 | |
| 256 | // This implementation is copied from `WriteFileStep.make` | 256 | // Optimize for the hot path. Stat the file, and if it already exists, |
| 257 | | 257 | // cache hit. |
| 258 | var hash = std.crypto.hash.blake2.Blake2b384.init(.{}); | 258 | if (b.cache_root.handle.access(sub_path, .{})) |_| { |
| 259 | | 259 | // This is the hot path, success. |
| 260 | // Random bytes to make OptionsStep unique. Refresh this with | 260 | step.result_cached = true; |
| 261 | // new random bytes when OptionsStep implementation is modified | 261 | return; |
| 262 | // in a non-backwards-compatible way. | 262 | } else |outer_err| switch (outer_err) { |
| 263 | hash.update("yL0Ya4KkmcCjBlP8"); | 263 | error.FileNotFound => { |
| 264 | hash.update(self.contents.items); | 264 | const sub_dirname = fs.path.dirname(sub_path).?; |
| 265 | | 265 | b.cache_root.handle.makePath(sub_dirname) catch |e| { |
| 266 | var digest: [48]u8 = undefined; | 266 | return step.fail("unable to make path '{}{s}': {s}", .{ |
| 267 | hash.final(&digest); | 267 | b.cache_root, sub_dirname, @errorName(e), |
| 268 | var hash_basename: [64]u8 = undefined; | 268 | }); |
| 269 | _ = fs.base64_encoder.encode(&hash_basename, &digest); | 269 | }; |
| 270 | return hash_basename; | 270 | |
| | 271 | const rand_int = std.crypto.random.int(u64); |
| | 272 | const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ |
| | 273 | std.Build.hex64(rand_int) ++ fs.path.sep_str ++ |
| | 274 | basename; |
| | 275 | const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?; |
| | 276 | |
| | 277 | b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| { |
| | 278 | return step.fail("unable to make temporary directory '{}{s}': {s}", .{ |
| | 279 | b.cache_root, tmp_sub_path_dirname, @errorName(err), |
| | 280 | }); |
| | 281 | }; |
| | 282 | |
| | 283 | b.cache_root.handle.writeFile(tmp_sub_path, self.contents.items) catch |err| { |
| | 284 | return step.fail("unable to write options to '{}{s}': {s}", .{ |
| | 285 | b.cache_root, tmp_sub_path, @errorName(err), |
| | 286 | }); |
| | 287 | }; |
| | 288 | |
| | 289 | b.cache_root.handle.rename(tmp_sub_path, sub_path) catch |err| switch (err) { |
| | 290 | error.PathAlreadyExists => { |
| | 291 | // Other process beat us to it. Clean up the temp file. |
| | 292 | b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| { |
| | 293 | try step.addError("warning: unable to delete temp file '{}{s}': {s}", .{ |
| | 294 | b.cache_root, tmp_sub_path, @errorName(e), |
| | 295 | }); |
| | 296 | }; |
| | 297 | step.result_cached = true; |
| | 298 | return; |
| | 299 | }, |
| | 300 | else => { |
| | 301 | return step.fail("unable to rename options from '{}{s}' to '{}{s}': {s}", .{ |
| | 302 | b.cache_root, tmp_sub_path, |
| | 303 | b.cache_root, sub_path, |
| | 304 | @errorName(err), |
| | 305 | }); |
| | 306 | }, |
| | 307 | }; |
| | 308 | }, |
| | 309 | else => |e| return step.fail("unable to access options file '{}{s}': {s}", .{ |
| | 310 | b.cache_root, sub_path, @errorName(e), |
| | 311 | }), |
| | 312 | } |
| 271 | } | 313 | } |
| 272 | | 314 | |
| 273 | const OptionArtifactArg = struct { | 315 | const OptionArtifactArg = struct { |