From 3b63a7eff49236780f52f22c491c6353a60193b6 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Tue, 13 Aug 2024 10:34:40 -0400 Subject: [PATCH] Add `brew debugger` command --- .vscode/launch.json | 14 ++++++ Library/Homebrew/abstract_command.rb | 4 ++ Library/Homebrew/commands.rb | 9 ++++ Library/Homebrew/dev-cmd/debugger.rb | 45 +++++++++++++++++++ .../rbi/dsl/homebrew/dev_cmd/debugger.rbi | 25 +++++++++++ 5 files changed, 97 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 Library/Homebrew/dev-cmd/debugger.rb create mode 100644 Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/debugger.rbi diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..108f3d8486 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "rdbg", + "name": "Attach with rdbg", + "request": "attach", + "rdbgPath": "${workspaceFolder}/Library/Homebrew/vendor/portable-ruby/current/lib/ruby/gems/3.3.0/gems/debug-1.9.1/exe/rdbg", + "env": { + "TMPDIR": "/private/tmp/", + } + } + ] +} diff --git a/Library/Homebrew/abstract_command.rb b/Library/Homebrew/abstract_command.rb index 8fd46295ef..03b493c834 100644 --- a/Library/Homebrew/abstract_command.rb +++ b/Library/Homebrew/abstract_command.rb @@ -2,6 +2,7 @@ # frozen_string_literal: true require "cli/parser" +require "shell_command" module Homebrew # Subclass this to implement a `brew` command. This is preferred to declaring a named function in the `Homebrew` @@ -41,6 +42,9 @@ module Homebrew sig { returns(T::Boolean) } def dev_cmd? = T.must(name).start_with?("Homebrew::DevCmd") + sig { returns(T::Boolean) } + def ruby_cmd? = !include?(Homebrew::ShellCommand) + sig { returns(CLI::Parser) } def parser = CLI::Parser.new(self, &@parser_block) diff --git a/Library/Homebrew/commands.rb b/Library/Homebrew/commands.rb index 29fd1b9469..a96c5f15d7 100644 --- a/Library/Homebrew/commands.rb +++ b/Library/Homebrew/commands.rb @@ -41,6 +41,15 @@ module Commands require?(HOMEBREW_DEV_CMD_PATH/cmd) end + def self.valid_ruby_cmd?(cmd) + if (valid_internal_cmd?(cmd) || valid_internal_dev_cmd?(cmd) || external_ruby_v2_cmd_path(cmd)) && + (command = Homebrew::AbstractCommand.command(cmd)) + command.ruby_cmd? + else + false + end + end + def self.method_name(cmd) cmd.to_s .tr("-", "_") diff --git a/Library/Homebrew/dev-cmd/debugger.rb b/Library/Homebrew/dev-cmd/debugger.rb new file mode 100644 index 0000000000..545bdd91bf --- /dev/null +++ b/Library/Homebrew/dev-cmd/debugger.rb @@ -0,0 +1,45 @@ +# typed: strict +# frozen_string_literal: true + +module Homebrew + module DevCmd + class Debugger < AbstractCommand + cmd_args do + description <<~EOS + Run the specified Homebrew command in debug mode. + + To pass flags to the command, use `--` to separate them from the `brew` flags. + For example: `brew debugger -- list --formula`. + EOS + switch "-n", "--nonstop", + description: "Do not stop at the beginning of the script." + switch "-O", "--open", + description: "Start remote debugging over a Unix socket." + + named_args :command, min: 1 + end + + sig { override.void } + def run + unless Commands.valid_ruby_cmd?(args.named.first) + raise UsageError, "`#{args.named.first}` is not a valid Ruby command!" + end + + brew_rb = (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path + nonstop = "1" if args.nonstop? + debugger_method = if args.open? + "open" + else + "start" + end + + with_env RUBY_DEBUG_NONSTOP: nonstop, RUBY_DEBUG_FORK_MODE: "parent" do + system(*HOMEBREW_RUBY_EXEC_ARGS, + "-I", $LOAD_PATH.join(File::PATH_SEPARATOR), + "-rdebug/#{debugger_method}", + brew_rb, *args.named) + end + end + end + end +end diff --git a/Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/debugger.rbi b/Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/debugger.rbi new file mode 100644 index 0000000000..9c09f8a29b --- /dev/null +++ b/Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/debugger.rbi @@ -0,0 +1,25 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for dynamic methods in `Homebrew::DevCmd::Debugger`. +# Please instead update this file by running `bin/tapioca dsl Homebrew::DevCmd::Debugger`. + + +class Homebrew::DevCmd::Debugger + sig { returns(Homebrew::DevCmd::Debugger::Args) } + def args; end +end + +class Homebrew::DevCmd::Debugger::Args < Homebrew::CLI::Args + sig { returns(T::Boolean) } + def O?; end + + sig { returns(T::Boolean) } + def n?; end + + sig { returns(T::Boolean) } + def nonstop?; end + + sig { returns(T::Boolean) } + def open?; end +end