| ... | ... | @@ -311,6 +311,23 @@ pub const Builder = struct { |
| 311 | 311 | return the_copy; |
| 312 | 312 | } |
| 313 | 313 | |
| 314 | pub fn dupePkg(self: *Builder, package: Pkg) Pkg { |
| 315 | var the_copy = Pkg{ |
| 316 | .name = self.dupe(package.name), |
| 317 | .path = self.dupePath(package.path), |
| 318 | }; |
| 319 | |
| 320 | if (package.dependencies) |dependencies| { |
| 321 | const new_dependencies = self.allocator.alloc(Pkg, dependencies.len) catch unreachable; |
| 322 | the_copy.dependencies = new_dependencies; |
| 323 | |
| 324 | for (dependencies) |dep_package, i| { |
| 325 | new_dependencies[i] = self.dupePkg(dep_package); |
| 326 | } |
| 327 | } |
| 328 | return the_copy; |
| 329 | } |
| 330 | |
| 314 | 331 | pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep { |
| 315 | 332 | const write_file_step = self.addWriteFiles(); |
| 316 | 333 | write_file_step.add(file_path, data); |
| ... | ... | @@ -1826,7 +1843,7 @@ pub const LibExeObjStep = struct { |
| 1826 | 1843 | } |
| 1827 | 1844 | |
| 1828 | 1845 | pub fn addPackage(self: *LibExeObjStep, package: Pkg) void { |
| 1829 | | self.packages.append(package) catch unreachable; |
| 1846 | self.packages.append(self.dupePkg(package)) catch unreachable; |
| 1830 | 1847 | } |
| 1831 | 1848 | |
| 1832 | 1849 | pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void { |
| ... | ... | @@ -2691,6 +2708,47 @@ pub const InstalledFile = struct { |
| 2691 | 2708 | path: []const u8, |
| 2692 | 2709 | }; |
| 2693 | 2710 | |
| 2711 | test "Builder.dupePkg()" { |
| 2712 | var arena = std.heap.ArenaAllocator.init(std.testing.allocator); |
| 2713 | defer arena.deinit(); |
| 2714 | var builder = try Builder.create( |
| 2715 | &arena.allocator, |
| 2716 | "test", |
| 2717 | "test", |
| 2718 | "test", |
| 2719 | ); |
| 2720 | defer builder.destroy(); |
| 2721 | |
| 2722 | var pkg_dep = Pkg{ |
| 2723 | .name = "pkg_dep", |
| 2724 | .path = "/not/a/pkg_dep.zig", |
| 2725 | }; |
| 2726 | var pkg_top = Pkg{ |
| 2727 | .name = "pkg_top", |
| 2728 | .path = "/not/a/pkg_top.zig", |
| 2729 | .dependencies = &[_]Pkg{pkg_dep}, |
| 2730 | }; |
| 2731 | const dupe = builder.dupePkg(pkg_top); |
| 2732 | |
| 2733 | const original_deps = pkg_top.dependencies.?; |
| 2734 | const dupe_deps = dupe.dependencies.?; |
| 2735 | |
| 2736 | // probably the same top level package details |
| 2737 | std.testing.expectEqualStrings(pkg_top.name, dupe.name); |
| 2738 | |
| 2739 | // probably the same dependencies |
| 2740 | std.testing.expectEqual(original_deps.len, dupe_deps.len); |
| 2741 | std.testing.expectEqual(original_deps[0].name, pkg_dep.name); |
| 2742 | |
| 2743 | // could segfault otherwise if pointers in duplicated package's fields are |
| 2744 | // the same as those in stack allocated package's fields |
| 2745 | std.testing.expect(dupe_deps.ptr != original_deps.ptr); |
| 2746 | std.testing.expect(dupe.name.ptr != pkg_top.name.ptr); |
| 2747 | std.testing.expect(dupe.path.ptr != pkg_top.path.ptr); |
| 2748 | std.testing.expect(dupe_deps[0].name.ptr != pkg_dep.name.ptr); |
| 2749 | std.testing.expect(dupe_deps[0].path.ptr != pkg_dep.path.ptr); |
| 2750 | } |
| 2751 | |
| 2694 | 2752 | test "" { |
| 2695 | 2753 | // The only purpose of this test is to get all these untested functions |
| 2696 | 2754 | // to be referenced to avoid regression so it is okay to skip some targets. |