1const std = @import("std");
2const builtin = @import("builtin");
3const extras = @import("extras");
4const nfs = @import("nfs");
5
6const zigmod = @import("../lib.zig");
7const u = @import("./../util/funcs.zig");
8const common = @import("./../common.zig");
9
10//
11//
12
13pub fn execute(self_name: []const u8, args: []const [:0]const u8) !void {
14 _ = self_name;
15
16 const gpa = std.heap.c_allocator;
17 const cachepath = try u.find_cachepath();
18 const dir = nfs.cwd();
19 const should_lock = args.len >= 1 and std.mem.eql(u8, args[0], "--locked");
20 const format_i: usize = if (should_lock) 1 else 0;
21 const Format = enum {
22 tree,
23 mermaid,
24 dot,
25 };
26 const format_s = if (args.len >= 1 + format_i and std.mem.eql(u8, args[format_i], "--format")) args[format_i + 1] else "";
27 const format = std.meta.stringToEnum(Format, format_s) orelse u.fail("unrecognized --format: {s}", .{format_s});
28
29 var options = common.CollectOptions{
30 .log = false,
31 .update = false,
32 .alloc = gpa,
33 .lock = if (should_lock) try common.parse_lockfile(gpa, dir) else null,
34 };
35 const top_module = try common.collect_deps_deep(cachepath, dir, &options);
36
37 var seencache = std.array_list.Managed([48]u8).init(gpa);
38 defer seencache.deinit();
39
40 const w = nfs.stdout();
41
42 switch (format) {
43 .tree => {
44 try printTree(w, top_module, 0);
45 },
46 .mermaid => {
47 try w.writeAll("graph TD;\n");
48 try printMermaid(w, top_module, &seencache);
49 },
50 .dot => {
51 try w.writeAll("digraph {\n");
52 try printDot(w, top_module, &seencache);
53 try w.writeAll("}\n");
54 },
55 }
56}
57
58fn printTree(writer: anytype, module: zigmod.Module, depth: u16) !void {
59 try writer.writeByteNTimes('\t', depth);
60 try writer.writeAll(module.name);
61 try writer.writeAll("\n");
62
63 for (module.deps) |dep| {
64 try printTree(writer, dep, depth + 1);
65 }
66}
67
68fn printMermaid(writer: anytype, module: zigmod.Module, seencache: *std.array_list.Managed([48]u8)) !void {
69 for (seencache.items) |item| {
70 if (std.mem.eql(u8, &module.id, &item)) {
71 return;
72 }
73 }
74 try seencache.append(module.id);
75
76 for (module.deps) |dep| {
77 if (dep.name.len == 0) continue;
78 try writer.print(" {s}-->{s};\n", .{ module.name, dep.name });
79 }
80 for (module.deps) |dep| {
81 try printMermaid(writer, dep, seencache);
82 }
83}
84
85fn printDot(writer: anytype, module: zigmod.Module, seencache: *std.array_list.Managed([48]u8)) !void {
86 for (seencache.items) |item| {
87 if (std.mem.eql(u8, &module.id, &item)) {
88 return;
89 }
90 }
91 try seencache.append(module.id);
92
93 for (module.deps) |dep| {
94 if (dep.name.len == 0) continue;
95 try writer.print(" \"{s}\" -> \"{s}\";\n", .{ module.name, dep.name });
96 }
97 for (module.deps) |dep| {
98 try printDot(writer, dep, seencache);
99 }
100}