1const UpdateSourceFiles = @This();
2
3const std = @import("std");
4const Io = std.Io;
5const Path = std.Build.Cache.Path;
6const Configuration = std.Build.Configuration;
7
8const Step = @import("../Step.zig");
9const Maker = @import("../../Maker.zig");
10
11pub fn make(
12 usf: *UpdateSourceFiles,
13 step_index: Configuration.Step.Index,
14 maker: *Maker,
15 progress_node: std.Progress.Node,
16) Step.ExtendedMakeError!void {
17 _ = usf;
18 const graph = maker.graph;
19 const arena = maker.graph.arena; // TODO don't leak into process arena
20 const io = graph.io;
21 const step = maker.stepByIndex(step_index);
22 const conf = &maker.scanned_config.configuration;
23 const conf_step = step_index.ptr(conf);
24 const conf_usf = conf_step.extended.get(conf.extra).update_source_files;
25 const build_root = graph.build_root_directory;
26
27 if (conf_step.owner != .root)
28 return step.fail(maker, "non-root package attempted to update its source files", .{});
29
30 var any_miss = false;
31
32 progress_node.setEstimatedTotalItems(conf_usf.embeds.slice.len + conf_usf.copies.slice.len);
33
34 step.clearWatchInputs(maker);
35
36 for (conf_usf.embeds.slice) |*embed| {
37 const dest_path: Path = .{
38 .root_dir = build_root,
39 .sub_path = embed.sub_path.slice(conf),
40 };
41 if (Io.Dir.path.dirname(dest_path.sub_path)) |dirname| {
42 const dirname_path: Path = .{
43 .root_dir = build_root,
44 .sub_path = dirname,
45 };
46 dirname_path.root_dir.handle.createDirPath(io, dirname_path.sub_path) catch |err|
47 return step.fail(maker, "failed creating path {f}: {t}", .{ dirname_path, err });
48 }
49 dest_path.root_dir.handle.writeFile(io, .{
50 .sub_path = dest_path.sub_path,
51 .data = embed.contents.slice(conf),
52 }) catch |err| return step.fail(maker, "failed writing file {f}: {t}", .{ dest_path, err });
53 any_miss = true;
54 progress_node.completeOne();
55 }
56
57 for (conf_usf.copies.slice) |*copy| {
58 const dest_path: Path = .{
59 .root_dir = build_root,
60 .sub_path = copy.sub_path.slice(conf),
61 };
62 if (Io.Dir.path.dirname(dest_path.sub_path)) |dirname| {
63 const dirname_path: Path = .{
64 .root_dir = build_root,
65 .sub_path = dirname,
66 };
67 dirname_path.root_dir.handle.createDirPath(io, dirname_path.sub_path) catch |err|
68 return step.fail(maker, "failed creating path {f}: {t}", .{ dirname_path, err });
69 }
70 const src_lazy_path = copy.src_file.get(conf);
71 const source_path = try maker.resolveLazyPath(arena, src_lazy_path, step_index);
72 try step.addWatchInput(maker, arena, src_lazy_path);
73
74 const prev_status = source_path.root_dir.handle.updateFile(
75 io,
76 source_path.sub_path,
77 dest_path.root_dir.handle,
78 dest_path.sub_path,
79 .{},
80 ) catch |err| return step.fail(maker, "failed updating file from {f} to {f}: {t}", .{
81 source_path, dest_path, err,
82 });
83 any_miss = any_miss or prev_status == .stale;
84 progress_node.completeOne();
85 }
86
87 step.result_cached = !any_miss;
88}