| ... | @@ -363,9 +363,9 @@ pub const Manifest = struct { | ... | @@ -363,9 +363,9 @@ pub const Manifest = struct { |
| 363 | pub const File = extern struct { | 363 | pub const File = extern struct { |
| 364 | size: u64, | 364 | size: u64, |
| 365 | inode: u64, | 365 | inode: u64, |
| 366 | digest: BinDigest, | | |
| 367 | /// Nanoseconds. | 366 | /// Nanoseconds. |
| 368 | mtime: i64, | 367 | mtime: i64, |
| | 368 | digest: BinDigest, |
| 369 | /// Starting with this field and continuing into the path, excluding the null byte, | 369 | /// Starting with this field and continuing into the path, excluding the null byte, |
| 370 | /// is the string that is hashed for the manifest digest. | 370 | /// is the string that is hashed for the manifest digest. |
| 371 | flags: Flags, | 371 | flags: Flags, |
| ... | @@ -546,35 +546,29 @@ pub const Manifest = struct { | ... | @@ -546,35 +546,29 @@ pub const Manifest = struct { |
| 546 | pub fn addInputPath(m: *Manifest, path: Path, options: AddInputPathOptions) Allocator.Error!InputPath.Index { | 546 | pub fn addInputPath(m: *Manifest, path: Path, options: AddInputPathOptions) Allocator.Error!InputPath.Index { |
| 547 | const cache = m.cache; | 547 | const cache = m.cache; |
| 548 | const gpa = cache.gpa; | 548 | const gpa = cache.gpa; |
| | 549 | const is_directory = options.handle.isDirectory(); |
| | 550 | |
| 549 | try m.files.ensureUnusedCapacityContext(gpa, 1, .{ .contents = m.contents.items }); | 551 | try m.files.ensureUnusedCapacityContext(gpa, 1, .{ .contents = m.contents.items }); |
| 550 | try m.input_paths.ensureUnusedCapacity(gpa, 1); | 552 | try m.input_paths.ensureUnusedCapacity(gpa, 1); |
| 551 | | 553 | |
| 552 | const prev_contents_len = m.contents.items.len; | 554 | const new_file_offset: File.Offset = @fromBackingInt(@intCast(m.contents.items.len)); |
| 553 | const header: *File = @ptrCast(@alignCast(try m.contents.addManyAsSlice(gpa, @sizeOf(File)))); | 555 | try m.contents.appendNTimes(gpa, 0, @offsetOf(File, "path_start")); |
| 554 | errdefer m.contents.shrinkRetainingCapacity(prev_contents_len); | 556 | errdefer m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset)); |
| 555 | | 557 | |
| 556 | header.* = .{ | 558 | const new_prefix = try cache.resolveAppendPath(&m.contents, path); |
| 557 | .flags = .{ | | |
| 558 | .prefix = try cache.resolveAppendPath(&m.contents, path), | | |
| 559 | .is_directory = options.handle.isDirectory(), | | |
| 560 | .metadata_only = options.metadata_only, | | |
| 561 | }, | | |
| 562 | .size = undefined, | | |
| 563 | .inode = undefined, | | |
| 564 | .mtime = undefined, | | |
| 565 | .digest = undefined, | | |
| 566 | .path_start = .{}, | | |
| 567 | }; | | |
| 568 | assert(mem.isAligned(m.contents.items.len, @alignOf(File))); | 559 | assert(mem.isAligned(m.contents.items.len, @alignOf(File))); |
| | 560 | new_file_offset.get(m.contents.items).flags = .{ |
| | 561 | .prefix = new_prefix, |
| | 562 | .is_directory = is_directory, |
| | 563 | .metadata_only = options.metadata_only, |
| | 564 | }; |
| 569 | | 565 | |
| 570 | const gop = m.files.getOrPutAssumeCapacityContext(@fromBackingInt(@intCast(prev_contents_len)), .{ | 566 | const gop = m.files.getOrPutAssumeCapacityContext(new_file_offset, .{ .contents = m.contents.items }); |
| 571 | .contents = m.contents.items, | | |
| 572 | }); | | |
| 573 | m.files.lockPointers(); | 567 | m.files.lockPointers(); |
| 574 | defer m.files.unlockPointers(); | 568 | defer m.files.unlockPointers(); |
| 575 | | 569 | |
| 576 | if (gop.found_existing) { | 570 | if (gop.found_existing) { |
| 577 | m.contents.shrinkRetainingCapacity(prev_contents_len); | 571 | m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset)); |
| 578 | const existing_input_file = &m.input_paths.items[gop.index]; | 572 | const existing_input_file = &m.input_paths.items[gop.index]; |
| 579 | switch (options.handle) { | 573 | switch (options.handle) { |
| 580 | .file => |opt_file| if (opt_file) |file| { | 574 | .file => |opt_file| if (opt_file) |file| { |
| ... | @@ -600,7 +594,7 @@ pub const Manifest = struct { | ... | @@ -600,7 +594,7 @@ pub const Manifest = struct { |
| 600 | // If it trips, the same file path has been added to the cache | 594 | // If it trips, the same file path has been added to the cache |
| 601 | // manifest both as a directory and as a normal file, making the | 595 | // manifest both as a directory and as a normal file, making the |
| 602 | // intended caching behavior ambiguous. | 596 | // intended caching behavior ambiguous. |
| 603 | assert(existing_header.flags.is_directory == options.handle.isDirectory()); | 597 | assert(existing_header.flags.is_directory == is_directory); |
| 604 | if (!options.metadata_only) | 598 | if (!options.metadata_only) |
| 605 | existing_header.flags.metadata_only = false; | 599 | existing_header.flags.metadata_only = false; |
| 606 | } else { | 600 | } else { |
| ... | @@ -617,6 +611,7 @@ pub const Manifest = struct { | ... | @@ -617,6 +611,7 @@ pub const Manifest = struct { |
| 617 | }); | 611 | }); |
| 618 | assert(m.input_paths.items.len - 1 == gop.index); | 612 | assert(m.input_paths.items.len - 1 == gop.index); |
| 619 | if (options.stat) |stat| { | 613 | if (options.stat) |stat| { |
| | 614 | const header = new_file_offset.get(m.contents.items); |
| 620 | header.size = stat.size; | 615 | header.size = stat.size; |
| 621 | header.inode = stat.inode; | 616 | header.inode = stat.inode; |
| 622 | header.mtime = @intCast(stat.mtime.toNanoseconds()); | 617 | header.mtime = @intCast(stat.mtime.toNanoseconds()); |
| ... | @@ -1134,33 +1129,25 @@ pub const Manifest = struct { | ... | @@ -1134,33 +1129,25 @@ pub const Manifest = struct { |
| 1134 | try m.files.ensureUnusedCapacityContext(gpa, 1, .{ .contents = m.contents.items }); | 1129 | try m.files.ensureUnusedCapacityContext(gpa, 1, .{ .contents = m.contents.items }); |
| 1135 | | 1130 | |
| 1136 | const new_file_offset: File.Offset = @fromBackingInt(@intCast(m.contents.items.len)); | 1131 | const new_file_offset: File.Offset = @fromBackingInt(@intCast(m.contents.items.len)); |
| 1137 | const new_header: *File = @ptrCast(@alignCast(try m.contents.addManyAsSlice(gpa, @sizeOf(File)))); | 1132 | try m.contents.appendNTimes(gpa, 0, @offsetOf(File, "path_start")); |
| 1138 | errdefer m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset)); | 1133 | errdefer m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset)); |
| 1139 | | 1134 | |
| 1140 | new_header.* = .{ | 1135 | const new_prefix = switch (options.path) { |
| 1141 | .flags = .{ | 1136 | .unresolved => |unresolved| try cache.resolveAppendPath(&m.contents, unresolved), |
| 1142 | .prefix = switch (options.path) { | 1137 | .prefixed => |prefixed| try cache.appendPrefixedPath(&m.contents, prefixed), |
| 1143 | .unresolved => |unresolved| try cache.resolveAppendPath(&m.contents, unresolved), | | |
| 1144 | .prefixed => |prefixed| try cache.appendPrefixedPath(&m.contents, prefixed), | | |
| 1145 | }, | | |
| 1146 | .is_directory = is_directory, | | |
| 1147 | .metadata_only = options.metadata_only, | | |
| 1148 | }, | | |
| 1149 | .size = undefined, | | |
| 1150 | .inode = undefined, | | |
| 1151 | .mtime = undefined, | | |
| 1152 | .digest = @splat(0), | | |
| 1153 | .path_start = .{}, | | |
| 1154 | }; | 1138 | }; |
| 1155 | assert(mem.isAligned(m.contents.items.len, @alignOf(File))); | 1139 | assert(mem.isAligned(m.contents.items.len, @alignOf(File))); |
| | 1140 | new_file_offset.get(m.contents.items).flags = .{ |
| | 1141 | .prefix = new_prefix, |
| | 1142 | .is_directory = is_directory, |
| | 1143 | .metadata_only = options.metadata_only, |
| | 1144 | }; |
| 1156 | | 1145 | |
| 1157 | const gop = m.files.getOrPutAssumeCapacityContext(new_file_offset, .{ | 1146 | const gop = m.files.getOrPutAssumeCapacityContext(new_file_offset, .{ .contents = m.contents.items }); |
| 1158 | .contents = m.contents.items, | | |
| 1159 | }); | | |
| 1160 | m.files.lockPointers(); | 1147 | m.files.lockPointers(); |
| 1161 | defer m.files.unlockPointers(); | 1148 | defer m.files.unlockPointers(); |
| 1162 | | 1149 | |
| 1163 | const header, const file_offset = if (gop.found_existing) h: { | 1150 | const file_offset = if (gop.found_existing) h: { |
| 1164 | m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset)); | 1151 | m.contents.shrinkRetainingCapacity(@backingInt(new_file_offset)); |
| 1165 | const existing_off = gop.key_ptr.*; | 1152 | const existing_off = gop.key_ptr.*; |
| 1166 | const header = existing_off.get(m.contents.items); | 1153 | const header = existing_off.get(m.contents.items); |
| ... | @@ -1170,8 +1157,10 @@ pub const Manifest = struct { | ... | @@ -1170,8 +1157,10 @@ pub const Manifest = struct { |
| 1170 | assert(header.flags.is_directory == is_directory); | 1157 | assert(header.flags.is_directory == is_directory); |
| 1171 | if (!options.metadata_only) | 1158 | if (!options.metadata_only) |
| 1172 | header.flags.metadata_only = false; | 1159 | header.flags.metadata_only = false; |
| 1173 | break :h .{ header, existing_off }; | 1160 | break :h existing_off; |
| 1174 | } else .{ new_header, new_file_offset }; | 1161 | } else new_file_offset; |
| | 1162 | |
| | 1163 | const header = file_offset.get(m.contents.items); |
| 1175 | | 1164 | |
| 1176 | if (options.stat) |stat| { | 1165 | if (options.stat) |stat| { |
| 1177 | try header.setStat(m, stat); | 1166 | try header.setStat(m, stat); |