authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-12-23 00:00:37+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-12-23 00:00:37+02:00
logba2f2e139306618b8beaa8e833b1f9845309df73
treea0d0d184a7a3070bca4161d2760e66a57a4256b1
parentccdb81fb31f3fa1384b44b74ecdae345457bd0b5
parentfa09c3a5e7ab855026ae10f9e1f61b05611a2275
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7476 from ifreund/pkgs

stage2: free Package resources, print package path on --pkg-begin failure

2 files changed, 61 insertions(+), 57 deletions(-)

src/Package.zig+34-22
...@@ -1,3 +1,12 @@...@@ -1,3 +1,12 @@
1const Package = @This();
2
3const std = @import("std");
4const fs = std.fs;
5const mem = std.mem;
6const Allocator = mem.Allocator;
7
8const Compilation = @import("Compilation.zig");
9
1pub const Table = std.StringHashMapUnmanaged(*Package);10pub const Table = std.StringHashMapUnmanaged(*Package);
211
3root_src_directory: Compilation.Directory,12root_src_directory: Compilation.Directory,
...@@ -6,57 +15,60 @@ root_src_path: []const u8,...@@ -6,57 +15,60 @@ root_src_path: []const u8,
6table: Table = .{},15table: Table = .{},
7parent: ?*Package = null,16parent: ?*Package = null,
817
9const std = @import("std");18/// Allocate a Package. No references to the slices passed are kept.
10const mem = std.mem;
11const Allocator = std.mem.Allocator;
12const assert = std.debug.assert;
13const Package = @This();
14const Compilation = @import("Compilation.zig");
15
16/// No references to `root_src_dir` and `root_src_path` are kept.
17pub fn create(19pub fn create(
18 gpa: *Allocator,20 gpa: *Allocator,
19 base_directory: Compilation.Directory,21 /// Null indicates the current working directory
20 /// Relative to `base_directory`.22 root_src_dir_path: ?[]const u8,
21 root_src_dir: []const u8,23 /// Relative to root_src_dir_path
22 /// Relative to `root_src_dir`.
23 root_src_path: []const u8,24 root_src_path: []const u8,
24) !*Package {25) !*Package {
25 const ptr = try gpa.create(Package);26 const ptr = try gpa.create(Package);
26 errdefer gpa.destroy(ptr);27 errdefer gpa.destroy(ptr);
2728
28 const root_src_dir_path = try base_directory.join(gpa, &[_][]const u8{root_src_dir});29 const owned_dir_path = if (root_src_dir_path) |p| try gpa.dupe(u8, p) else null;
29 errdefer gpa.free(root_src_dir_path);30 errdefer if (owned_dir_path) |p| gpa.free(p);
3031
31 const root_src_path_dupe = try mem.dupe(gpa, u8, root_src_path);32 const owned_src_path = try gpa.dupe(u8, root_src_path);
32 errdefer gpa.free(root_src_path_dupe);33 errdefer gpa.free(owned_src_path);
3334
34 ptr.* = .{35 ptr.* = .{
35 .root_src_directory = .{36 .root_src_directory = .{
36 .path = root_src_dir_path,37 .path = owned_dir_path,
37 .handle = try base_directory.handle.openDir(root_src_dir, .{}),38 .handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(),
38 },39 },
39 .root_src_path = root_src_path_dupe,40 .root_src_path = owned_src_path,
40 };41 };
42
41 return ptr;43 return ptr;
42}44}
4345
46/// Free all memory associated with this package and recursively call destroy
47/// on all packages in its table
44pub fn destroy(pkg: *Package, gpa: *Allocator) void {48pub fn destroy(pkg: *Package, gpa: *Allocator) void {
45 pkg.root_src_directory.handle.close();
46 gpa.free(pkg.root_src_path);49 gpa.free(pkg.root_src_path);
47 if (pkg.root_src_directory.path) |p| gpa.free(p);50
51 // If root_src_directory.path is null then the handle is the cwd()
52 // which shouldn't be closed.
53 if (pkg.root_src_directory.path) |p| {
54 gpa.free(p);
55 pkg.root_src_directory.handle.close();
56 }
57
48 {58 {
49 var it = pkg.table.iterator();59 var it = pkg.table.iterator();
50 while (it.next()) |kv| {60 while (it.next()) |kv| {
61 kv.value.destroy(gpa);
51 gpa.free(kv.key);62 gpa.free(kv.key);
52 }63 }
53 }64 }
65
54 pkg.table.deinit(gpa);66 pkg.table.deinit(gpa);
55 gpa.destroy(pkg);67 gpa.destroy(pkg);
56}68}
5769
58pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) !void {70pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) !void {
59 try pkg.table.ensureCapacity(gpa, pkg.table.items().len + 1);71 try pkg.table.ensureCapacity(gpa, pkg.table.count() + 1);
60 const name_dupe = try mem.dupe(gpa, u8, name);72 const name_dupe = try mem.dupe(gpa, u8, name);
61 pkg.table.putAssumeCapacityNoClobber(name_dupe, package);73 pkg.table.putAssumeCapacityNoClobber(name_dupe, package);
62}74}
src/main.zig+27-35
...@@ -568,12 +568,15 @@ fn buildOutputType(...@@ -568,12 +568,15 @@ fn buildOutputType(
568 var test_exec_args = std.ArrayList(?[]const u8).init(gpa);568 var test_exec_args = std.ArrayList(?[]const u8).init(gpa);
569 defer test_exec_args.deinit();569 defer test_exec_args.deinit();
570570
571 var root_pkg_memory: Package = .{571 const pkg_tree_root = try gpa.create(Package);
572 .root_src_directory = undefined,572 // This package only exists to clean up the code parsing --pkg-begin and
573 .root_src_path = undefined,573 // --pkg-end flags. Use dummy values that are safe for the destroy call.
574 pkg_tree_root.* = .{
575 .root_src_directory = .{ .path = null, .handle = fs.cwd() },
576 .root_src_path = &[0]u8{},
574 };577 };
575 defer root_pkg_memory.table.deinit(gpa);578 defer pkg_tree_root.destroy(gpa);
576 var cur_pkg: *Package = &root_pkg_memory;579 var cur_pkg: *Package = pkg_tree_root;
577580
578 switch (arg_mode) {581 switch (arg_mode) {
579 .build, .translate_c, .zig_test, .run => {582 .build, .translate_c, .zig_test, .run => {
...@@ -627,22 +630,15 @@ fn buildOutputType(...@@ -627,22 +630,15 @@ fn buildOutputType(
627 i += 1;630 i += 1;
628 const pkg_path = args[i];631 const pkg_path = args[i];
629632
630 const new_cur_pkg = try arena.create(Package);633 const new_cur_pkg = Package.create(
631 new_cur_pkg.* = .{634 gpa,
632 .root_src_directory = if (fs.path.dirname(pkg_path)) |dirname|635 fs.path.dirname(pkg_path),
633 .{636 fs.path.basename(pkg_path),
634 .path = dirname,637 ) catch |err| {
635 .handle = try fs.cwd().openDir(dirname, .{}), // TODO close this fd638 fatal("Failed to add package at path {}: {}", .{ pkg_path, @errorName(err) });
636 }
637 else
638 .{
639 .path = null,
640 .handle = fs.cwd(),
641 },
642 .root_src_path = fs.path.basename(pkg_path),
643 .parent = cur_pkg,
644 };639 };
645 try cur_pkg.table.put(gpa, pkg_name, new_cur_pkg);640 new_cur_pkg.parent = cur_pkg;
641 try cur_pkg.add(gpa, pkg_name, new_cur_pkg);
646 cur_pkg = new_cur_pkg;642 cur_pkg = new_cur_pkg;
647 } else if (mem.eql(u8, arg, "--pkg-end")) {643 } else if (mem.eql(u8, arg, "--pkg-end")) {
648 cur_pkg = cur_pkg.parent orelse644 cur_pkg = cur_pkg.parent orelse
...@@ -1600,26 +1596,22 @@ fn buildOutputType(...@@ -1600,26 +1596,22 @@ fn buildOutputType(
1600 .yes => |p| p,1596 .yes => |p| p,
1601 };1597 };
16021598
1603 var cleanup_root_dir: ?fs.Dir = null;
1604 defer if (cleanup_root_dir) |*dir| dir.close();
1605
1606 const root_pkg: ?*Package = if (root_src_file) |src_path| blk: {1599 const root_pkg: ?*Package = if (root_src_file) |src_path| blk: {
1607 if (main_pkg_path) |p| {1600 if (main_pkg_path) |p| {
1608 const dir = try fs.cwd().openDir(p, .{});1601 const rel_src_path = try fs.path.relative(gpa, p, src_path);
1609 cleanup_root_dir = dir;1602 defer gpa.free(rel_src_path);
1610 root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir };1603 break :blk try Package.create(gpa, p, rel_src_path);
1611 root_pkg_memory.root_src_path = try fs.path.relative(arena, p, src_path);
1612 } else if (fs.path.dirname(src_path)) |p| {
1613 const dir = try fs.cwd().openDir(p, .{});
1614 cleanup_root_dir = dir;
1615 root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir };
1616 root_pkg_memory.root_src_path = fs.path.basename(src_path);
1617 } else {1604 } else {
1618 root_pkg_memory.root_src_directory = .{ .path = null, .handle = fs.cwd() };1605 break :blk try Package.create(gpa, fs.path.dirname(src_path), fs.path.basename(src_path));
1619 root_pkg_memory.root_src_path = src_path;
1620 }1606 }
1621 break :blk &root_pkg_memory;
1622 } else null;1607 } else null;
1608 defer if (root_pkg) |p| p.destroy(gpa);
1609
1610 // Transfer packages added with --pkg-begin/--pkg-end to the root package
1611 if (root_pkg) |pkg| {
1612 pkg.table = pkg_tree_root.table;
1613 pkg_tree_root.table = .{};
1614 }
16231615
1624 const self_exe_path = try fs.selfExePathAlloc(arena);1616 const self_exe_path = try fs.selfExePathAlloc(arena);
1625 var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir|1617 var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir|