Commit e36718165c

Andrew Kelley <andrew@ziglang.org>
2021-12-31 00:42:32
stage2: add `@import` and `@embedFile` to CacheHash
when using `CacheMode.whole`. Also, I verified that `addDepFilePost` is in fact including the original C source file in addition to the files it depends on.
1 parent 67e3180
Changed files (2)
src/Cache.zig
@@ -47,10 +47,16 @@ pub const hasher_init: Hasher = Hasher.init(&[_]u8{0} ** Hasher.key_length);
 pub const File = struct {
     path: ?[]const u8,
     max_file_size: ?usize,
-    stat: fs.File.Stat,
+    stat: Stat,
     bin_digest: BinDigest,
     contents: ?[]const u8,
 
+    pub const Stat = struct {
+        inode: fs.File.INode,
+        size: u64,
+        mtime: i128,
+    };
+
     pub fn deinit(self: *File, allocator: Allocator) void {
         if (self.path) |owned_slice| {
             allocator.free(owned_slice);
@@ -424,7 +430,11 @@ pub const Manifest = struct {
             if (!size_match or !mtime_match or !inode_match) {
                 self.manifest_dirty = true;
 
-                cache_hash_file.stat = actual_stat;
+                cache_hash_file.stat = .{
+                    .size = actual_stat.size,
+                    .mtime = actual_stat.mtime,
+                    .inode = actual_stat.inode,
+                };
 
                 if (self.isProblematicTimestamp(cache_hash_file.stat.mtime)) {
                     // The actual file has an unreliable timestamp, force it to be hashed
@@ -530,7 +540,12 @@ pub const Manifest = struct {
         const file = try fs.cwd().openFile(ch_file.path.?, .{});
         defer file.close();
 
-        ch_file.stat = try file.stat();
+        const actual_stat = try file.stat();
+        ch_file.stat = .{
+            .size = actual_stat.size,
+            .mtime = actual_stat.mtime,
+            .inode = actual_stat.inode,
+        };
 
         if (self.isProblematicTimestamp(ch_file.stat.mtime)) {
             // The actual file has an unreliable timestamp, force it to be hashed
@@ -615,6 +630,42 @@ pub const Manifest = struct {
         try self.populateFileHash(new_ch_file);
     }
 
+    /// Like `addFilePost` but when the file contents have already been loaded from disk.
+    /// On success, cache takes ownership of `resolved_path`.
+    pub fn addFilePostContents(
+        self: *Manifest,
+        resolved_path: []const u8,
+        bytes: []const u8,
+        stat: File.Stat,
+    ) error{OutOfMemory}!void {
+        assert(self.manifest_file != null);
+
+        const ch_file = try self.files.addOne(self.cache.gpa);
+        errdefer self.files.shrinkRetainingCapacity(self.files.items.len - 1);
+
+        ch_file.* = .{
+            .path = resolved_path,
+            .max_file_size = null,
+            .stat = stat,
+            .bin_digest = undefined,
+            .contents = null,
+        };
+
+        if (self.isProblematicTimestamp(ch_file.stat.mtime)) {
+            // The actual file has an unreliable timestamp, force it to be hashed
+            ch_file.stat.mtime = 0;
+            ch_file.stat.inode = 0;
+        }
+
+        {
+            var hasher = hasher_init;
+            hasher.update(bytes);
+            hasher.final(&ch_file.bin_digest);
+        }
+
+        self.hash.hasher.update(&ch_file.bin_digest);
+    }
+
     pub fn addDepFilePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
         assert(self.manifest_file != null);
 
src/Module.zig
@@ -3380,6 +3380,19 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
             error.OutOfMemory => return error.OutOfMemory,
             error.AnalysisFail => {},
         }
+
+        if (mod.comp.whole_cache_manifest) |man| {
+            assert(file.source_loaded);
+            const resolved_path = try file.pkg.root_src_directory.join(gpa, &.{
+                file.sub_file_path,
+            });
+            errdefer gpa.free(resolved_path);
+            try man.addFilePostContents(resolved_path, file.source, .{
+                .size = file.stat_size,
+                .inode = file.stat_inode,
+                .mtime = file.stat_mtime,
+            });
+        }
     } else {
         new_decl.analysis = .file_failure;
     }
@@ -3836,6 +3849,16 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
         resolved_root_path, resolved_path, sub_file_path, rel_file_path,
     });
 
+    if (mod.comp.whole_cache_manifest) |man| {
+        const copied_resolved_path = try gpa.dupe(u8, resolved_path);
+        errdefer gpa.free(copied_resolved_path);
+        try man.addFilePostContents(copied_resolved_path, bytes, .{
+            .size = stat.size,
+            .inode = stat.inode,
+            .mtime = stat.mtime,
+        });
+    }
+
     keep_resolved_path = true; // It's now owned by embed_table.
     gop.value_ptr.* = new_file;
     new_file.* = .{