| author | |
| committer | |
| log | bb1b59ee1feecd5500847d394fc90842efe138ed |
| tree | a472dc6fb7a4fce1a411075d7ed11d78a122a892 |
| parent | db7ceada15b007747bfd433e6635324edcec918e |
7 files changed, 103 insertions(+), 59 deletions(-)
BRANCH_TODO+1| ... | @@ -41,6 +41,7 @@ | ... | @@ -41,6 +41,7 @@ |
| 41 | ## Already Filed Followup Issues | 41 | ## Already Filed Followup Issues |
| 42 | * build system fmt step with check=false does not acquire a write lock on source files #35204 | 42 | * build system fmt step with check=false does not acquire a write lock on source files #35204 |
| 43 | * enhance CheckFile step output when there is not a match #35208 | 43 | * enhance CheckFile step output when there is not a match #35208 |
| 44 | * missing truncate functionality #35353 | ||
| 44 | 45 | ||
| 45 | ## Release Notes | 46 | ## Release Notes |
| 46 | 47 |
lib/compiler/Maker.zig+41-4| ... | @@ -1879,13 +1879,50 @@ pub fn installGenerated( | ... | @@ -1879,13 +1879,50 @@ pub fn installGenerated( |
| 1879 | return installPath(maker, arena, src_path, dest_path, asking_step_index); | 1879 | return installPath(maker, arena, src_path, dest_path, asking_step_index); |
| 1880 | } | 1880 | } |
| 1881 | 1881 | ||
| 1882 | pub fn truncatePath( | ||
| 1883 | maker: *Maker, | ||
| 1884 | arena: Allocator, | ||
| 1885 | dest_path: Path, | ||
| 1886 | asking_step_index: Configuration.Step.Index, | ||
| 1887 | ) Step.ExtendedMakeError!void { | ||
| 1888 | const graph = maker.graph; | ||
| 1889 | const io = graph.io; | ||
| 1890 | if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{ | ||
| 1891 | "truncate", try dest_path.toString(arena), | ||
| 1892 | }); | ||
| 1893 | // https://codeberg.org/ziglang/zig/issues/35353 | ||
| 1894 | const err = e: { | ||
| 1895 | var file = f: { | ||
| 1896 | break :f dest_path.root_dir.handle.createFile(io, dest_path.sub_path, .{}) catch |err| switch (err) { | ||
| 1897 | error.FileNotFound => { | ||
| 1898 | const parent_path = dest_path.dirname() orelse break :e err; | ||
| 1899 | parent_path.root_dir.handle.createDirPath(io, parent_path.sub_path) catch |in| switch (in) { | ||
| 1900 | error.Canceled => |e| return e, | ||
| 1901 | else => |e| { | ||
| 1902 | const s = stepByIndex(maker, asking_step_index); | ||
| 1903 | return s.fail(maker, "failed creating directory {f}: {t}", .{ parent_path, e }); | ||
| 1904 | }, | ||
| 1905 | }; | ||
| 1906 | break :f dest_path.root_dir.handle.createFile(io, dest_path.sub_path, .{}) catch |in| break :e in; | ||
| 1907 | }, | ||
| 1908 | error.Canceled => |e| return e, | ||
| 1909 | else => |e| break :e e, | ||
| 1910 | }; | ||
| 1911 | }; | ||
| 1912 | file.close(io); | ||
| 1913 | return; | ||
| 1914 | }; | ||
| 1915 | const s = stepByIndex(maker, asking_step_index); | ||
| 1916 | return s.fail(maker, "failed truncating file {f}: {t}", .{ dest_path, err }); | ||
| 1917 | } | ||
| 1918 | |||
| 1882 | pub fn installPath( | 1919 | pub fn installPath( |
| 1883 | maker: *Maker, | 1920 | maker: *Maker, |
| 1884 | arena: Allocator, | 1921 | arena: Allocator, |
| 1885 | src_path: Path, | 1922 | src_path: Path, |
| 1886 | dest_path: Path, | 1923 | dest_path: Path, |
| 1887 | asking_step_index: Configuration.Step.Index, | 1924 | asking_step_index: Configuration.Step.Index, |
| 1888 | ) !Dir.PrevStatus { | 1925 | ) Step.ExtendedMakeError!Dir.PrevStatus { |
| 1889 | const graph = maker.graph; | 1926 | const graph = maker.graph; |
| 1890 | const io = graph.io; | 1927 | const io = graph.io; |
| 1891 | if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{ | 1928 | if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{ |
| ... | @@ -1900,7 +1937,7 @@ pub fn installPath( | ... | @@ -1900,7 +1937,7 @@ pub fn installPath( |
| 1900 | .{}, | 1937 | .{}, |
| 1901 | ) catch |err| { | 1938 | ) catch |err| { |
| 1902 | const s = stepByIndex(maker, asking_step_index); | 1939 | const s = stepByIndex(maker, asking_step_index); |
| 1903 | return s.fail(maker, "unable to update file from {f} to {f}: {t}", .{ src_path, dest_path, err }); | 1940 | return s.fail(maker, "failed updating file from {f} to {f}: {t}", .{ src_path, dest_path, err }); |
| 1904 | }; | 1941 | }; |
| 1905 | } | 1942 | } |
| 1906 | 1943 | ||
| ... | @@ -1910,7 +1947,7 @@ pub fn installDir( | ... | @@ -1910,7 +1947,7 @@ pub fn installDir( |
| 1910 | arena: Allocator, | 1947 | arena: Allocator, |
| 1911 | dest_path: Path, | 1948 | dest_path: Path, |
| 1912 | asking_step_index: Configuration.Step.Index, | 1949 | asking_step_index: Configuration.Step.Index, |
| 1913 | ) !Dir.CreatePathStatus { | 1950 | ) Step.ExtendedMakeError!Dir.CreatePathStatus { |
| 1914 | const graph = maker.graph; | 1951 | const graph = maker.graph; |
| 1915 | const io = graph.io; | 1952 | const io = graph.io; |
| 1916 | if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{ | 1953 | if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{ |
| ... | @@ -1918,7 +1955,7 @@ pub fn installDir( | ... | @@ -1918,7 +1955,7 @@ pub fn installDir( |
| 1918 | }); | 1955 | }); |
| 1919 | return dest_path.root_dir.handle.createDirPathStatus(io, dest_path.sub_path, .default_dir) catch |err| { | 1956 | return dest_path.root_dir.handle.createDirPathStatus(io, dest_path.sub_path, .default_dir) catch |err| { |
| 1920 | const s = stepByIndex(maker, asking_step_index); | 1957 | const s = stepByIndex(maker, asking_step_index); |
| 1921 | return s.fail(maker, "unable to create dir {f}: {t}", .{ dest_path, err }); | 1958 | return s.fail(maker, "failed creating dir {f}: {t}", .{ dest_path, err }); |
| 1922 | }; | 1959 | }; |
| 1923 | } | 1960 | } |
| 1924 | 1961 |
lib/compiler/Maker/Step.zig+2-3| ... | @@ -21,6 +21,7 @@ const Maker = @import("../Maker.zig"); | ... | @@ -21,6 +21,7 @@ const Maker = @import("../Maker.zig"); |
| 21 | pub const Compile = @import("Step/Compile.zig"); | 21 | pub const Compile = @import("Step/Compile.zig"); |
| 22 | pub const Fmt = @import("Step/Fmt.zig"); | 22 | pub const Fmt = @import("Step/Fmt.zig"); |
| 23 | pub const InstallArtifact = @import("Step/InstallArtifact.zig"); | 23 | pub const InstallArtifact = @import("Step/InstallArtifact.zig"); |
| 24 | pub const InstallDir = @import("Step/InstallDir.zig"); | ||
| 24 | pub const InstallFile = @import("Step/InstallFile.zig"); | 25 | pub const InstallFile = @import("Step/InstallFile.zig"); |
| 25 | pub const ObjCopy = @import("Step/ObjCopy.zig"); | 26 | pub const ObjCopy = @import("Step/ObjCopy.zig"); |
| 26 | pub const Options = @import("Step/Options.zig"); | 27 | pub const Options = @import("Step/Options.zig"); |
| ... | @@ -79,11 +80,10 @@ pub const Extended = union(enum) { | ... | @@ -79,11 +80,10 @@ pub const Extended = union(enum) { |
| 79 | find_program: Todo, | 80 | find_program: Todo, |
| 80 | fmt: Fmt, | 81 | fmt: Fmt, |
| 81 | install_artifact: InstallArtifact, | 82 | install_artifact: InstallArtifact, |
| 82 | install_dir: Todo, | 83 | install_dir: InstallDir, |
| 83 | install_file: InstallFile, | 84 | install_file: InstallFile, |
| 84 | obj_copy: ObjCopy, | 85 | obj_copy: ObjCopy, |
| 85 | options: Options, | 86 | options: Options, |
| 86 | remove_dir: Todo, | ||
| 87 | run: Run, | 87 | run: Run, |
| 88 | top_level: TopLevel, | 88 | top_level: TopLevel, |
| 89 | translate_c: Todo, | 89 | translate_c: Todo, |
| ... | @@ -103,7 +103,6 @@ pub const Extended = union(enum) { | ... | @@ -103,7 +103,6 @@ pub const Extended = union(enum) { |
| 103 | .install_file => .{ .install_file = .{} }, | 103 | .install_file => .{ .install_file = .{} }, |
| 104 | .obj_copy => .{ .obj_copy = .{} }, | 104 | .obj_copy => .{ .obj_copy = .{} }, |
| 105 | .options => .{ .options = .{} }, | 105 | .options => .{ .options = .{} }, |
| 106 | .remove_dir => .{ .remove_dir = .{} }, | ||
| 107 | .run => .{ .run = .{} }, | 106 | .run => .{ .run = .{} }, |
| 108 | .top_level => .{ .top_level = .{} }, | 107 | .top_level => .{ .top_level = .{} }, |
| 109 | .translate_c => .{ .translate_c = .{} }, | 108 | .translate_c => .{ .translate_c = .{} }, |
lib/compiler/Maker/Step/InstallDir.zig+56-22| ... | @@ -1,7 +1,10 @@ | ... | @@ -1,7 +1,10 @@ |
| 1 | const InstallDir = @This(); | 1 | const InstallDir = @This(); |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const Io = std.Io; | ||
| 5 | const log = std.log; | ||
| 4 | const Configuration = std.Build.Configuration; | 6 | const Configuration = std.Build.Configuration; |
| 7 | const endsWith = std.mem.endsWith; | ||
| 5 | 8 | ||
| 6 | const Step = @import("../Step.zig"); | 9 | const Step = @import("../Step.zig"); |
| 7 | const Maker = @import("../../Maker.zig"); | 10 | const Maker = @import("../../Maker.zig"); |
| ... | @@ -12,51 +15,82 @@ pub fn make( | ... | @@ -12,51 +15,82 @@ pub fn make( |
| 12 | maker: *Maker, | 15 | maker: *Maker, |
| 13 | progress_node: std.Progress.Node, | 16 | progress_node: std.Progress.Node, |
| 14 | ) Step.ExtendedMakeError!void { | 17 | ) Step.ExtendedMakeError!void { |
| 18 | _ = install_dir; | ||
| 15 | const graph = maker.graph; | 19 | const graph = maker.graph; |
| 20 | const gpa = maker.gpa; | ||
| 16 | const arena = maker.graph.arena; // TODO don't leak into process arena | 21 | const arena = maker.graph.arena; // TODO don't leak into process arena |
| 17 | const io = graph.io; | 22 | const io = graph.io; |
| 18 | const step = maker.stepByIndex(step_index); | 23 | const step = maker.stepByIndex(step_index); |
| 24 | const conf = &maker.scanned_config.configuration; | ||
| 25 | const conf_step = step_index.ptr(conf); | ||
| 26 | const conf_id = conf_step.extended.get(conf.extra).install_dir; | ||
| 19 | 27 | ||
| 20 | step.clearWatchInputs(); | 28 | step.clearWatchInputs(maker); |
| 21 | const dest_prefix = b.getInstallPath(install_dir.options.install_dir, install_dir.options.install_subdir); | 29 | |
| 22 | const src_dir_path = install_dir.options.source_dir.getPath3(b, step); | 30 | const dest_parent_path = try maker.resolveInstallDir(arena, conf_id.dest_dir); |
| 23 | const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir); | 31 | const dest_prefix = if (conf_id.dest_sub_path.value) |s| |
| 24 | var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { | 32 | try dest_parent_path.join(arena, s.slice(conf)) |
| 25 | return step.fail("unable to open source directory '{f}': {t}", .{ src_dir_path, err }); | 33 | else |
| 26 | }; | 34 | dest_parent_path; |
| 35 | const src_dir_lazy_path = conf_id.source_dir.get(conf); | ||
| 36 | const src_dir_path = try maker.resolveLazyPath(arena, src_dir_lazy_path, step_index); | ||
| 37 | const need_derived_inputs = try step.addDirectoryWatchInput(maker, src_dir_lazy_path); | ||
| 38 | |||
| 39 | var src_dir = src_dir_path.root_dir.handle.openDir( | ||
| 40 | io, | ||
| 41 | src_dir_path.subPathOrDot(), | ||
| 42 | .{ .iterate = true }, | ||
| 43 | ) catch |err| return step.fail(maker, "failed opening source directory {f}: {t}", .{ src_dir_path, err }); | ||
| 27 | defer src_dir.close(io); | 44 | defer src_dir.close(io); |
| 28 | var it = try src_dir.walk(arena); | 45 | |
| 46 | const exclude_extensions = conf_id.exclude_extensions.slice; | ||
| 47 | const include_extensions: ?[]const Configuration.String = if (conf_id.flags.include_extensions_active) | ||
| 48 | conf_id.include_extensions.slice | ||
| 49 | else | ||
| 50 | null; | ||
| 51 | const blank_extensions = conf_id.blank_extensions.slice; | ||
| 52 | |||
| 29 | var all_cached = true; | 53 | var all_cached = true; |
| 30 | next_entry: while (try it.next(io)) |entry| { | 54 | var it = try src_dir.walk(gpa); |
| 31 | for (install_dir.options.exclude_extensions) |ext| { | 55 | defer it.deinit(); |
| 32 | if (std.mem.endsWith(u8, entry.path, ext)) continue :next_entry; | 56 | next_entry: while (it.next(io) catch |err| switch (err) { |
| 57 | error.Canceled, error.OutOfMemory => |e| return e, | ||
| 58 | else => |e| return step.fail(maker, "failed iterating dir {f}: {t}", .{ src_dir_path, e }), | ||
| 59 | }) |entry| { | ||
| 60 | for (exclude_extensions) |ext| { | ||
| 61 | if (endsWith(u8, entry.path, ext.slice(conf))) continue :next_entry; | ||
| 33 | } | 62 | } |
| 34 | if (install_dir.options.include_extensions) |incs| { | 63 | if (include_extensions) |includes| { |
| 35 | for (incs) |inc| { | 64 | for (includes) |inc| { |
| 36 | if (std.mem.endsWith(u8, entry.path, inc)) break; | 65 | if (endsWith(u8, entry.path, inc.slice(conf))) break; |
| 37 | } else { | 66 | } else { |
| 38 | continue :next_entry; | 67 | continue :next_entry; |
| 39 | } | 68 | } |
| 40 | } | 69 | } |
| 41 | 70 | ||
| 42 | const src_path = try install_dir.options.source_dir.join(arena, entry.path); | 71 | const dest_path = try dest_prefix.join(arena, entry.path); |
| 43 | const dest_path = b.pathJoin(&.{ dest_prefix, entry.path }); | ||
| 44 | switch (entry.kind) { | 72 | switch (entry.kind) { |
| 45 | .directory => { | 73 | .directory => { |
| 46 | if (need_derived_inputs) _ = try step.addDirectoryWatchInput(src_path); | 74 | if (need_derived_inputs) { |
| 47 | const p = try step.installDir(dest_path); | 75 | const entry_path = try src_dir_path.join(arena, entry.path); |
| 76 | try step.addDirectoryWatchInputFromPath(maker, entry_path); | ||
| 77 | } | ||
| 78 | const p = try maker.installDir(arena, dest_path, step_index); | ||
| 48 | all_cached = all_cached and p == .existed; | 79 | all_cached = all_cached and p == .existed; |
| 49 | }, | 80 | }, |
| 50 | .file => { | 81 | .file => { |
| 51 | for (install_dir.options.blank_extensions) |ext| { | 82 | for (blank_extensions) |ext| { |
| 52 | if (std.mem.endsWith(u8, entry.path, ext)) { | 83 | if (endsWith(u8, entry.path, ext.slice(conf))) { |
| 53 | try b.truncateFile(dest_path); | 84 | // TODO check if the file was already there and length 0 |
| 85 | try maker.truncatePath(arena, dest_path, step_index); | ||
| 54 | continue :next_entry; | 86 | continue :next_entry; |
| 55 | } | 87 | } |
| 56 | } | 88 | } |
| 57 | 89 | ||
| 58 | const p = try step.installFile(src_path, dest_path); | 90 | const entry_path = try src_dir_path.join(arena, entry.path); |
| 91 | const p = try maker.installPath(arena, entry_path, dest_path, step_index); | ||
| 59 | all_cached = all_cached and p == .fresh; | 92 | all_cached = all_cached and p == .fresh; |
| 93 | progress_node.completeOne(); | ||
| 60 | }, | 94 | }, |
| 61 | else => continue, | 95 | else => continue, |
| 62 | } | 96 | } |
lib/compiler/configurer.zig+1-1| ... | @@ -931,6 +931,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { | ... | @@ -931,6 +931,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { |
| 931 | .dest_sub_path = dest_sub_path != null, | 931 | .dest_sub_path = dest_sub_path != null, |
| 932 | .exclude_extensions = sid.options.exclude_extensions.len != 0, | 932 | .exclude_extensions = sid.options.exclude_extensions.len != 0, |
| 933 | .include_extensions = include_extensions.len != 0, | 933 | .include_extensions = include_extensions.len != 0, |
| 934 | .include_extensions_active = sid.options.include_extensions != null, | ||
| 934 | .blank_extensions = sid.options.blank_extensions.len != 0, | 935 | .blank_extensions = sid.options.blank_extensions.len != 0, |
| 935 | }, | 936 | }, |
| 936 | .source_dir = try s.addLazyPath(sid.options.source_dir), | 937 | .source_dir = try s.addLazyPath(sid.options.source_dir), |
| ... | @@ -941,7 +942,6 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { | ... | @@ -941,7 +942,6 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { |
| 941 | .blank_extensions = .{ .slice = try s.initStringList(sid.options.blank_extensions) }, | 942 | .blank_extensions = .{ .slice = try s.initStringList(sid.options.blank_extensions) }, |
| 942 | }))); | 943 | }))); |
| 943 | }, | 944 | }, |
| 944 | .remove_dir => @panic("TODO"), | ||
| 945 | .fail => e: { | 945 | .fail => e: { |
| 946 | const sf: *Step.Fail = @fieldParentPtr("step", step); | 946 | const sf: *Step.Fail = @fieldParentPtr("step", step); |
| 947 | break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.Fail, .{ | 947 | break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.Fail, .{ |
lib/std/Build.zig-17| ... | @@ -1584,23 +1584,6 @@ pub fn addCheckFile( | ... | @@ -1584,23 +1584,6 @@ pub fn addCheckFile( |
| 1584 | return Step.CheckFile.create(b, file_source, options); | 1584 | return Step.CheckFile.create(b, file_source, options); |
| 1585 | } | 1585 | } |
| 1586 | 1586 | ||
| 1587 | pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.CreateDirError || Io.Dir.StatFileError)!void { | ||
| 1588 | const graph = b.graph; | ||
| 1589 | const io = graph.io; | ||
| 1590 | if (graph.verbose) log.info("truncate {s}", .{dest_path}); | ||
| 1591 | const cwd = Io.Dir.cwd(); | ||
| 1592 | var src_file = cwd.createFile(io, dest_path, .{}) catch |err| switch (err) { | ||
| 1593 | error.FileNotFound => blk: { | ||
| 1594 | if (fs.path.dirname(dest_path)) |dirname| { | ||
| 1595 | try cwd.createDirPath(io, dirname); | ||
| 1596 | } | ||
| 1597 | break :blk try cwd.createFile(io, dest_path, .{}); | ||
| 1598 | }, | ||
| 1599 | else => |e| return e, | ||
| 1600 | }; | ||
| 1601 | src_file.close(io); | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | /// References a file or directory relative to the source root. | 1587 | /// References a file or directory relative to the source root. |
| 1605 | pub fn path(b: *Build, sub_path: []const u8) LazyPath { | 1588 | pub fn path(b: *Build, sub_path: []const u8) LazyPath { |
| 1606 | if (fs.path.isAbsolute(sub_path)) { | 1589 | if (fs.path.isAbsolute(sub_path)) { |
lib/std/Build/Configuration.zig+2-12| ... | @@ -466,7 +466,6 @@ pub const Step = extern struct { | ... | @@ -466,7 +466,6 @@ pub const Step = extern struct { |
| 466 | install_file: InstallFile, | 466 | install_file: InstallFile, |
| 467 | obj_copy: ObjCopy, | 467 | obj_copy: ObjCopy, |
| 468 | options: Options, | 468 | options: Options, |
| 469 | remove_dir: RemoveDir, | ||
| 470 | run: Run, | 469 | run: Run, |
| 471 | top_level: TopLevel, | 470 | top_level: TopLevel, |
| 472 | translate_c: TranslateC, | 471 | translate_c: TranslateC, |
| ... | @@ -501,7 +500,6 @@ pub const Step = extern struct { | ... | @@ -501,7 +500,6 @@ pub const Step = extern struct { |
| 501 | install_file, | 500 | install_file, |
| 502 | obj_copy, | 501 | obj_copy, |
| 503 | options, | 502 | options, |
| 504 | remove_dir, | ||
| 505 | run, | 503 | run, |
| 506 | top_level, | 504 | top_level, |
| 507 | translate_c, | 505 | translate_c, |
| ... | @@ -1197,8 +1195,9 @@ pub const Step = extern struct { | ... | @@ -1197,8 +1195,9 @@ pub const Step = extern struct { |
| 1197 | dest_sub_path: bool, | 1195 | dest_sub_path: bool, |
| 1198 | exclude_extensions: bool, | 1196 | exclude_extensions: bool, |
| 1199 | include_extensions: bool, | 1197 | include_extensions: bool, |
| 1198 | include_extensions_active: bool, | ||
| 1200 | blank_extensions: bool, | 1199 | blank_extensions: bool, |
| 1201 | _: u23 = 0, | 1200 | _: u22 = 0, |
| 1202 | }; | 1201 | }; |
| 1203 | }; | 1202 | }; |
| 1204 | 1203 | ||
| ... | @@ -1320,15 +1319,6 @@ pub const Step = extern struct { | ... | @@ -1320,15 +1319,6 @@ pub const Step = extern struct { |
| 1320 | }; | 1319 | }; |
| 1321 | }; | 1320 | }; |
| 1322 | 1321 | ||
| 1323 | pub const RemoveDir = struct { | ||
| 1324 | flags: @This().Flags, | ||
| 1325 | |||
| 1326 | pub const Flags = packed struct(u32) { | ||
| 1327 | tag: Tag = .remove_dir, | ||
| 1328 | _: u27 = 0, | ||
| 1329 | }; | ||
| 1330 | }; | ||
| 1331 | |||
| 1332 | pub const TranslateC = struct { | 1322 | pub const TranslateC = struct { |
| 1333 | flags: @This().Flags, | 1323 | flags: @This().Flags, |
| 1334 | src_path: LazyPath.Index, | 1324 | src_path: LazyPath.Index, |