aboutsummaryrefslogtreecommitdiff
path: root/src/cli.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-01-19 02:29:07 -0800
committerGravatar GitHub <noreply@github.com> 2022-01-19 02:29:07 -0800
commitd3a93d527336af73df838d69ca42ad1b18adebb8 (patch)
tree726dad460bf4ee2608ffa9557943df11da56f8c3 /src/cli.zig
parented9637de5056af4572ec5e0a75feee9ca858798e (diff)
downloadbun-d3a93d527336af73df838d69ca42ad1b18adebb8.tar.gz
bun-d3a93d527336af73df838d69ca42ad1b18adebb8.tar.zst
bun-d3a93d527336af73df838d69ca42ad1b18adebb8.zip
`fs.*Sync()`, `bun wiptest`, and More ™ (#106)
* very very wip * almost ready to fix the errors * Update identity_context.zig * Update base.zig * [bun test] It runs successfully * Remove unnecessary call * [Bun.js] Improve JS <> Zig unicode string interop This fixes longstanding unicode bugs with `console.log` & `fetch`. I believe @evanwashere reported this first awhile ago * [Bun.js] Implement `Object.is()` binding and a way to set a timeout for script execution * Update PLCrashReport.zig * [Bun.js] Make `console.log` more closely match Node.js and Deno * [Bun.js] Implement formatting specifier for console.* * Implement `console.clear()` * bug fix * Support console.clear() * Buffer stderr * [bun test] Begin implementing Node.js `fs` * Update darwin_c.zig * Implement more of `fs` * `mkdir`, `mkdir` recursive, `mkdtemp` * `open`, `read` (and pread) * Move some things into more files * Implement readdir * `readFile`, `readLink`, and `realpath` * `writeFile`, `symlink`, `chown`, `rename`, `stat`, `unlink`, `truncate` * `lutimes` * Implement `SystemError` and begin wiring up the `fs` module * `"fs"` - Most of the arguments / validation * `fs` - Rest of the arguments / validations * Begin wiring up the `fs` module * Fix all the build errors * support printing typed arrays in console.log * It...works? * Support `require("fs")`, `import fs from 'fs';`, `import * as fs from 'fs'` * Fix a couple bugs * get rid of the crash reporter for now * Update fs.exports.js * [bun.js] slight improvement to startup time * [bun.js] Improve error message printing * [Bun.js] Add `Bun.gc()` to run the garbage collector manually and report heap size * [Bun.js] Add Bun.generateHeapSnapshot to return what JS types are using memory * [Bun.js] Add `Bun.shrink()` to tell JSC to shrink the VM size * Improve encoding reader * [bun.js] Improve callback & microtask performance * Update node_fs.zig * Implement `console.assert` * simple test * [Bun.js] Prepare for multiple globals/realms to support testing * Create callbacks-overhead.mjs * Update http.zig * [Bun.js] Implement `queueMicrotask` * Add test for queueMicrotask * :sleepy: * [Bun.js] Implement `process.versions`, `process.pid`, `process.ppid`, `process.nextTick`, `process.versions`, * Implement `process.env.toJSON()` * [Bun.js] Improve performance of `fs.existsSync` * :nail_care: * [Bun.js] Implement `process.chdir(str)` and `process.cwd()`, support up to 4 args in `process.nextTick` * Make creating Zig::Process lazy * Split processi nto separte file * [Bun.js] Node.js Streams - Part 1/? * [Bun.js] Node.js streams 2/? * WIP streams * fix crash * Reduce allocations in many places * swap * Make `bun` start 2ms faster * Always use an apiLock() * libBacktrace doesn't really work yet * Fix crash in the upgrade checker * Clean up code for importing the runtime when not bundling * :camera: * Update linker.zig * 68! * backtrace * no, really backtrace * Fix * Linux fixes * Fixes on Linux * Update mimalloc * [bun test] Automatically scan for {.test,_test,.spec,_spec}.{jsx,tsx,js,cts,mts,ts,cjs}
Diffstat (limited to 'src/cli.zig')
-rw-r--r--src/cli.zig178
1 files changed, 124 insertions, 54 deletions
diff --git a/src/cli.zig b/src/cli.zig
index b17dc8396..40b59b928 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -36,30 +36,35 @@ const Router = @import("./router.zig");
const NodeModuleBundle = @import("./node_module_bundle.zig").NodeModuleBundle;
-const BunCommand = @import("./cli/bun_command.zig").BunCommand;
-const DevCommand = @import("./cli/dev_command.zig").DevCommand;
-const DiscordCommand = @import("./cli/discord_command.zig").DiscordCommand;
+const AddCommand = @import("./cli/add_command.zig").AddCommand;
const BuildCommand = @import("./cli/build_command.zig").BuildCommand;
+const BunCommand = @import("./cli/bun_command.zig").BunCommand;
const CreateCommand = @import("./cli/create_command.zig").CreateCommand;
const CreateListExamplesCommand = @import("./cli/create_command.zig").CreateListExamplesCommand;
-const RunCommand = @import("./cli/run_command.zig").RunCommand;
-const UpgradeCommand = @import("./cli/upgrade_command.zig").UpgradeCommand;
+const DevCommand = @import("./cli/dev_command.zig").DevCommand;
+const DiscordCommand = @import("./cli/discord_command.zig").DiscordCommand;
const InstallCommand = @import("./cli/install_command.zig").InstallCommand;
-const AddCommand = @import("./cli/add_command.zig").AddCommand;
-const RemoveCommand = @import("./cli/remove_command.zig").RemoveCommand;
-const PackageManagerCommand = @import("./cli/package_manager_command.zig").PackageManagerCommand;
const InstallCompletionsCommand = @import("./cli/install_completions_command.zig").InstallCompletionsCommand;
+const PackageManagerCommand = @import("./cli/package_manager_command.zig").PackageManagerCommand;
+const RemoveCommand = @import("./cli/remove_command.zig").RemoveCommand;
+const RunCommand = @import("./cli/run_command.zig").RunCommand;
const ShellCompletions = @import("./cli/shell_completions.zig");
+const TestCommand = @import("./cli/test_command.zig").TestCommand;
+const UpgradeCommand = @import("./cli/upgrade_command.zig").UpgradeCommand;
+const Reporter = @import("./report.zig");
var start_time: i128 = undefined;
pub const Cli = struct {
var wait_group: sync.WaitGroup = undefined;
+ var log_: logger.Log = undefined;
pub fn startTransform(_: std.mem.Allocator, _: Api.TransformOptions, _: *logger.Log) anyerror!void {}
- pub fn start(allocator: std.mem.Allocator, _: anytype, _: anytype, comptime MainPanicHandler: type) anyerror!void {
+ pub fn start(allocator: std.mem.Allocator, _: anytype, _: anytype, comptime MainPanicHandler: type) void {
start_time = std.time.nanoTimestamp();
- var log = try allocator.create(logger.Log);
- log.* = logger.Log.init(allocator);
+ log_ = logger.Log.init(allocator);
+
+ var log = &log_;
+
var panicker = MainPanicHandler.init(log);
MainPanicHandler.Singleton = &panicker;
@@ -71,7 +76,14 @@ pub const Cli = struct {
std.os.exit(1);
},
else => {
- return err;
+ // Always dump the logs
+ if (Output.enable_ansi_colors_stderr) {
+ log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true) catch {};
+ } else {
+ log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {};
+ }
+
+ Reporter.globalError(err);
},
}
};
@@ -84,7 +96,13 @@ const LoaderMatcher = strings.ExactSizeMatcher(4);
const ColonListType = @import("./cli/colon_list_type.zig").ColonListType;
pub const LoaderColonList = ColonListType(Api.Loader, Arguments.loader_resolver);
pub const DefineColonList = ColonListType(string, Arguments.noop_resolver);
-
+fn invalidPlatform(diag: *clap.Diagnostic, _platform: []const u8) noreturn {
+ @setCold(true);
+ diag.name.long = "--platform";
+ diag.arg = _platform;
+ diag.report(Output.errorWriter(), error.InvalidPlatform) catch {};
+ std.process.exit(1);
+}
pub const Arguments = struct {
pub fn loader_resolver(in: string) !Api.Loader {
const Matcher = strings.ExactSizeMatcher(4);
@@ -199,11 +217,16 @@ pub const Arguments = struct {
printVersionAndExit();
}
- var cwd_paths = [_]string{args.option("--cwd") orelse try std.process.getCwdAlloc(allocator)};
- var cwd = try std.fs.path.resolve(allocator, &cwd_paths);
+ var cwd: []u8 = undefined;
+ if (args.option("--cwd")) |cwd_| {
+ var cwd_paths = [_]string{cwd_};
+ cwd = try std.fs.path.resolve(allocator, &cwd_paths);
+ } else {
+ cwd = try std.process.getCwdAlloc(allocator);
+ }
var defines_tuple = try DefineColonList.resolve(allocator, args.options("--define"));
- var loader_tuple = try LoaderColonList.resolve(allocator, args.options("--define"));
+ var loader_tuple = try LoaderColonList.resolve(allocator, args.options("--loader"));
var externals = std.mem.zeroes([][]u8);
if (args.options("--external").len > 0) {
externals = try allocator.alloc([]u8, args.options("--external").len);
@@ -329,17 +352,19 @@ pub const Arguments = struct {
else => true,
};
- opts.node_modules_bundle_path = args.option("--bunfile") orelse brk: {
- const node_modules_bundle_path_absolute = resolve_path.joinAbs(cwd, .auto, "node_modules.bun");
+ if (comptime Command.Tag.cares_about_bun_file.get(cmd)) {
+ opts.node_modules_bundle_path = args.option("--bunfile") orelse brk: {
+ const node_modules_bundle_path_absolute = resolve_path.joinAbs(cwd, .auto, "node_modules.bun");
- break :brk std.fs.realpathAlloc(allocator, node_modules_bundle_path_absolute) catch null;
- };
+ break :brk std.fs.realpathAlloc(allocator, node_modules_bundle_path_absolute) catch null;
+ };
- opts.node_modules_bundle_path_server = args.option("--server-bunfile") orelse brk: {
- const node_modules_bundle_path_absolute = resolve_path.joinAbs(cwd, .auto, "node_modules.server.bun");
+ opts.node_modules_bundle_path_server = args.option("--server-bunfile") orelse brk: {
+ const node_modules_bundle_path_absolute = resolve_path.joinAbs(cwd, .auto, "node_modules.server.bun");
- break :brk std.fs.realpathAlloc(allocator, node_modules_bundle_path_absolute) catch null;
- };
+ break :brk std.fs.realpathAlloc(allocator, node_modules_bundle_path_absolute) catch null;
+ };
+ }
switch (comptime cmd) {
.AutoCommand, .DevCommand, .BuildCommand, .BunCommand => {
@@ -387,23 +412,12 @@ pub const Arguments = struct {
const PlatformMatcher = strings.ExactSizeMatcher(8);
if (args.option("--platform")) |_platform| {
- switch (PlatformMatcher.match(_platform)) {
- PlatformMatcher.case("browser") => {
- opts.platform = Api.Platform.browser;
- },
- PlatformMatcher.case("node") => {
- opts.platform = Api.Platform.node;
- },
- PlatformMatcher.case("macro"), PlatformMatcher.case("bun") => {
- opts.platform = Api.Platform.bun;
- },
- else => {
- diag.name.long = "--platform";
- diag.arg = _platform;
- try diag.report(Output.errorWriter(), error.InvalidPlatform);
- std.process.exit(1);
- },
- }
+ opts.platform = switch (PlatformMatcher.match(_platform)) {
+ PlatformMatcher.case("browser") => Api.Platform.browser,
+ PlatformMatcher.case("node") => Api.Platform.node,
+ PlatformMatcher.case("macro"), PlatformMatcher.case("bun") => Api.Platform.bun,
+ else => invalidPlatform(&diag, _platform),
+ };
}
if (jsx_factory != null or
@@ -577,22 +591,26 @@ pub const Command = struct {
pub const Context = struct {
start_time: i128,
- args: Api.TransformOptions = std.mem.zeroes(Api.TransformOptions),
+ args: Api.TransformOptions,
log: *logger.Log,
allocator: std.mem.Allocator,
positionals: []const string = &[_]string{},
debug: DebugOptions = DebugOptions{},
+ const _ctx = Command.Context{
+ .args = std.mem.zeroes(Api.TransformOptions),
+ .log = undefined,
+ .start_time = 0,
+ .allocator = undefined,
+ };
+
pub fn create(allocator: std.mem.Allocator, log: *logger.Log, comptime command: Command.Tag) anyerror!Context {
Cli.cmd = command;
-
- var ctx = Command.Context{
- .args = std.mem.zeroes(Api.TransformOptions),
- .log = log,
- .start_time = start_time,
- .allocator = allocator,
- };
+ var ctx = _ctx;
+ ctx.log = log;
+ ctx.start_time = start_time;
+ ctx.allocator = allocator;
if (comptime Command.Tag.uses_global_options.get(command)) {
ctx.args = try Arguments.parse(allocator, &ctx, command);
@@ -602,8 +620,27 @@ pub const Command = struct {
}
};
- pub fn which(allocator: std.mem.Allocator) Tag {
- var args_iter = std.process.args();
+ // std.process.args allocates!
+ const ArgsIterator = struct {
+ buf: [][*:0]u8 = undefined,
+ i: u32 = 0,
+
+ pub fn next(this: *ArgsIterator) ?[]const u8 {
+ if (this.buf.len <= this.i) {
+ return null;
+ }
+ const i = this.i;
+ this.i += 1;
+ return std.mem.span(this.buf[i]);
+ }
+
+ pub fn skip(this: *ArgsIterator) bool {
+ return this.next() != null;
+ }
+ };
+
+ pub fn which() Tag {
+ var args_iter = ArgsIterator{ .buf = std.os.argv };
// first one is the executable name
const skipped = args_iter.skip();
@@ -611,9 +648,9 @@ pub const Command = struct {
return .AutoCommand;
}
- var next_arg = ((args_iter.next(allocator) catch null) orelse return .AutoCommand);
+ var next_arg = ((args_iter.next()) orelse return .AutoCommand);
while (next_arg[0] == '-') {
- next_arg = ((args_iter.next(allocator) catch null) orelse return .AutoCommand);
+ next_arg = ((args_iter.next()) orelse return .AutoCommand);
}
const first_arg_name = std.mem.span(next_arg);
@@ -630,6 +667,8 @@ pub const Command = struct {
RootCommandMatcher.case("i"), RootCommandMatcher.case("install") => .InstallCommand,
RootCommandMatcher.case("c"), RootCommandMatcher.case("create") => .CreateCommand,
+ RootCommandMatcher.case(TestCommand.name) => .TestCommand,
+
RootCommandMatcher.case("pm") => .PackageManagerCommand,
RootCommandMatcher.case("add"), RootCommandMatcher.case("update"), RootCommandMatcher.case("a") => .AddCommand,
@@ -665,7 +704,7 @@ pub const Command = struct {
};
pub fn start(allocator: std.mem.Allocator, log: *logger.Log) !void {
- const tag = which(allocator);
+ const tag = which();
switch (tag) {
.DiscordCommand => return try DiscordCommand.exec(allocator),
.HelpCommand => return try HelpCommand.exec(allocator),
@@ -717,6 +756,12 @@ pub const Command = struct {
try PackageManagerCommand.exec(ctx);
return;
},
+ .TestCommand => {
+ const ctx = try Command.Context.create(allocator, log, .TestCommand);
+
+ try TestCommand.exec(ctx);
+ return;
+ },
.GetCompletionsCommand => {
const ctx = try Command.Context.create(allocator, log, .GetCompletionsCommand);
var filter = ctx.positionals;
@@ -881,6 +926,21 @@ pub const Command = struct {
const file_: std.fs.File.OpenError!std.fs.File = brk: {
if (script_name_to_search[0] == std.fs.path.sep) {
break :brk std.fs.openFileAbsolute(script_name_to_search, .{ .read = true });
+ } else if (!strings.hasPrefix(script_name_to_search, "..") and script_name_to_search[0] != '~') {
+ const file_pathZ = brk2: {
+ if (!strings.hasPrefix(file_path, "./")) {
+ script_name_buf[0..2].* = "./".*;
+ @memcpy(script_name_buf[2..], file_path.ptr, file_path.len);
+ script_name_buf[file_path.len + 2] = 0;
+ break :brk2 script_name_buf[0 .. file_path.len + 2 :0];
+ } else {
+ @memcpy(&script_name_buf, file_path.ptr, file_path.len);
+ script_name_buf[file_path.len] = 0;
+ break :brk2 script_name_buf[0..file_path.len :0];
+ }
+ };
+
+ break :brk std.fs.cwd().openFileZ(file_pathZ, .{ .read = true });
} else {
var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
const cwd = std.os.getcwd(&path_buf) catch break :possibly_open_with_bun_js;
@@ -954,6 +1014,16 @@ pub const Command = struct {
RunCommand,
UpgradeCommand,
PackageManagerCommand,
+ TestCommand,
+
+ pub const cares_about_bun_file: std.EnumArray(Tag, bool) = std.EnumArray(Tag, bool).initDefault(false, .{
+ .AutoCommand = true,
+ .BuildCommand = true,
+ .BunCommand = true,
+ .DevCommand = true,
+ .RunCommand = true,
+ .TestCommand = true,
+ });
pub const uses_global_options: std.EnumArray(Tag, bool) = std.EnumArray(Tag, bool).initDefault(true, .{
.CreateCommand = false,