From b71bf2a8024c0a05ec07d2a245cb13a14095dff7 Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Sun, 2 Jun 2024 20:30:52 -0700 Subject: [PATCH] add writer to lockfile printing and bun pm ls --- src/cli/package_manager_command.zig | 61 +++++++++++++++++++---------- src/install/lockfile.zig | 2 +- src/output.zig | 8 +++- src/sys.zig | 20 ++++++++++ 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/cli/package_manager_command.zig b/src/cli/package_manager_command.zig index 55631722ef..3d32c6f241 100644 --- a/src/cli/package_manager_command.zig +++ b/src/cli/package_manager_command.zig @@ -265,6 +265,8 @@ pub const PackageManagerCommand = struct { Output.flush(); Output.disableBuffering(); + const writer = Output.writerThatExitsOnEpipe(); + const lockfile = load_lockfile.ok.lockfile; var iterator = Lockfile.Tree.Iterator.init(lockfile); @@ -298,7 +300,19 @@ pub const PackageManagerCommand = struct { if (first_directory.dependencies.len > 1) more_packages[0] = true; if (strings.leftHasAnyInRight(args, &.{ "-A", "-a", "--all" })) { - try printNodeModulesFolderStructure(&first_directory, null, 0, &directories, lockfile, more_packages); + switch (Output.enable_ansi_colors) { + inline else => |enable_ansi_colors| try printNodeModulesFolderStructure( + &first_directory, + null, + 0, + &directories, + lockfile, + more_packages, + @TypeOf(writer), + writer, + enable_ansi_colors, + ), + } } else { var cwd_buf: bun.PathBuffer = undefined; const path = bun.getcwd(&cwd_buf) catch { @@ -310,7 +324,7 @@ pub const PackageManagerCommand = struct { const resolutions = slice.items(.resolution); const root_deps = slice.items(.dependencies)[0]; - Output.println("{s} node_modules ({d})", .{ path, dependencies.len }); + try writer.print("{s} node_modules ({d})\n", .{ path, dependencies.len }); const string_bytes = lockfile.buffers.string_bytes.items; const sorted_dependencies = try ctx.allocator.alloc(DependencyID, root_deps.len); defer ctx.allocator.free(sorted_dependencies); @@ -328,10 +342,14 @@ pub const PackageManagerCommand = struct { const name = dependencies[dependency_id].name.slice(string_bytes); const resolution = resolutions[package_id].fmt(string_bytes, .auto); - if (index < sorted_dependencies.len - 1) { - Output.prettyln("├── {s}@{any}\n", .{ name, resolution }); - } else { - Output.prettyln("└── {s}@{any}\n", .{ name, resolution }); + switch (Output.enable_ansi_colors) { + inline else => |enable_ansi_colors| { + if (index < sorted_dependencies.len - 1) { + try writer.print(Output.prettyFmt("├── {s}@{any}\n", enable_ansi_colors), .{ name, resolution }); + } else { + try writer.print(Output.prettyFmt("└── {s}@{any}\n", enable_ansi_colors), .{ name, resolution }); + } + }, } } } @@ -386,6 +404,9 @@ fn printNodeModulesFolderStructure( directories: *std.ArrayList(NodeModulesFolder), lockfile: *Lockfile, more_packages: []bool, + comptime Writer: type, + writer: Writer, + comptime enable_ansi_colors: bool, ) !void { const allocator = lockfile.allocator; const resolutions = lockfile.packages.items(.resolution); @@ -396,15 +417,15 @@ fn printNodeModulesFolderStructure( while (i < depth) : (i += 1) { if (i == depth - 1) { if (more_packages[i]) { - Output.pretty("├──", .{}); + try writer.print(Output.prettyFmt("|--", enable_ansi_colors), .{}); } else { - Output.pretty("└──", .{}); + try writer.print(Output.prettyFmt("└──", enable_ansi_colors), .{}); } } else { if (more_packages[i]) { - Output.pretty(" ", .{}); + try writer.print(Output.prettyFmt(" ", enable_ansi_colors), .{}); } else { - Output.pretty(" ", .{}); + try writer.print(Output.prettyFmt(" ", enable_ansi_colors), .{}); } } } @@ -414,7 +435,7 @@ fn printNodeModulesFolderStructure( var path = directory.relative_path; if (depth != 0) { - Output.pretty(" ", .{}); + try writer.print(" ", .{}); var temp_depth = depth; while (temp_depth > 0) : (temp_depth -= 1) { if (std.mem.indexOf(u8, path, "node_modules")) |j| { @@ -424,9 +445,9 @@ fn printNodeModulesFolderStructure( } const directory_version = try std.fmt.bufPrint(&resolution_buf, "{}", .{resolutions[id].fmt(string_bytes, .auto)}); if (std.mem.indexOf(u8, path, "node_modules")) |j| { - Output.prettyln("{s}@{s}", .{ path[0 .. j - 1], directory_version }); + try writer.print(Output.prettyFmt("{s}@{s}\n", enable_ansi_colors), .{ path[0 .. j - 1], directory_version }); } else { - Output.prettyln("{s}@{s}", .{ path, directory_version }); + try writer.print(Output.prettyFmt("{s}@{s}\n", enable_ansi_colors), .{ path, directory_version }); } } else { var cwd_buf: bun.PathBuffer = undefined; @@ -434,7 +455,7 @@ fn printNodeModulesFolderStructure( Output.prettyErrorln("error: Could not get current working directory", .{}); Global.exit(1); }; - Output.println("{s} node_modules", .{path}); + try writer.print("{s} node_modules\n", .{path}); } } @@ -475,7 +496,7 @@ fn printNodeModulesFolderStructure( } more_packages[new_depth] = true; - try printNodeModulesFolderStructure(&next, package_id, new_depth, directories, lockfile, more_packages); + try printNodeModulesFolderStructure(&next, package_id, new_depth, directories, lockfile, more_packages, Writer, writer, enable_ansi_colors); } } @@ -484,20 +505,20 @@ fn printNodeModulesFolderStructure( var i: usize = 0; while (i < depth) : (i += 1) { if (more_packages[i]) { - Output.pretty(" ", .{}); + try writer.print(Output.prettyFmt(" ", enable_ansi_colors), .{}); } else { - Output.pretty(" ", .{}); + try writer.print(Output.prettyFmt(" ", enable_ansi_colors), .{}); } } if (more_packages[depth]) { - Output.pretty("├── ", .{}); + try writer.print(Output.prettyFmt("├── ", enable_ansi_colors), .{}); } else { - Output.pretty("└── ", .{}); + try writer.print(Output.prettyFmt("└── ", enable_ansi_colors), .{}); } var resolution_buf: [512]u8 = undefined; const package_version = try std.fmt.bufPrint(&resolution_buf, "{}", .{resolutions[package_id].fmt(string_bytes, .auto)}); - Output.prettyln("{s}@{s}", .{ package_name, package_version }); + try writer.print(Output.prettyFmt("{s}@{s}\n", enable_ansi_colors), .{ package_name, package_version }); } } diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig index 270d4c0a10..36f520fa71 100644 --- a/src/install/lockfile.zig +++ b/src/install/lockfile.zig @@ -1211,7 +1211,7 @@ pub const Printer = struct { .ok => {}, } - const writer = Output.writer(); + const writer = Output.writerThatExitsOnEpipe(); try printWithLockfile(allocator, lockfile, format, @TypeOf(writer), writer); Output.flush(); } diff --git a/src/output.zig b/src/output.zig index 570b89fd0a..33c01f47a2 100644 --- a/src/output.zig +++ b/src/output.zig @@ -357,7 +357,8 @@ pub noinline fn panic(comptime fmt: string, args: anytype) noreturn { } } -pub const WriterType: type = @TypeOf(Source.StreamType.quietWriter(undefined)); +pub const WriterType: type = Source.StreamType.QuietWriter; +pub const QuietWriterTypeThatExitsOnEpipe: type = Source.StreamType.QuietWriterThatExitsOnEpipe; pub fn errorWriter() WriterType { bun.debugAssert(source_set); @@ -374,6 +375,11 @@ pub fn writer() WriterType { return source.stream.quietWriter(); } +pub fn writerThatExitsOnEpipe() QuietWriterTypeThatExitsOnEpipe { + bun.debugAssert(source_set); + return source.stream.quietWriterThatExitsOnEpipe(); +} + pub fn resetTerminal() void { if (!enable_ansi_colors) { return; diff --git a/src/sys.zig b/src/sys.zig index 035e9b8bb6..7e230522da 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -4,6 +4,7 @@ const std = @import("std"); const builtin = @import("builtin"); const bun = @import("root").bun; +const Global = bun.Global; const os = std.os; const assertIsValidWindowsPath = bun.strings.assertIsValidWindowsPath; @@ -2824,13 +2825,32 @@ pub const File = struct { return bytes.len; } + fn stdIoWriteQuietDebugAndExitOnEpipe(this: File, bytes: []const u8) WriteError!usize { + bun.Output.disableScopedDebugWriter(); + defer bun.Output.enableScopedDebugWriter(); + + this.writeAll(bytes).unwrap() catch |err| { + if (err == error.EPIPE) { + Global.exit(0); + } + return err; + }; + + return bytes.len; + } + pub const Writer = std.io.Writer(File, anyerror, stdIoWrite); pub const QuietWriter = if (Environment.isDebug) std.io.Writer(File, anyerror, stdIoWriteQuietDebug) else Writer; + pub const QuietWriterThatExitsOnEpipe = std.io.Writer(File, anyerror, stdIoWriteQuietDebugAndExitOnEpipe); pub fn writer(self: File) Writer { return Writer{ .context = self }; } + pub fn quietWriterThatExitsOnEpipe(self: File) QuietWriterThatExitsOnEpipe { + return QuietWriterThatExitsOnEpipe{ .context = self }; + } + pub fn quietWriter(self: File) QuietWriter { return QuietWriter{ .context = self }; }