From d84fac5af467a4742249c5d816aa6840cac9cebb Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Wed, 19 Mar 2025 11:42:37 +0000 Subject: [PATCH] Look for VSCode variants We've had requests for this in Homebrew/bundle a few times so let's implement it both for there and for `brew edit`. Tested on my machine with `cursor` and working as expected. --- Library/Homebrew/bundle/bundle.rb | 9 ++++++++- Library/Homebrew/bundle/commands/cleanup.rb | 2 +- Library/Homebrew/bundle/vscode_extension_dumper.rb | 2 +- .../Homebrew/bundle/vscode_extension_installer.rb | 2 +- Library/Homebrew/cmd/bundle.rb | 6 +++--- Library/Homebrew/extend/kernel.rb | 4 ++-- .../Homebrew/test/bundle/commands/cleanup_spec.rb | 3 ++- .../test/bundle/vscode_extension_installer_spec.rb | 14 +++++++------- completions/fish/brew.fish | 6 +++--- completions/zsh/_brew | 6 +++--- docs/Manpage.md | 8 ++++---- manpages/brew.1 | 6 +++--- 12 files changed, 38 insertions(+), 30 deletions(-) diff --git a/Library/Homebrew/bundle/bundle.rb b/Library/Homebrew/bundle/bundle.rb index c54f75a716..77201acee9 100644 --- a/Library/Homebrew/bundle/bundle.rb +++ b/Library/Homebrew/bundle/bundle.rb @@ -32,7 +32,14 @@ module Homebrew end def vscode_installed? - @vscode_installed ||= which("code").present? + @vscode_installed ||= which_vscode.present? + end + + def which_vscode + @which_vscode ||= which("code", ORIGINAL_PATHS) + @which_vscode ||= which("codium", ORIGINAL_PATHS) + @which_vscode ||= which("cursor", ORIGINAL_PATHS) + @which_vscode ||= which("code-insiders", ORIGINAL_PATHS) end def whalebrew_installed? diff --git a/Library/Homebrew/bundle/commands/cleanup.rb b/Library/Homebrew/bundle/commands/cleanup.rb index 66fc099207..4764facc46 100644 --- a/Library/Homebrew/bundle/commands/cleanup.rb +++ b/Library/Homebrew/bundle/commands/cleanup.rb @@ -44,7 +44,7 @@ module Homebrew Bundle.exchange_uid_if_needed! do vscode_extensions.each do |extension| - Kernel.system "code", "--uninstall-extension", extension + Kernel.system(Bundle.which_vscode, "--uninstall-extension", extension) end end diff --git a/Library/Homebrew/bundle/vscode_extension_dumper.rb b/Library/Homebrew/bundle/vscode_extension_dumper.rb index 5b1ee3c42e..eb6522d639 100644 --- a/Library/Homebrew/bundle/vscode_extension_dumper.rb +++ b/Library/Homebrew/bundle/vscode_extension_dumper.rb @@ -13,7 +13,7 @@ module Homebrew def extensions @extensions ||= if Bundle.vscode_installed? Bundle.exchange_uid_if_needed! do - `code --list-extensions 2>/dev/null` + `"#{Bundle.which_vscode}" --list-extensions 2>/dev/null` end.split("\n").map(&:downcase) else [] diff --git a/Library/Homebrew/bundle/vscode_extension_installer.rb b/Library/Homebrew/bundle/vscode_extension_installer.rb index b27c3b04de..19003c87f0 100644 --- a/Library/Homebrew/bundle/vscode_extension_installer.rb +++ b/Library/Homebrew/bundle/vscode_extension_installer.rb @@ -33,7 +33,7 @@ module Homebrew puts "Installing #{name} VSCode extension. It is not currently installed." if verbose return false unless Bundle.exchange_uid_if_needed! do - Bundle.system("code", "--install-extension", name, verbose:) + Bundle.system(Bundle.which_vscode, "--install-extension", name, verbose:) end installed_extensions << name diff --git a/Library/Homebrew/cmd/bundle.rb b/Library/Homebrew/cmd/bundle.rb index fdb8fb2613..c7b8394dff 100755 --- a/Library/Homebrew/cmd/bundle.rb +++ b/Library/Homebrew/cmd/bundle.rb @@ -10,7 +10,7 @@ module Homebrew usage_banner <<~EOS `bundle` [] - Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code. + Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code (and forks/variants). `brew bundle` [`install`]: Install and upgrade (by default) all dependencies from the `Brewfile`. @@ -105,10 +105,10 @@ module Homebrew switch "--whalebrew", description: "`list` or `dump` Whalebrew dependencies." switch "--vscode", - description: "`list` or `dump` VSCode extensions." + description: "`list` or `dump` VSCode (and forks/variants) extensions." switch "--no-vscode", env: :bundle_dump_no_vscode, - description: "`dump` without VSCode extensions. " \ + description: "`dump` without VSCode (and forks/variants) extensions. " \ "This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set." switch "--describe", env: :bundle_dump_describe, diff --git a/Library/Homebrew/extend/kernel.rb b/Library/Homebrew/extend/kernel.rb index 7d21851fd0..e92210b18d 100644 --- a/Library/Homebrew/extend/kernel.rb +++ b/Library/Homebrew/extend/kernel.rb @@ -332,8 +332,8 @@ module Kernel editor = Homebrew::EnvConfig.editor return editor if editor - # Find VS Code, Sublime Text, Textmate, BBEdit, or vim - editor = %w[code subl mate bbedit vim].find do |candidate| + # Find VS Code variants, Sublime Text, Textmate, BBEdit, or vim + editor = %w[code codium cursor code-insiders subl mate bbedit vim].find do |candidate| candidate if which(candidate, ORIGINAL_PATHS) end editor ||= "vim" diff --git a/Library/Homebrew/test/bundle/commands/cleanup_spec.rb b/Library/Homebrew/test/bundle/commands/cleanup_spec.rb index 7696226676..6bf7b878be 100644 --- a/Library/Homebrew/test/bundle/commands/cleanup_spec.rb +++ b/Library/Homebrew/test/bundle/commands/cleanup_spec.rb @@ -186,6 +186,7 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do context "when there are VSCode extensions to uninstall" do before do described_class.reset! + allow(Homebrew::Bundle).to receive(:which_vscode).and_return(Pathname("code")) allow(described_class).to receive_messages(casks_to_uninstall: [], formulae_to_uninstall: [], taps_to_untap: [], @@ -193,7 +194,7 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do end it "uninstalls extensions" do - expect(Kernel).to receive(:system).with("code", "--uninstall-extension", "GitHub.codespaces") + expect(Kernel).to receive(:system).with(Pathname("code"), "--uninstall-extension", "GitHub.codespaces") expect(described_class).to receive(:system_output_no_stderr).and_return("") described_class.run(force: true) end diff --git a/Library/Homebrew/test/bundle/vscode_extension_installer_spec.rb b/Library/Homebrew/test/bundle/vscode_extension_installer_spec.rb index 6de8efe0e0..db9a4634a9 100644 --- a/Library/Homebrew/test/bundle/vscode_extension_installer_spec.rb +++ b/Library/Homebrew/test/bundle/vscode_extension_installer_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Homebrew::Bundle::VscodeExtensionInstaller do context "when VSCode is installed" do before do - allow(Homebrew::Bundle).to receive(:vscode_installed?).and_return(true) + allow(Homebrew::Bundle).to receive(:which_vscode).and_return(Pathname("code")) end context "when extension is installed" do @@ -45,8 +45,8 @@ RSpec.describe Homebrew::Bundle::VscodeExtensionInstaller do end it "installs extension" do - expect(Homebrew::Bundle).to receive(:system).with("code", "--install-extension", "foo", - verbose: false).and_return(true) + expect(Homebrew::Bundle).to \ + receive(:system).with(Pathname("code"), "--install-extension", "foo", verbose: false).and_return(true) expect(described_class.preinstall("foo")).to be(true) expect(described_class.install("foo")).to be(true) end @@ -56,8 +56,8 @@ RSpec.describe Homebrew::Bundle::VscodeExtensionInstaller do expect(Process::UID).to receive(:re_exchangeable?).and_return(true).once expect(Process::UID).to receive(:re_exchange).twice - expect(Homebrew::Bundle).to receive(:system).with("code", "--install-extension", "foo", - verbose: false).and_return(true) + expect(Homebrew::Bundle).to \ + receive(:system).with(Pathname("code"), "--install-extension", "foo", verbose: false).and_return(true) expect(described_class.preinstall("foo")).to be(true) expect(described_class.install("foo")).to be(true) end @@ -67,8 +67,8 @@ RSpec.describe Homebrew::Bundle::VscodeExtensionInstaller do expect(Process::UID).to receive(:re_exchangeable?).and_return(false).once expect(Process::Sys).to receive(:seteuid).twice - expect(Homebrew::Bundle).to receive(:system).with("code", "--install-extension", "foo", - verbose: false).and_return(true) + expect(Homebrew::Bundle).to \ + receive(:system).with(Pathname("code"), "--install-extension", "foo", verbose: false).and_return(true) expect(described_class.preinstall("foo")).to be(true) expect(described_class.install("foo")).to be(true) end diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index 0275380c7e..234412aa5f 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -493,7 +493,7 @@ __fish_brew_complete_arg 'bump-unversioned-casks' -a '(__fish_brew_suggest_casks __fish_brew_complete_arg 'bump-unversioned-casks' -a '(__fish_brew_suggest_taps_installed)' -__fish_brew_complete_cmd 'bundle' 'Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code' +__fish_brew_complete_cmd 'bundle' 'Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code (and forks/variants)' __fish_brew_complete_sub_cmd 'bundle' 'install' __fish_brew_complete_sub_cmd 'bundle' 'dump' __fish_brew_complete_sub_cmd 'bundle' 'cleanup' @@ -517,12 +517,12 @@ __fish_brew_complete_arg 'bundle' -l install -d 'Run `install` before continuing __fish_brew_complete_arg 'bundle' -l mas -d '`list` or `dump` Mac App Store dependencies' __fish_brew_complete_arg 'bundle' -l no-restart -d '`dump` does not add `restart_service` to formula lines' __fish_brew_complete_arg 'bundle' -l no-upgrade -d '`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set' -__fish_brew_complete_arg 'bundle' -l no-vscode -d '`dump` without VSCode extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set' +__fish_brew_complete_arg 'bundle' -l no-vscode -d '`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set' __fish_brew_complete_arg 'bundle' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'bundle' -l tap -d '`list` or `dump` Homebrew tap dependencies' __fish_brew_complete_arg 'bundle' -l upgrade -d '`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set. ' __fish_brew_complete_arg 'bundle' -l verbose -d '`install` prints output from commands as they are run. `check` lists all missing dependencies' -__fish_brew_complete_arg 'bundle' -l vscode -d '`list` or `dump` VSCode extensions' +__fish_brew_complete_arg 'bundle' -l vscode -d '`list` or `dump` VSCode (and forks/variants) extensions' __fish_brew_complete_arg 'bundle' -l whalebrew -d '`list` or `dump` Whalebrew dependencies' __fish_brew_complete_arg 'bundle' -l zap -d '`cleanup` casks using the `zap` command instead of `uninstall`' diff --git a/completions/zsh/_brew b/completions/zsh/_brew index 8fb3fdfa00..6e978ed4af 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -149,7 +149,7 @@ __brew_internal_commands() { 'bump-formula-pr:Create a pull request to update formula with a new URL or a new tag' 'bump-revision:Create a commit to increment the revision of formula' 'bump-unversioned-casks:Check all casks with unversioned URLs in a given tap for updates' - 'bundle:Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code' + 'bundle:Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code (and forks/variants)' 'casks:List all locally installable casks including short names' 'cat:Display the source of a formula or cask' 'cleanup:Remove stale lock files and outdated downloads for all formulae and casks, and remove old versions of installed formulae' @@ -659,12 +659,12 @@ _brew_bundle() { '--mas[`list` or `dump` Mac App Store dependencies]' \ '--no-restart[`dump` does not add `restart_service` to formula lines]' \ '--no-upgrade[`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \ - '(--all --vscode)--no-vscode[`dump` without VSCode extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set]' \ + '(--all --vscode)--no-vscode[`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set]' \ '--quiet[Make some output more quiet]' \ '--tap[`list` or `dump` Homebrew tap dependencies]' \ '(--install)--upgrade[`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set. ]' \ '--verbose[`install` prints output from commands as they are run. `check` lists all missing dependencies]' \ - '(--no-vscode)--vscode[`list` or `dump` VSCode extensions]' \ + '(--no-vscode)--vscode[`list` or `dump` VSCode (and forks/variants) extensions]' \ '--whalebrew[`list` or `dump` Whalebrew dependencies]' \ '--zap[`cleanup` casks using the `zap` command instead of `uninstall`]' \ - subcommand \ diff --git a/docs/Manpage.md b/docs/Manpage.md index 1de0470320..fe83f47dff 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -136,7 +136,7 @@ and are now no longer needed. ### `bundle` \[*`subcommand`*\] Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, -Whalebrew and Visual Studio Code. +Whalebrew and Visual Studio Code (and forks/variants). `brew bundle` \[`install`\] @@ -288,12 +288,12 @@ flags which will help with finding keg-only dependencies like `openssl`, `--vscode` -: `list` or `dump` VSCode extensions. +: `list` or `dump` VSCode (and forks/variants) extensions. `--no-vscode` -: `dump` without VSCode extensions. This is enabled by default if - `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set. +: `dump` without VSCode (and forks/variants) extensions. This is enabled by + default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set. `--describe` diff --git a/manpages/brew.1 b/manpages/brew.1 index 0bd58dfeed..21ec4d3a20 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -83,7 +83,7 @@ Uninstall formulae that were only installed as a dependency of another formula a \fB\-n\fP, \fB\-\-dry\-run\fP List what would be uninstalled, but do not actually uninstall anything\. .SS "\fBbundle\fP \fR[\fIsubcommand\fP]" -Bundler for non\-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code\. +Bundler for non\-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code (and forks/variants)\. .TP \fBbrew bundle\fP [\fBinstall\fP] Install and upgrade (by default) all dependencies from the \fBBrewfile\fP\&\. @@ -178,10 +178,10 @@ Run \fBinstall\fP before continuing to other operations e\.g\. \fBexec\fP\&\. \fBlist\fP or \fBdump\fP Whalebrew dependencies\. .TP \fB\-\-vscode\fP -\fBlist\fP or \fBdump\fP VSCode extensions\. +\fBlist\fP or \fBdump\fP VSCode (and forks/variants) extensions\. .TP \fB\-\-no\-vscode\fP -\fBdump\fP without VSCode extensions\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_NO_VSCODE\fP is set\. +\fBdump\fP without VSCode (and forks/variants) extensions\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_NO_VSCODE\fP is set\. .TP \fB\-\-describe\fP \fBdump\fP adds a description comment above each line, unless the dependency does not have a description\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_DESCRIBE\fP is set\.