tiny.smg.command.impact
Defined in command.
API (2)
Actions
Public operations.
Source
Source: tools/smg/src/command/impact.zig
zig
const std = @import("std");const smg = @import("../root.zig");const graph_mod = smg.graph;const model = smg.model;const query = smg.query;const traversal = smg.traversal;const cli_json = smg.cli.json;const cli_options = smg.cli.options;const cli_output = smg.cli.output;const cli_resolve = smg.cli.resolve;const cli_session = smg.command.session;const table = smg.cli.table;const cli_validation = smg.cli.validation;pub fn run(allocator: std.mem.Allocator, phases: std.mem.Allocator, args: []const []const u8, limits: smg.Limits, boundary: cli_session.PhaseBoundary) !u8 { if (try cli_validation.rejectMissingOptionValues(allocator, args, &.{ "--depth", "--format", "--limit" })) return 2; if (try cli_validation.rejectUnexpectedOptionsPlain(allocator, "impact", "[OPTIONS] NAME", args, &.{ "--depth", "--format", "--coupling-only", "--all-rels", "--limit" })) return 2; if (try cli_validation.rejectInvalidChoiceOption(allocator, "impact", "[OPTIONS] NAME", args, "--format", &.{ "text", "json" })) return 2; if (try cli_validation.rejectInvalidIntegerOption(allocator, "impact", "[OPTIONS] NAME", args, "--depth")) return 2; if (try cli_validation.rejectInvalidIntegerOption(allocator, "impact", "[OPTIONS] NAME", args, "--limit")) return 2; const pos = try cli_options.positional(allocator, args); if (pos.len == 0) { try cli_output.writeClickUsageError(allocator, "impact", "[OPTIONS] NAME", "Missing argument 'NAME'."); return 2; } if (pos.len > 1) { try cli_output.writeClickUsageError(allocator, "impact", "[OPTIONS] NAME", try cli_validation.unexpectedArgumentMessage(allocator, pos[1..])); return 2; } _ = phases; const root = try smg.storage.requireRoot(allocator); try cli_session.noteGraphAge(allocator, root); var opened = try smg.storage.store.openRead(allocator, root, limits.storage); defer opened.close(); const name = try cli_resolve.storedNode( allocator, root, &opened.reader, pos[0], limits.suggestions, ); const coupling_only = cli_options.couplingOnlyValue(args); const names = try query.impactFromReader( allocator, &opened.reader, name, cli_options.depthValue(args), coupling_only, ); boundary.seal(); defer boundary.beginTeardown(); const limit = cli_options.signedLimitValue(args); const displayed = cli_options.slicedLen(names.len, limit); var out: std.Io.Writer.Allocating = .init(allocator); if (std.mem.eql(u8, cli_options.flagValue(args, "--format") orelse "", "json")) { try cli_json.writeImpact(&out.writer, name, names[0..displayed], names.len, limit, coupling_only); return try cli_output.writeOut(out.written()); } try writeTextSource( allocator, &out.writer, .{ .stored = &opened.reader }, name, names[0..displayed], names.len, ); return try cli_output.writeOut(out.written());}pub fn writeText(writer: *std.Io.Writer, graph: graph_mod.Graph, target: []const u8, names: []const []const u8, total: usize) !void { return try writeTextSource(graph.allocator, writer, .{ .graph = graph }, target, names, total);}fn writeTextSource( allocator: std.mem.Allocator, writer: *std.Io.Writer, source: traversal.Source, target: []const u8, names: []const []const u8, total: usize,) !void { if (total == 0) { try writer.print("{s}: no upstream dependents\n", .{target}); return; } try writer.print("Impact of changing {s}:\n", .{target}); const columns = [_]table.Column{ .{ .header = "type", .max_width = 14 }, .{ .header = "name", .max_width = 72 }, }; var scratch_state = std.heap.ArenaAllocator.init(allocator); defer scratch_state.deinit(); const scratch = scratch_state.allocator(); var rows: std.ArrayList([]const []const u8) = .empty; for (names) |name| { const node_type = if (try source.node(scratch, name)) |node| node.type else "?"; try table.appendRow(scratch, &rows, &.{ node_type, name }); } try table.writeJsonOption(allocator, writer, &columns, rows.items, total, "--format json"); try writer.print("\n{d} node(s) affected\n", .{total});}test "impact renders all relationship text contract" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var graph = graph_mod.init(allocator); try graph_mod.addNode(&graph, .{ .name = "app", .type = model.NodeType.module }); try graph_mod.addNode(&graph, .{ .name = "app.main", .type = model.NodeType.function }); try graph_mod.addNode(&graph, .{ .name = "app.helper", .type = model.NodeType.function }); try graph_mod.addNode(&graph, .{ .name = "owner", .type = model.NodeType.module }); try graph_mod.addEdge(&graph, .{ .source = "app", .rel = model.RelType.contains, .target = "app.main" }); try graph_mod.addEdge(&graph, .{ .source = "app.main", .rel = model.RelType.calls, .target = "app.helper" }); try graph_mod.addEdge(&graph, .{ .source = "owner", .rel = model.RelType.contains, .target = "app.helper" }); const all = try query.impact(allocator, graph, "app.helper", null, false); var out: std.Io.Writer.Allocating = .init(allocator); try writeText(&out.writer, graph, "app.helper", all[0..1], all.len); try std.testing.expectEqualStrings( "Impact of changing app.helper:\n" ++ "type name\n" ++ "------ ----\n" ++ "module app\n" ++ "(showing 1 of 3 \xE2\x80\x94 use --limit 0 for all, --format json for exact records)\n" ++ "\n" ++ "3 node(s) affected\n", out.written(), );}Source: tools/smg/src/command/root.zig:13
zig
pub const impact = @import("impact.zig");Audit
| Definitions | 3 |
|---|---|
| Public names | 3 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |