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 @@
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
110pub const Table = std.StringHashMapUnmanaged(*Package);
211
312root_src_directory: Compilation.Directory,
......@@ -6,57 +15,60 @@ root_src_path: []const u8,
615table: Table = .{},
716parent: ?*Package = null,
817
9const std = @import("std");
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.
18/// Allocate a Package. No references to the slices passed are kept.
1719pub fn create(
1820 gpa: *Allocator,
19 base_directory: Compilation.Directory,
20 /// Relative to `base_directory`.
21 root_src_dir: []const u8,
22 /// Relative to `root_src_dir`.
21 /// Null indicates the current working directory
22 root_src_dir_path: ?[]const u8,
23 /// Relative to root_src_dir_path
2324 root_src_path: []const u8,
2425) !*Package {
2526 const ptr = try gpa.create(Package);
2627 errdefer gpa.destroy(ptr);
2728
28 const root_src_dir_path = try base_directory.join(gpa, &[_][]const u8{root_src_dir});
29 errdefer gpa.free(root_src_dir_path);
29 const owned_dir_path = if (root_src_dir_path) |p| try gpa.dupe(u8, p) else null;
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 errdefer gpa.free(root_src_path_dupe);
32 const owned_src_path = try gpa.dupe(u8, root_src_path);
33 errdefer gpa.free(owned_src_path);
3334
3435 ptr.* = .{
3536 .root_src_directory = .{
36 .path = root_src_dir_path,
37 .handle = try base_directory.handle.openDir(root_src_dir, .{}),
37 .path = owned_dir_path,
38 .handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(),
3839 },
39 .root_src_path = root_src_path_dupe,
40 .root_src_path = owned_src_path,
4041 };
42
4143 return ptr;
4244}
4345
46/// Free all memory associated with this package and recursively call destroy
47/// on all packages in its table
4448pub fn destroy(pkg: *Package, gpa: *Allocator) void {
45 pkg.root_src_directory.handle.close();
4649 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
4858 {
4959 var it = pkg.table.iterator();
5060 while (it.next()) |kv| {
61 kv.value.destroy(gpa);
5162 gpa.free(kv.key);
5263 }
5364 }
65
5466 pkg.table.deinit(gpa);
5567 gpa.destroy(pkg);
5668}
5769
5870pub 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);
6072 const name_dupe = try mem.dupe(gpa, u8, name);
6173 pkg.table.putAssumeCapacityNoClobber(name_dupe, package);
6274}
src/main.zig+27-35
......@@ -568,12 +568,15 @@ fn buildOutputType(
568568 var test_exec_args = std.ArrayList(?[]const u8).init(gpa);
569569 defer test_exec_args.deinit();
570570
571 var root_pkg_memory: Package = .{
572 .root_src_directory = undefined,
573 .root_src_path = undefined,
571 const pkg_tree_root = try gpa.create(Package);
572 // This package only exists to clean up the code parsing --pkg-begin and
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{},
574577 };
575 defer root_pkg_memory.table.deinit(gpa);
576 var cur_pkg: *Package = &root_pkg_memory;
578 defer pkg_tree_root.destroy(gpa);
579 var cur_pkg: *Package = pkg_tree_root;
577580
578581 switch (arg_mode) {
579582 .build, .translate_c, .zig_test, .run => {
......@@ -627,22 +630,15 @@ fn buildOutputType(
627630 i += 1;
628631 const pkg_path = args[i];
629632
630 const new_cur_pkg = try arena.create(Package);
631 new_cur_pkg.* = .{
632 .root_src_directory = if (fs.path.dirname(pkg_path)) |dirname|
633 .{
634 .path = dirname,
635 .handle = try fs.cwd().openDir(dirname, .{}), // TODO close this fd
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,
633 const new_cur_pkg = Package.create(
634 gpa,
635 fs.path.dirname(pkg_path),
636 fs.path.basename(pkg_path),
637 ) catch |err| {
638 fatal("Failed to add package at path {}: {}", .{ pkg_path, @errorName(err) });
644639 };
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);
646642 cur_pkg = new_cur_pkg;
647643 } else if (mem.eql(u8, arg, "--pkg-end")) {
648644 cur_pkg = cur_pkg.parent orelse
......@@ -1600,26 +1596,22 @@ fn buildOutputType(
16001596 .yes => |p| p,
16011597 };
16021598
1603 var cleanup_root_dir: ?fs.Dir = null;
1604 defer if (cleanup_root_dir) |*dir| dir.close();
1605
16061599 const root_pkg: ?*Package = if (root_src_file) |src_path| blk: {
16071600 if (main_pkg_path) |p| {
1608 const dir = try fs.cwd().openDir(p, .{});
1609 cleanup_root_dir = dir;
1610 root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir };
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);
1601 const rel_src_path = try fs.path.relative(gpa, p, src_path);
1602 defer gpa.free(rel_src_path);
1603 break :blk try Package.create(gpa, p, rel_src_path);
16171604 } else {
1618 root_pkg_memory.root_src_directory = .{ .path = null, .handle = fs.cwd() };
1619 root_pkg_memory.root_src_path = src_path;
1605 break :blk try Package.create(gpa, fs.path.dirname(src_path), fs.path.basename(src_path));
16201606 }
1621 break :blk &root_pkg_memory;
16221607 } 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
16241616 const self_exe_path = try fs.selfExePathAlloc(arena);
16251617 var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir|