diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/install/install.zig | 108 | ||||
-rw-r--r-- | src/install/lockfile.zig | 118 | ||||
-rw-r--r-- | src/install/resolvers/folder_resolver.zig | 3 | ||||
-rw-r--r-- | src/json_parser.zig | 9 | ||||
-rw-r--r-- | src/report.zig | 12 |
5 files changed, 146 insertions, 104 deletions
diff --git a/src/install/install.zig b/src/install/install.zig index 3034b82f8..ee46ad079 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -767,11 +767,10 @@ const PackageInstall = struct { resolution: *const Resolution, buf: []const u8, ) bool { - if (resolution.tag == .github) { - return this.verifyGitHubResolution(resolution, buf); - } - - return this.verifyPackageJSONNameAndVersion(); + return switch (resolution.tag) { + .github => this.verifyGitHubResolution(resolution, buf), + else => this.verifyPackageJSONNameAndVersion(), + }; } fn verifyPackageJSONNameAndVersion(this: *PackageInstall) bool { @@ -1026,7 +1025,7 @@ const PackageInstall = struct { progress_.refresh(); Output.prettyErrorln("<r><red>{s}<r>: copying file {s}", .{ @errorName(err), entry.path }); - Global.exit(1); + Global.crash(); }; }; defer outfile.close(); @@ -1043,7 +1042,7 @@ const PackageInstall = struct { progress_.refresh(); Output.prettyErrorln("<r><red>{s}<r>: copying file {s}", .{ @errorName(err), entry.path }); - Global.exit(1); + Global.crash(); }; } @@ -1222,8 +1221,8 @@ const PackageInstall = struct { }; } - pub fn uninstall(this: *PackageInstall) !void { - try this.destination_dir.dir.deleteTree(bun.span(this.destination_dir_subpath)); + pub fn uninstall(this: *PackageInstall) void { + this.destination_dir.dir.deleteTree(bun.span(this.destination_dir_subpath)) catch {}; } fn isDanglingSymlink(path: [:0]const u8) bool { @@ -1253,7 +1252,7 @@ const PackageInstall = struct { const dest_path = this.destination_dir_subpath; // If this fails, we don't care. // we'll catch it the next error - if (!skip_delete and !strings.eqlComptime(dest_path, ".")) this.uninstall() catch {}; + if (!skip_delete and !strings.eqlComptime(dest_path, ".")) this.uninstall(); const subdir = std.fs.path.dirname(dest_path); var dest_dir = if (subdir) |dir| brk: { @@ -1309,7 +1308,7 @@ const PackageInstall = struct { // If this fails, we don't care. // we'll catch it the next error - if (!skip_delete and !strings.eqlComptime(this.destination_dir_subpath, ".")) this.uninstall() catch {}; + if (!skip_delete and !strings.eqlComptime(this.destination_dir_subpath, ".")) this.uninstall(); var supported_method_to_use = if (strings.eqlComptime(this.cache_dir_subpath, ".") or strings.hasPrefixComptime(this.cache_dir_subpath, "..")) Method.symlink @@ -1883,7 +1882,7 @@ pub const PackageManager = struct { return cachedGitHubFolderNamePrint(&cached_package_folder_name_buf, this.lockfile.str(&repository.resolved)); } - pub fn cachedGitHubFolderNamePrintGuess(buf: []u8, string_buf: []const u8, repository: *const Repository) stringZ { + fn cachedGitHubFolderNamePrintGuess(buf: []u8, string_buf: []const u8, repository: *const Repository) stringZ { return std.fmt.bufPrintZ( buf, "@GH@{any}-{any}-{any}", @@ -3027,9 +3026,8 @@ pub const PackageManager = struct { ); var package = Lockfile.Package{}; - Lockfile.Package.parse( + package.parse( manager.lockfile, - &package, manager.allocator, manager.log, package_json_source, @@ -3043,7 +3041,7 @@ pub const PackageManager = struct { if (comptime log_level != .silent) { const string_buf = manager.lockfile.buffers.string_bytes.items; Output.prettyErrorln("<r><red>error:<r> expected package.json in <b>{any}<r> to be a JSON file: {s}\n", .{ - package.resolution.fmtURL(&manager.options, string_buf), + resolution.fmtURL(&manager.options, string_buf), @errorName(err), }); } @@ -4668,7 +4666,7 @@ pub const PackageManager = struct { var lockfile: Lockfile = undefined; var name: string = ""; - var package: Lockfile.Package = Lockfile.Package{}; + var package = Lockfile.Package{}; // Step 1. parse the nearest package.json file { @@ -4685,18 +4683,20 @@ pub const PackageManager = struct { ); try lockfile.initEmpty(ctx.allocator); - try Lockfile.Package.parseMain(&lockfile, &package, ctx.allocator, manager.log, package_json_source, Features.folder); + try package.parseMain(&lockfile, ctx.allocator, manager.log, package_json_source, Features.folder); name = lockfile.str(&package.name); if (name.len == 0) { - if (manager.options.log_level != .silent) + if (manager.options.log_level != .silent) { Output.prettyErrorln("<r><red>error:<r> package.json missing \"name\" <d>in \"{s}\"<r>", .{package_json_source.path.text}); + } Global.crash(); } else if (!strings.isNPMPackageName(name)) { - if (manager.options.log_level != .silent) - Output.prettyErrorln("<r><red>error:<r> invalid package.json name \"{s}\" <d>in \"{s}\"<r>", .{ + if (manager.options.log_level != .silent) { + Output.prettyErrorln("<r><red>error:<r> invalid package.json name \"{s}\" <d>in \"{any}\"<r>", .{ name, package_json_source.path.text, }); + } Global.crash(); } } @@ -4830,7 +4830,7 @@ pub const PackageManager = struct { var lockfile: Lockfile = undefined; var name: string = ""; - var package: Lockfile.Package = Lockfile.Package{}; + var package = Lockfile.Package{}; // Step 1. parse the nearest package.json file { @@ -4847,18 +4847,20 @@ pub const PackageManager = struct { ); try lockfile.initEmpty(ctx.allocator); - try Lockfile.Package.parseMain(&lockfile, &package, ctx.allocator, manager.log, package_json_source, Features.folder); + try package.parseMain(&lockfile, ctx.allocator, manager.log, package_json_source, Features.folder); name = lockfile.str(&package.name); if (name.len == 0) { - if (manager.options.log_level != .silent) + if (manager.options.log_level != .silent) { Output.prettyErrorln("<r><red>error:<r> package.json missing \"name\" <d>in \"{s}\"<r>", .{package_json_source.path.text}); + } Global.crash(); } else if (!strings.isNPMPackageName(name)) { - if (manager.options.log_level != .silent) + if (manager.options.log_level != .silent) { Output.prettyErrorln("<r><red>error:<r> invalid package.json name \"{s}\" <d>in \"{s}\"<r>", .{ name, package_json_source.path.text, }); + } Global.crash(); } } @@ -4922,7 +4924,7 @@ pub const PackageManager = struct { Global.exit(0); } else { Output.prettyln("<r><red>error:<r> bun unlink {{packageName}} not implemented yet", .{}); - Global.exit(1); + Global.crash(); } } @@ -5102,7 +5104,7 @@ pub const PackageManager = struct { // cli.omit.peer = true; // } else { // Output.prettyErrorln("<b>error<r><d>:<r> Invalid argument <b>\"--omit\"<r> must be one of <cyan>\"dev\"<r>, <cyan>\"optional\"<r>, or <cyan>\"peer\"<r>. ", .{}); - // Global.exit(1); + // Global.crash(); // } // } @@ -5208,7 +5210,7 @@ pub const PackageManager = struct { Output.prettyErrorln("<r><red>error<r><d>:<r> unrecognised dependency format: {s}", .{ positional, }); - Global.exit(1); + Global.crash(); }; if (switch (version.tag) { .dist_tag => version.value.dist_tag.name.eql(placeholder, input, input), @@ -5218,7 +5220,7 @@ pub const PackageManager = struct { Output.prettyErrorln("<r><red>error<r><d>:<r> unrecognised dependency format: {s}", .{ positional, }); - Global.exit(1); + Global.crash(); } var request = UpdateRequest{ @@ -5461,12 +5463,10 @@ pub const PackageManager = struct { if (op == .remove) { if (current_package_json.data != .e_object) { Output.prettyErrorln("<red>error<r><d>:<r> package.json is not an Object {{}}, so there's nothing to remove!", .{}); - Global.exit(1); - return; + Global.crash(); } else if (current_package_json.data.e_object.properties.len == 0) { Output.prettyErrorln("<red>error<r><d>:<r> package.json is empty {{}}, so there's nothing to remove!", .{}); - Global.exit(1); - return; + Global.crash(); } else if (current_package_json.asProperty("devDependencies") == null and current_package_json.asProperty("dependencies") == null and current_package_json.asProperty("optionalDependencies") == null and @@ -5474,7 +5474,6 @@ pub const PackageManager = struct { { Output.prettyErrorln("package.json doesn't have dependencies, there's nothing to remove!", .{}); Global.exit(0); - return; } } @@ -5959,8 +5958,8 @@ pub const PackageManager = struct { } if (this.manager.options.enable.fail_early) { - installer.uninstall() catch {}; - Global.exit(1); + installer.uninstall(); + Global.crash(); } } } @@ -6337,9 +6336,7 @@ pub const PackageManager = struct { } } - if (this.options.enable.fail_early) { - Global.exit(1); - } + if (this.options.enable.fail_early) Global.crash(); } continue :outer; @@ -6460,7 +6457,7 @@ pub const PackageManager = struct { Output.flush(); } - if (manager.options.enable.fail_early) Global.exit(1); + if (manager.options.enable.fail_early) Global.crash(); }, .ok => { differ: { @@ -6479,9 +6476,8 @@ pub const PackageManager = struct { try lockfile.initEmpty(ctx.allocator); var maybe_root = Lockfile.Package{}; - try Lockfile.Package.parseMain( + try maybe_root.parseMain( &lockfile, - &maybe_root, ctx.allocator, ctx.log, package_json_source, @@ -6504,11 +6500,10 @@ pub const PackageManager = struct { had_any_diffs = had_any_diffs or sum > 0; if (manager.options.enable.frozen_lockfile and had_any_diffs) { - if (log_level != .silent) { + if (comptime log_level != .silent) { Output.prettyErrorln("<r><red>error<r>: lockfile had changes, but lockfile is frozen", .{}); } - - Global.exit(1); + Global.crash(); } // If you changed packages, we will copy over the new package from the new lockfile @@ -6591,16 +6586,14 @@ pub const PackageManager = struct { try manager.lockfile.initEmpty(ctx.allocator); if (manager.options.enable.frozen_lockfile) { - if (log_level != .silent) { + if (comptime log_level != .silent) { Output.prettyErrorln("<r><red>error<r>: lockfile had changes, but lockfile is frozen", .{}); } - - Global.exit(1); + Global.crash(); } - try Lockfile.Package.parseMain( + try root.parseMain( manager.lockfile, - &root, ctx.allocator, ctx.log, package_json_source, @@ -6615,10 +6608,7 @@ pub const PackageManager = struct { _ = manager.getCacheDirectory(); _ = manager.getTemporaryDirectory(); } - manager.enqueueDependencyList( - root.dependencies, - true, - ); + manager.enqueueDependencyList(root.dependencies, true); } manager.flushDependencyQueue(); @@ -6644,10 +6634,10 @@ pub const PackageManager = struct { *PackageManager, manager, .{ - .onExtract = void{}, - .onResolve = void{}, - .onPackageManifestError = void{}, - .onPackageDownloadError = void{}, + .onExtract = {}, + .onResolve = {}, + .onPackageManifestError = {}, + .onPackageDownloadError = {}, .progress_bar = true, }, log_level, @@ -6668,9 +6658,7 @@ pub const PackageManager = struct { try manager.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false); } - if (manager.log.errors > 0) { - Global.exit(1); - } + if (manager.log.errors > 0) Global.crash(); const needs_clean_lockfile = had_any_diffs or needs_new_lockfile or manager.package_json_updates.len > 0; var did_meta_hash_change = needs_clean_lockfile; diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig index cb4326699..eb0ca6c3a 100644 --- a/src/install/lockfile.zig +++ b/src/install/lockfile.zig @@ -889,15 +889,13 @@ pub const Printer = struct { try log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false); } } - Global.exit(1); - return; + Global.crash(); }, .not_found => { Output.prettyErrorln("<r><red>lockfile not found:<r> {s}", .{ std.mem.span(lockfile_path), }); - Global.exit(1); - return; + Global.crash(); }, .ok => {}, @@ -1372,9 +1370,7 @@ pub fn verifyResolutions(this: *Lockfile, local_features: Features, remote_featu } } - if (any_failed) { - Global.exit(1); - } + if (any_failed) Global.crash(); } pub fn saveToDisk(this: *Lockfile, filename: stringZ) void { @@ -2281,19 +2277,19 @@ pub const Package = extern struct { } pub fn parseMain( - lockfile: *Lockfile, package: *Lockfile.Package, + lockfile: *Lockfile, allocator: std.mem.Allocator, log: *logger.Log, source: logger.Source, comptime features: Features, ) !void { - return parse(lockfile, package, allocator, log, source, void, void{}, features); + return package.parse(lockfile, allocator, log, source, void, void{}, features); } pub fn parse( - lockfile: *Lockfile, package: *Lockfile.Package, + lockfile: *Lockfile, allocator: std.mem.Allocator, log: *logger.Log, source: logger.Source, @@ -2303,10 +2299,7 @@ pub const Package = extern struct { ) !void { initializeStore(); - // A valid package.json always has "{}" characters - if (source.contents.len < 2) return error.InvalidPackageJSON; - - var json = json_parser.ParseJSONUTF8(&source, log, allocator) catch |err| { + const json = json_parser.ParseJSONUTF8(&source, log, allocator) catch |err| { if (Output.enable_ansi_colors) { log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true) catch {}; } else { @@ -2314,11 +2307,10 @@ pub const Package = extern struct { } Output.prettyErrorln("<r><red>{s}<r> parsing package.json in <b>\"{s}\"<r>", .{ @errorName(err), source.path.prettyDir() }); - Global.exit(1); + Global.crash(); }; - try parseWithJSON( - package, + try package.parseWithJSON( lockfile, allocator, log, @@ -2398,7 +2390,12 @@ pub const Package = extern struct { ); dependency_version.value.workspace = path; var workspace_entry = try lockfile.workspace_paths.getOrPut(allocator, @truncate(u32, external_name.hash)); - if (workspace_entry.found_existing) return error.@"Workspace name already exists"; + if (workspace_entry.found_existing) { + log.addErrorFmt(&source, key.loc, allocator, "Workspace name \"{s}\" already exists", .{ + external_name.slice(buf), + }) catch {}; + return error.InstallFailed; + } workspace_entry.value_ptr.* = path; }, else => {}, @@ -2593,6 +2590,15 @@ pub const Package = extern struct { if (json.asProperty(group.prop)) |dependencies_q| brk: { switch (dependencies_q.expr.data) { .e_array => |arr| { + if (!group.behavior.isWorkspace()) { + log.addErrorFmt(&source, dependencies_q.loc, allocator, + \\{0s} expects a map of specifiers, e.g. + \\"{0s}": {{ + \\ "bun": "latest" + \\}} + , .{group.prop}) catch {}; + return error.InvalidPackageJSON; + } if (arr.items.len == 0) break :brk; workspace_names = try allocator.alloc(string, arr.items.len); @@ -2604,7 +2610,15 @@ pub const Package = extern struct { for (arr.slice()) |item, i| { defer fallback.fixed_buffer_allocator.reset(); - const path = item.asString(allocator) orelse return error.InvalidPackageJSON; + const path = item.asString(allocator) orelse { + log.addErrorFmt(&source, item.loc, allocator, + \\Workspaces expects an array of strings, e.g. + \\"workspaces": [ + \\ "path/to/package" + \\] + , .{}) catch {}; + return error.InvalidPackageJSON; + }; var workspace_dir = std.fs.cwd().openIterableDir(path, .{}) catch |err| { if (err == error.FileNotFound) { @@ -2661,7 +2675,17 @@ pub const Package = extern struct { var workspace_json = try json_parser.PackageJSONVersionChecker.init(allocator, &workspace_source, log); _ = try workspace_json.parseExpr(); - if (!workspace_json.has_found_name) return error.InvalidPackageJSON; + if (!workspace_json.has_found_name) { + log.addErrorFmt( + &source, + dependencies_q.loc, + allocator, + "Missing \"name\" from package.json in {s}", + .{workspace_source.path.text}, + ) catch {}; + // report errors for multiple workspaces + continue; + } const workspace_name = workspace_json.found_name; @@ -2671,15 +2695,38 @@ pub const Package = extern struct { workspace_names[i] = try allocator.dupe(u8, workspace_name); } - if (orig_msgs_len != log.msgs.items.len) { - return error.InstallFailed; - } + if (orig_msgs_len != log.msgs.items.len) return error.InstallFailed; total_dependencies_count += @truncate(u32, arr.items.len); }, .e_object => |obj| { + if (group.behavior.isWorkspace()) { + log.addErrorFmt(&source, dependencies_q.loc, allocator, + \\Workspaces expects an array of strings, e.g. + \\"workspaces": [ + \\ "path/to/package" + \\] + , .{}) catch {}; + return error.InvalidPackageJSON; + } for (obj.properties.slice()) |item| { - const key = item.key.?.asString(allocator) orelse return error.InvalidPackageJSON; - const value = item.value.?.asString(allocator) orelse return error.InvalidPackageJSON; + const key = item.key.?.asString(allocator) orelse { + log.addErrorFmt(&source, item.key.?.loc, allocator, + \\{0s} expects a map of specifiers, e.g. + \\"{0s}": {{ + \\ "bun": "latest" + \\}} + , .{group.prop}) catch {}; + return error.InvalidPackageJSON; + }; + const value = item.value.?.asString(allocator) orelse { + log.addErrorFmt(&source, item.value.?.loc, allocator, + \\{0s} expects a map of specifiers, e.g. + \\"{0s}": {{ + \\ "bun": "latest" + \\}} + , .{group.prop}) catch {}; + return error.InvalidPackageJSON; + }; string_builder.count(key); string_builder.count(value); @@ -2691,7 +2738,24 @@ pub const Package = extern struct { } total_dependencies_count += @truncate(u32, obj.properties.len); }, - else => {}, + else => { + if (group.behavior.isWorkspace()) { + log.addErrorFmt(&source, dependencies_q.loc, allocator, + \\Workspaces expects an array of strings, e.g. + \\"workspaces": [ + \\ "path/to/package" + \\] + , .{}) catch {}; + } else { + log.addErrorFmt(&source, dependencies_q.loc, allocator, + \\{0s} expects a map of specifiers, e.g. + \\"{0s}": {{ + \\ "bun": "latest" + \\}} + , .{group.prop}) catch {}; + } + return error.InvalidPackageJSON; + }, } } } @@ -2899,7 +2963,7 @@ pub const Package = extern struct { } } }, - else => {}, + else => unreachable, } } } diff --git a/src/install/resolvers/folder_resolver.zig b/src/install/resolvers/folder_resolver.zig index f525ee613..968ee57ca 100644 --- a/src/install/resolvers/folder_resolver.zig +++ b/src/install/resolvers/folder_resolver.zig @@ -149,9 +149,8 @@ pub const FolderResolution = union(Tag) { const source = logger.Source.initPathString(abs, body.data.list.items[0..source_buf]); - try Lockfile.Package.parse( + try package.parse( manager.lockfile, - &package, manager.allocator, manager.log, source, diff --git a/src/json_parser.zig b/src/json_parser.zig index fb3b7dedf..b420cbd43 100644 --- a/src/json_parser.zig +++ b/src/json_parser.zig @@ -318,15 +318,6 @@ fn JSONLikeParser_( } try p.lexer.unexpected(); - if (comptime Environment.isDebug) { - std.io.getStdErr().writer().print("\nThis range: {d} - {d} \n{s}", .{ - p.lexer.range().loc.start, - p.lexer.range().end().start, - p.lexer.range().in(p.lexer.source.contents), - }) catch {}; - - @breakpoint(); - } return error.ParserError; }, } diff --git a/src/report.zig b/src/report.zig index c8c1304b6..62b807f0e 100644 --- a/src/report.zig +++ b/src/report.zig @@ -336,7 +336,7 @@ pub noinline fn globalError(err: anyerror) noreturn { ); Global.exit(1); }, - error.InvalidArgument, error.InstallFailed => { + error.InvalidArgument, error.InstallFailed, error.InvalidPackageJSON => { Global.exit(1); }, error.SystemFdQuotaExceeded => { @@ -349,7 +349,7 @@ pub noinline fn globalError(err: anyerror) noreturn { \\<d>Current limit: {d}<r> \\ \\To fix this, try running: - \\ + \\ \\ <cyan>sudo launchctl limit maxfiles 2147483646<r> \\ <cyan>ulimit -n 2147483646<r> \\ @@ -368,7 +368,7 @@ pub noinline fn globalError(err: anyerror) noreturn { \\<d>Current limit: {d}<r> \\ \\To fix this, try running: - \\ + \\ \\ <cyan>sudo echo -e "\nfs.file-max=2147483646\n" >> /etc/sysctl.conf<r> \\ <cyan>sudo sysctl -p<r> \\ <cyan>ulimit -n 2147483646<r> @@ -410,7 +410,7 @@ pub noinline fn globalError(err: anyerror) noreturn { \\<d>Current limit: {d}<r> \\ \\To fix this, try running: - \\ + \\ \\ <cyan>ulimit -n 2147483646<r> \\ \\You may also need to run: @@ -430,7 +430,7 @@ pub noinline fn globalError(err: anyerror) noreturn { \\<d>Current limit: {d}<r> \\ \\To fix this, try running: - \\ + \\ \\ <cyan>ulimit -n 2147483646<r> \\ \\That will only work for the current shell. To fix this for the entire system, run: @@ -474,7 +474,7 @@ pub noinline fn globalError(err: anyerror) noreturn { \\<d>Current limit: {d}<r> \\ \\To fix this, try running: - \\ + \\ \\ <cyan>ulimit -n 2147483646<r> \\ , |