| ... | @@ -1019,6 +1019,23 @@ pub const Builder = struct { | ... | @@ -1019,6 +1019,23 @@ pub const Builder = struct { |
| 1019 | }; | 1019 | }; |
| 1020 | } | 1020 | } |
| 1021 | | 1021 | |
| | 1022 | pub fn truncateFile(self: *Builder, dest_path: []const u8) !void { |
| | 1023 | if (self.verbose) { |
| | 1024 | warn("truncate {s}\n", .{dest_path}); |
| | 1025 | } |
| | 1026 | const cwd = fs.cwd(); |
| | 1027 | var src_file = cwd.createFile(dest_path, .{}) catch |err| switch (err) { |
| | 1028 | error.FileNotFound => blk: { |
| | 1029 | if (fs.path.dirname(dest_path)) |dirname| { |
| | 1030 | try cwd.makePath(dirname); |
| | 1031 | } |
| | 1032 | break :blk try cwd.createFile(dest_path, .{}); |
| | 1033 | }, |
| | 1034 | else => |e| return e, |
| | 1035 | }; |
| | 1036 | src_file.close(); |
| | 1037 | } |
| | 1038 | |
| 1022 | pub fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 { | 1039 | pub fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 { |
| 1023 | return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch unreachable; | 1040 | return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch unreachable; |
| 1024 | } | 1041 | } |
| ... | @@ -2791,17 +2808,23 @@ pub const InstallDirectoryOptions = struct { | ... | @@ -2791,17 +2808,23 @@ pub const InstallDirectoryOptions = struct { |
| 2791 | source_dir: []const u8, | 2808 | source_dir: []const u8, |
| 2792 | install_dir: InstallDir, | 2809 | install_dir: InstallDir, |
| 2793 | install_subdir: []const u8, | 2810 | install_subdir: []const u8, |
| 2794 | exclude_extensions: ?[]const []const u8 = null, | 2811 | /// File paths which end in any of these suffixes will be excluded |
| | 2812 | /// from being installed. |
| | 2813 | exclude_extensions: []const []const u8 = &.{}, |
| | 2814 | /// File paths which end in any of these suffixes will result in |
| | 2815 | /// empty files being installed. This is mainly intended for large |
| | 2816 | /// test.zig files in order to prevent needless installation bloat. |
| | 2817 | /// However if the files were not present at all, then |
| | 2818 | /// `@import("test.zig")` would be a compile error. |
| | 2819 | blank_extensions: []const []const u8 = &.{}, |
| 2795 | | 2820 | |
| 2796 | fn dupe(self: InstallDirectoryOptions, b: *Builder) InstallDirectoryOptions { | 2821 | fn dupe(self: InstallDirectoryOptions, b: *Builder) InstallDirectoryOptions { |
| 2797 | return .{ | 2822 | return .{ |
| 2798 | .source_dir = b.dupe(self.source_dir), | 2823 | .source_dir = b.dupe(self.source_dir), |
| 2799 | .install_dir = self.install_dir.dupe(b), | 2824 | .install_dir = self.install_dir.dupe(b), |
| 2800 | .install_subdir = b.dupe(self.install_subdir), | 2825 | .install_subdir = b.dupe(self.install_subdir), |
| 2801 | .exclude_extensions = if (self.exclude_extensions) |extensions| | 2826 | .exclude_extensions = b.dupeStrings(self.exclude_extensions), |
| 2802 | b.dupeStrings(extensions) | 2827 | .blank_extensions = b.dupeStrings(self.blank_extensions), |
| 2803 | else | | |
| 2804 | null, | | |
| 2805 | }; | 2828 | }; |
| 2806 | } | 2829 | } |
| 2807 | }; | 2830 | }; |
| ... | @@ -2829,17 +2852,29 @@ pub const InstallDirStep = struct { | ... | @@ -2829,17 +2852,29 @@ pub const InstallDirStep = struct { |
| 2829 | const full_src_dir = self.builder.pathFromRoot(self.options.source_dir); | 2852 | const full_src_dir = self.builder.pathFromRoot(self.options.source_dir); |
| 2830 | var it = try fs.walkPath(self.builder.allocator, full_src_dir); | 2853 | var it = try fs.walkPath(self.builder.allocator, full_src_dir); |
| 2831 | next_entry: while (try it.next()) |entry| { | 2854 | next_entry: while (try it.next()) |entry| { |
| 2832 | if (self.options.exclude_extensions) |ext_list| for (ext_list) |ext| { | 2855 | for (self.options.exclude_extensions) |ext| { |
| 2833 | if (mem.endsWith(u8, entry.path, ext)) { | 2856 | if (mem.endsWith(u8, entry.path, ext)) { |
| 2834 | continue :next_entry; | 2857 | continue :next_entry; |
| 2835 | } | 2858 | } |
| 2836 | }; | 2859 | } |
| 2837 | | 2860 | |
| 2838 | const rel_path = entry.path[full_src_dir.len + 1 ..]; | 2861 | const rel_path = entry.path[full_src_dir.len + 1 ..]; |
| 2839 | const dest_path = try fs.path.join(self.builder.allocator, &[_][]const u8{ dest_prefix, rel_path }); | 2862 | const dest_path = try fs.path.join(self.builder.allocator, &[_][]const u8{ |
| | 2863 | dest_prefix, rel_path, |
| | 2864 | }); |
| | 2865 | |
| 2840 | switch (entry.kind) { | 2866 | switch (entry.kind) { |
| 2841 | .Directory => try fs.cwd().makePath(dest_path), | 2867 | .Directory => try fs.cwd().makePath(dest_path), |
| 2842 | .File => try self.builder.updateFile(entry.path, dest_path), | 2868 | .File => { |
| | 2869 | for (self.options.blank_extensions) |ext| { |
| | 2870 | if (mem.endsWith(u8, entry.path, ext)) { |
| | 2871 | try self.builder.truncateFile(dest_path); |
| | 2872 | continue :next_entry; |
| | 2873 | } |
| | 2874 | } |
| | 2875 | |
| | 2876 | try self.builder.updateFile(entry.path, dest_path); |
| | 2877 | }, |
| 2843 | else => continue, | 2878 | else => continue, |
| 2844 | } | 2879 | } |
| 2845 | } | 2880 | } |