From b3ecd91f9739f2aca529c85fcb70ebb0b2349519 Mon Sep 17 00:00:00 2001 From: Eric Knibbe Date: Mon, 31 Jul 2023 20:26:29 -0400 Subject: [PATCH] dev-cmd/edit: suggest tapping core repositories --- Library/Homebrew/cask/cask_loader.rb | 2 +- Library/Homebrew/cli/named_args.rb | 15 +++-- Library/Homebrew/dev-cmd/edit.rb | 76 ++++++++++++++---------- Library/Homebrew/exceptions.rb | 16 ++++- Library/Homebrew/formulary.rb | 3 +- Library/Homebrew/test/exceptions_spec.rb | 2 +- completions/bash/brew | 1 + completions/fish/brew.fish | 3 +- completions/zsh/_brew | 6 +- docs/Manpage.md | 6 +- manpages/brew.1 | 4 +- 11 files changed, 85 insertions(+), 49 deletions(-) diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index a54085b217c50..bcf12b04d2986 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -244,7 +244,7 @@ def self.can_load?(ref) def initialize(token, from_json: nil) @token = token.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "") - @path = CaskLoader.default_path(token) + @path = CaskLoader.default_path(@token) @from_json = from_json end diff --git a/Library/Homebrew/cli/named_args.rb b/Library/Homebrew/cli/named_args.rb index 0e92f1aefddfa..37ffa4bbcb315 100644 --- a/Library/Homebrew/cli/named_args.rb +++ b/Library/Homebrew/cli/named_args.rb @@ -228,8 +228,9 @@ def to_resolved_formulae_to_casks(only: parent&.only_formula_or_cask) def to_paths(only: parent&.only_formula_or_cask, recurse_tap: false) @to_paths ||= {} @to_paths[only] ||= downcased_unique_named.flat_map do |name| + path = Pathname(name) if File.exist?(name) - Pathname(name) + path elsif name.count("/") == 1 && !name.start_with?("./", "/") tap = Tap.fetch(name) @@ -248,10 +249,16 @@ def to_paths(only: parent&.only_formula_or_cask, recurse_tap: false) paths = [] - paths << formula_path if formula_path.exist? - paths << cask_path if cask_path.exist? + if formula_path.exist? || + (!CoreTap.instance.installed? && Homebrew::API::Formula.all_formulae.key?(path.basename)) + paths << formula_path + end + if cask_path.exist? || + (!CoreCaskTap.instance.installed? && Homebrew::API::Cask.all_casks.key?(path.basename)) + paths << cask_path + end - paths.empty? ? Pathname(name) : paths + paths.empty? ? path : paths end end.uniq.freeze end diff --git a/Library/Homebrew/dev-cmd/edit.rb b/Library/Homebrew/dev-cmd/edit.rb index 30be090fece6d..2690cbfe52960 100644 --- a/Library/Homebrew/dev-cmd/edit.rb +++ b/Library/Homebrew/dev-cmd/edit.rb @@ -11,8 +11,8 @@ module Homebrew def edit_args Homebrew::CLI::Parser.new do description <<~EOS - Open a or in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, - or open the Homebrew repository for editing if no formula is provided. + Open a , or in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, + or open the Homebrew repository for editing if no argument is provided. EOS switch "--formula", "--formulae", @@ -24,7 +24,7 @@ def edit_args conflicts "--formula", "--cask" - named_args [:formula, :cask], without_api: true + named_args [:formula, :cask, :tap], without_api: true end end @@ -50,42 +50,56 @@ def edit [HOMEBREW_REPOSITORY] end else + edit_api_message_displayed = T.let(false, T::Boolean) args.named.to_paths.select do |path| - next path if path.exist? + core_formula_path = path.fnmatch?("**/homebrew-core/Formula/**.rb", File::FNM_DOTMATCH) + core_cask_path = path.fnmatch?("**/homebrew-cask/Casks/**.rb", File::FNM_DOTMATCH) + core_formula_tap = path == CoreTap.instance.path + core_cask_tap = path == CoreCaskTap.instance.path - not_exist_message = if args.cask? - "#{path.basename(".rb")} doesn't exist on disk." - else - "#{path} doesn't exist on disk." + if path.exist? + if (core_formula_path || core_cask_path || core_formula_tap || core_cask_tap) && + !edit_api_message_displayed && + !Homebrew::EnvConfig.no_install_from_api? && + !Homebrew::EnvConfig.no_env_hints? + opoo <<~EOS + Unless `HOMEBREW_NO_INSTALL_FROM_API` is set when running `brew install`, + it will ignore any locally edited #{(core_cask_path || core_cask_tap) ? "casks" : "formulae"}. + EOS + edit_api_message_displayed = true + end + next path end - message = if args.cask? - <<~EOS - #{not_exist_message} - Run #{Formatter.identifier("brew create --cask --set-name #{path.basename(".rb")} $URL")} \ - to create a new cask! - EOS + name = path.basename(".rb").to_s + + if (tap_match = Regexp.new(HOMEBREW_TAP_DIR_REGEX.source + /$/.source).match(path.to_s)) + raise TapUnavailableError, CoreTap.instance.name if core_formula_tap + raise TapUnavailableError, CoreCaskTap.instance.name if core_cask_tap + + raise TapUnavailableError, "#{tap_match[:user]}/#{tap_match[:repo]}" + elsif args.cask? || core_cask_path + if !CoreCaskTap.instance.installed? && Homebrew::API::Cask.all_casks.key?(name) + command = "brew tap --force #{CoreCaskTap.instance.name}" + action = "tap #{CoreCaskTap.instance.name}" + else + command = "brew create --cask --set-name #{name} $URL" + action = "create a new cask" + end + elsif core_formula_path && !CoreTap.instance.installed? && Homebrew::API::Formula.all_formulae.key?(name) + command = "brew tap --force #{CoreTap.instance.name}" + action = "tap #{CoreTap.instance.name}" else - <<~EOS - #{not_exist_message} - Run #{Formatter.identifier("brew create --set-name #{path.basename} $URL")} \ - to create a new formula! - EOS + command = "brew create --set-name #{name} $URL" + action = "create a new formula" end - raise UsageError, message - end.presence - end - - if !Homebrew::EnvConfig.no_install_from_api? && !Homebrew::EnvConfig.no_env_hints? - paths.each do |path| - next if !path.fnmatch?("**/homebrew-core/Formula/*.rb") && !path.fnmatch?("**/homebrew-cask/Casks/*.rb") - opoo <<~EOS - Unless `HOMEBREW_NO_INSTALL_FROM_API` is set when running - `brew install`, it will ignore your locally edited formula. + message = <<~EOS + #{name} doesn't exist on disk. + Run #{Formatter.identifier(command)} to #{action}! EOS - break - end + raise UsageError, message + end.presence end if args.print_path? diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 18bdd2d34112c..3845ce1d7c798 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -304,9 +304,19 @@ class TapUnavailableError < RuntimeError def initialize(name) @name = name - super <<~EOS - No available tap #{name}. - EOS + message = "No available tap #{name}.\n" + if [CoreTap.instance.name, CoreCaskTap.instance.name].include?(name) + command = "brew tap --force #{name}" + message += <<~EOS + Run #{Formatter.identifier(command)} to tap #{name}! + EOS + else + command = "brew tap-new #{name}" + message += <<~EOS + Run #{Formatter.identifier(command)} to create a new #{name} tap! + EOS + end + super message.freeze end end diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 675047abd07f6..bcc7e313f07a4 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -1004,7 +1004,8 @@ def self.tap_paths(name, taps = Tap) end def self.find_formula_in_tap(name, tap) - filename = "#{name}.rb" + filename = name.dup + filename << ".rb" unless filename.end_with?(".rb") Tap.formula_files_by_name(tap).fetch(filename, tap.formula_dir/filename) end diff --git a/Library/Homebrew/test/exceptions_spec.rb b/Library/Homebrew/test/exceptions_spec.rb index 984a520cf1467..3921f2c2e4d8f 100644 --- a/Library/Homebrew/test/exceptions_spec.rb +++ b/Library/Homebrew/test/exceptions_spec.rb @@ -131,7 +131,7 @@ class Baz < Formula; end describe TapUnavailableError do subject { described_class.new("foo") } - its(:to_s) { is_expected.to eq("No available tap foo.\n") } + its(:to_s) { is_expected.to eq("No available tap foo.\nRun brew tap-new foo to create a new foo tap!\n") } end describe TapAlreadyTappedError do diff --git a/completions/bash/brew b/completions/bash/brew index 1eb0e574acc10..399e844e737e4 100644 --- a/completions/bash/brew +++ b/completions/bash/brew @@ -927,6 +927,7 @@ _brew_edit() { esac __brew_complete_formulae __brew_complete_casks + __brew_complete_tapped } _brew_environment() { diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index 09aca9ec8b8fb..ea011bf9a86e0 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -670,7 +670,7 @@ __fish_brew_complete_arg 'dr' -l verbose -d 'Make some output more verbose' __fish_brew_complete_arg 'dr' -a '(__fish_brew_suggest_diagnostic_checks)' -__fish_brew_complete_cmd 'edit' 'Open a formula or cask in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no formula is provided' +__fish_brew_complete_cmd 'edit' 'Open a formula, cask or tap in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument is provided' __fish_brew_complete_arg 'edit' -l cask -d 'Treat all named arguments as casks' __fish_brew_complete_arg 'edit' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'edit' -l formula -d 'Treat all named arguments as formulae' @@ -680,6 +680,7 @@ __fish_brew_complete_arg 'edit' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'edit' -l verbose -d 'Make some output more verbose' __fish_brew_complete_arg 'edit; and not __fish_seen_argument -l cask -l casks' -a '(__fish_brew_suggest_formulae_all)' __fish_brew_complete_arg 'edit; and not __fish_seen_argument -l formula -l formulae' -a '(__fish_brew_suggest_casks_all)' +__fish_brew_complete_arg 'edit' -a '(__fish_brew_suggest_taps_installed)' __fish_brew_complete_cmd 'environment' 'Summarise Homebrew\'s build environment as a plain list' diff --git a/completions/zsh/_brew b/completions/zsh/_brew index 1ea75dcdf7d5c..8fc52f55ac3f7 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -164,7 +164,7 @@ __brew_internal_commands() { 'dispatch-build-bottle:Build bottles for these formulae with GitHub Actions' 'docs:Open Homebrew'\''s online documentation (https://docs.brew.sh) in a browser' 'doctor:Check your system for potential problems' - 'edit:Open a formula or cask in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no formula is provided' + 'edit:Open a formula, cask or tap in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument is provided' 'extract:Look through repository history to find the most recent version of formula and create a copy in tap' 'fetch:Download a bottle (if available) or source packages for formulae and binaries for casks' 'formula:Display the path where formula is located' @@ -853,7 +853,9 @@ _brew_edit() { '*::formula:__brew_formulae' \ - cask \ '(--formula)--cask[Treat all named arguments as casks]' \ - '*::cask:__brew_casks' + '*::cask:__brew_casks' \ + - tap \ + '*::tap:__brew_any_tap' } # brew environment diff --git a/docs/Manpage.md b/docs/Manpage.md index 8bd304b152014..d4059e01e2c18 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -1240,10 +1240,10 @@ Build bottles for these formulae with GitHub Actions. * `--linux-wheezy`: Use Debian Wheezy container for building the bottle on Linux. -### `edit` [*`options`*] [*`formula`*|*`cask`* ...] +### `edit` [*`options`*] [*`formula`*|*`cask`*|*`tap`* ...] -Open a *`formula`* or *`cask`* in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, -or open the Homebrew repository for editing if no formula is provided. +Open a *`formula`*, *`cask`* or *`tap`* in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, +or open the Homebrew repository for editing if no argument is provided. * `--formula`: Treat all named arguments as formulae. diff --git a/manpages/brew.1 b/manpages/brew.1 index 2eeb559384273..fb25c6f94c874 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1804,8 +1804,8 @@ Dispatch bottle for Linux (using self\-hosted runner)\. \fB\-\-linux\-wheezy\fR Use Debian Wheezy container for building the bottle on Linux\. . -.SS "\fBedit\fR [\fIoptions\fR] [\fIformula\fR|\fIcask\fR \.\.\.]" -Open a \fIformula\fR or \fIcask\fR in the editor set by \fBEDITOR\fR or \fBHOMEBREW_EDITOR\fR, or open the Homebrew repository for editing if no formula is provided\. +.SS "\fBedit\fR [\fIoptions\fR] [\fIformula\fR|\fIcask\fR|\fItap\fR \.\.\.]" +Open a \fIformula\fR, \fIcask\fR or \fItap\fR in the editor set by \fBEDITOR\fR or \fBHOMEBREW_EDITOR\fR, or open the Homebrew repository for editing if no argument is provided\. . .TP \fB\-\-formula\fR