Skip to content

Commit

Permalink
Add --no-vscode and HOMEBREW_BUNDLE_DUMP_NO_VSCODE
Browse files Browse the repository at this point in the history
This allows excluding VSCode output from `brew bundle dump` with a
flag or environment variable.

While we're here
- generally refactor how we handle command arguments so this logic is
  pushed into `cmd/bundle` and made more consistent
- fix early RSpec failure due to an unstubbed `exec` call
- refactor some specs to be more idiomatic
  • Loading branch information
MikeMcQuaid committed Oct 2, 2024
1 parent 4b25b52 commit a15c4b9
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 97 deletions.
105 changes: 53 additions & 52 deletions cmd/bundle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,21 @@ class BundleCmd < AbstractCommand
switch "--all",
description: "`list` all dependencies."
switch "--formula", "--brews",
description: "`list` Homebrew formula dependencies."
description: "`list` or `dump` Homebrew formula dependencies."
switch "--cask", "--casks",
description: "`list` Homebrew cask dependencies."
description: "`list` or `dump` Homebrew cask dependencies."
switch "--tap", "--taps",
description: "`list` Homebrew tap dependencies."
description: "`list` or `dump` Homebrew tap dependencies."
switch "--mas",
description: "`list` Mac App Store dependencies."
description: "`list` or `dump` Mac App Store dependencies."
switch "--whalebrew",
description: "`list` Whalebrew dependencies."
description: "`list` or `dump` Whalebrew dependencies."
switch "--vscode",
description: "`list` VSCode extensions."
description: "`list` or `dump` VSCode extensions."
switch "--no-vscode",
env: :bundle_dump_no_vscode,
description: "`dump` without VSCode extensions. " \
"This is enabled by default if `HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set."
switch "--describe",
env: :bundle_dump_describe,
description: "`dump` adds a description comment above each line, unless the " \
Expand All @@ -101,6 +105,9 @@ class BundleCmd < AbstractCommand
switch "--zap",
description: "`cleanup` casks using the `zap` command instead of `uninstall`."

conflicts "--all", "--no-vscode"
conflicts "--vscode", "--no-vscode"

named_args %w[install dump cleanup check exec list]
end

Expand All @@ -113,16 +120,22 @@ def run
raise UsageError, "This command does not take more than 1 subcommand argument."
end

global = args.global?
file = args.file
args.zap?
no_upgrade = args.no_upgrade?
verbose = args.verbose?
force = args.force?
zap = args.zap?

no_type_args = !args.brews? && !args.casks? && !args.taps? && !args.mas? && !args.whalebrew? && !args.vscode?

case subcommand
when nil, "install"
Bundle::Commands::Install.run(
global: args.global?,
file: args.file,
global:, file:, no_upgrade:, verbose:, force:,
no_lock: args.no_lock?,
no_upgrade: args.no_upgrade?,
verbose: args.verbose?,
force: args.force?,
quiet: args.quiet?,
quiet: args.quiet?
)

cleanup = if ENV.fetch("HOMEBREW_BUNDLE_INSTALL_CLEANUP", nil)
Expand All @@ -133,60 +146,48 @@ def run

if cleanup
Bundle::Commands::Cleanup.run(
global: args.global?,
file: args.file,
global:, file:, zap:,
force: true,
zap: args.zap?,
dsl: Bundle::Commands::Install.dsl,
dsl: Bundle::Commands::Install.dsl
)
end
when "dump"
vscode = if args.no_vscode?
false
elsif args.vscode?
true
else
no_type_args
end

Bundle::Commands::Dump.run(
global: args.global?,
file: args.file,
global:, file:, force:,
describe: args.describe?,
force: args.force?,
no_restart: args.no_restart?,
all: args.all?,
taps: args.taps?,
brews: args.brews?,
casks: args.casks?,
mas: args.mas?,
whalebrew: args.whalebrew?,
vscode: args.vscode?,
taps: args.taps? || no_type_args,
brews: args.brews? || no_type_args,
casks: args.casks? || no_type_args,
mas: args.mas? || no_type_args,
whalebrew: args.whalebrew? || no_type_args,
vscode:
)
when "cleanup"
Bundle::Commands::Cleanup.run(
global: args.global?,
file: args.file,
force: args.force?,
zap: args.zap?,
)
Bundle::Commands::Cleanup.run(global:, file:, force:, zap:)
when "check"
Bundle::Commands::Check.run(
global: args.global?,
file: args.file,
no_upgrade: args.no_upgrade?,
verbose: args.verbose?,
)
Bundle::Commands::Check.run(global:, file:, no_upgrade:, verbose:)
when "exec"
_subcommand, *named_args = args.named
Bundle::Commands::Exec.run(
*named_args,
global: args.global?,
file: args.file,
)
Bundle::Commands::Exec.run(*named_args, global:, file:)
when "list"
Bundle::Commands::List.run(
global: args.global?,
file: args.file,
all: args.all?,
casks: args.casks?,
taps: args.taps?,
mas: args.mas?,
whalebrew: args.whalebrew?,
vscode: args.vscode?,
brews: args.brews?,
global:,
file:,
brews: args.brews? || args.all? || no_type_args,
casks: args.casks? || args.all?,
taps: args.taps? || args.all?,
mas: args.mas? || args.all?,
whalebrew: args.whalebrew? || args.all?,
vscode: args.vscode? || args.all?,
)
else
raise UsageError, "unknown subcommand: #{subcommand}"
Expand Down
8 changes: 2 additions & 6 deletions lib/bundle/commands/dump.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@ module Commands
module Dump
module_function

def run(global: false, file: nil, describe: false, force: false, no_restart: false,
all: false, taps: false, brews: false, casks: false,
mas: false, whalebrew: false, vscode: false)
def run(global:, file:, describe:, force:, no_restart:, taps:, brews:, casks:, mas:, whalebrew:, vscode:)
Bundle::Dumper.dump_brewfile(
global:, file:, describe:, force:, no_restart:,
all:, taps:, brews:, casks:,
mas:, whalebrew:, vscode:
global:, file:, describe:, force:, no_restart:, taps:, brews:, casks:, mas:, whalebrew:, vscode:,
)
end
end
Expand Down
5 changes: 2 additions & 3 deletions lib/bundle/commands/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ module Commands
module List
module_function

def run(global: false, file: nil, all: false, casks: false, taps: false, mas: false, whalebrew: false,
vscode: false, brews: false)
def run(global:, file:, brews:, casks:, taps:, mas:, whalebrew:, vscode:)
parsed_entries = Brewfile.read(global:, file:).entries
Bundle::Lister.list(
parsed_entries,
all:, casks:, taps:, mas:, whalebrew:, vscode:, brews:,
brews:, casks:, taps:, mas:, whalebrew:, vscode:,
)
end
end
Expand Down
26 changes: 10 additions & 16 deletions lib/bundle/dumper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,22 @@ def can_write_to_brewfile?(brewfile_path, force: false)
true
end

def build_brewfile(describe: false, no_restart: false,
all: false, taps: false, brews: false, casks: false,
mas: false, whalebrew: false, vscode: false)
all ||= !(taps || brews || casks || mas || whalebrew || vscode)
def build_brewfile(describe:, no_restart:, brews:, taps:, casks:, mas:, whalebrew:, vscode:)
content = []
content << TapDumper.dump if taps || all
content << BrewDumper.dump(describe:, no_restart:) if brews || all
content << CaskDumper.dump(describe:) if casks || all
content << MacAppStoreDumper.dump if mas || all
content << WhalebrewDumper.dump if whalebrew || all
content << VscodeExtensionDumper.dump if vscode || all
content << TapDumper.dump if taps
content << BrewDumper.dump(describe:, no_restart:) if brews
content << CaskDumper.dump(describe:) if casks
content << MacAppStoreDumper.dump if mas
content << WhalebrewDumper.dump if whalebrew
content << VscodeExtensionDumper.dump if vscode
"#{content.reject(&:empty?).join("\n")}\n"
end

def dump_brewfile(global: false, file: nil, describe: false, force: false, no_restart: false,
all: false, taps: false, brews: false, casks: false,
mas: false, whalebrew: false, vscode: false)
def dump_brewfile(global:, file:, describe:, force:, no_restart:, brews:, taps:, casks:, mas:, whalebrew:,
vscode:)
path = brewfile_path(global:, file:)
can_write_to_brewfile?(path, force:)
content = build_brewfile(describe:, no_restart:,
all:, taps:, brews:, casks:,
mas:, whalebrew:, vscode:)
content = build_brewfile(describe:, no_restart:, taps:, brews:, casks:, mas:, whalebrew:, vscode:)
write_file path, content
end

Expand Down
15 changes: 4 additions & 11 deletions lib/bundle/lister.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,19 @@ module Bundle
module Lister
module_function

def list(entries, all: false, casks: false, taps: false, mas: false, whalebrew: false,
vscode: false, brews: false)
def list(entries, brews:, casks:, taps:, mas:, whalebrew:, vscode:)
entries.each do |entry|
if show?(entry.type, all:, casks:, taps:, mas:, whalebrew:, vscode:,
brews:)
puts entry.name
end
puts entry.name if show?(entry.type, brews:, casks:, taps:, mas:, whalebrew:, vscode:)
end
end

def self.show?(type, all: false, casks: false, taps: false, mas: false, whalebrew: false,
vscode: false, brews: false)
return true if all
def self.show?(type, brews:, casks:, taps:, mas:, whalebrew:, vscode:)
return true if brews && type == :brew
return true if casks && type == :cask
return true if taps && type == :tap
return true if mas && type == :mas
return true if whalebrew && type == :whalebrew
return true if vscode && type == :vscode
return true if brews && type == :brew
return true if type == :brew && !casks && !taps && !mas && !whalebrew && !vscode

false
end
Expand Down
15 changes: 11 additions & 4 deletions spec/bundle/commands/dump_command_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
require "spec_helper"

describe Bundle::Commands::Dump do
subject(:dump) { described_class.run(global:, file: nil, describe: false, force:, no_restart: false, taps: true, brews: true, casks: true, mas: true, whalebrew: true, vscode: true) }

Check failure on line 6 in spec/bundle/commands/dump_command_spec.rb

View workflow job for this annotation

GitHub Actions / tests (ubuntu-latest)

RSpec/EmptyLineAfterSubject: Add an empty line after `subject`.

Check failure on line 6 in spec/bundle/commands/dump_command_spec.rb

View workflow job for this annotation

GitHub Actions / tests (ubuntu-latest)

Layout/LineLength: Line is too long. [184/118]

Check failure on line 6 in spec/bundle/commands/dump_command_spec.rb

View workflow job for this annotation

GitHub Actions / tests (macOS-latest)

RSpec/EmptyLineAfterSubject: Add an empty line after `subject`.

Check failure on line 6 in spec/bundle/commands/dump_command_spec.rb

View workflow job for this annotation

GitHub Actions / tests (macOS-latest)

Layout/LineLength: Line is too long. [184/118]
let(:force) { false }
let(:global) { false }

context "when files existed" do
before do
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
Expand All @@ -11,7 +15,7 @@

it "raises error" do
expect do
described_class.run
dump
end.to raise_error(RuntimeError)
end

Expand All @@ -21,12 +25,15 @@
expect(Bundle::CaskDumper).not_to receive(:dump)
expect(Bundle::WhalebrewDumper).not_to receive(:dump)
expect do
described_class.run
dump
end.to raise_error(RuntimeError)
end
end

context "when files existed and `--force` is passed" do
context "when files existed and `--force` and `--global` are passed" do
let(:force) { true }
let(:global) { true }

before do
ENV["HOMEBREW_BUNDLE_FILE"] = ""
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
Expand All @@ -38,7 +45,7 @@
expect_any_instance_of(Pathname).to receive(:open).with("w").and_yield(io)
expect(io).to receive(:write)
expect do
described_class.run(force: true, global: true)
dump
end.not_to raise_error
end
end
Expand Down
1 change: 1 addition & 0 deletions spec/bundle/commands/exec_command_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
let(:rbenv_root) { Pathname.new("/tmp/.rbenv") }

it "prepends the path of the rbenv shims to PATH before running" do
allow(described_class).to receive(:exec).with("/usr/bin/true").and_return(0)
allow_any_instance_of(Pathname).to receive(:read)
.and_return("brew 'rbenv'")
allow(ENV).to receive(:fetch).with(any_args).and_call_original
Expand Down
19 changes: 15 additions & 4 deletions spec/bundle/commands/list_command_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
require "spec_helper"

describe Bundle::Commands::List do
subject(:list) { described_class.run(**options) }

let(:options) { {} }
subject(:list) { described_class.run(global: false, file: nil, brews:, casks:, taps:, mas:, whalebrew:, vscode:) }

Check failure on line 6 in spec/bundle/commands/list_command_spec.rb

View workflow job for this annotation

GitHub Actions / tests (ubuntu-latest)

RSpec/EmptyLineAfterSubject: Add an empty line after `subject`.

Check failure on line 6 in spec/bundle/commands/list_command_spec.rb

View workflow job for this annotation

GitHub Actions / tests (macOS-latest)

RSpec/EmptyLineAfterSubject: Add an empty line after `subject`.
let(:brews) { true }
let(:casks) { false }
let(:taps) { false }
let(:mas) { false }
let(:whalebrew) { false }
let(:vscode) { false }

before do
allow_any_instance_of(IO).to receive(:puts)
Expand All @@ -20,6 +24,7 @@
cask 'google-chrome'
mas '1Password', id: 443987910
whalebrew 'whalebrew/imagemagick'
vscode 'shopify.ruby-lsp'
EOS
)
end
Expand All @@ -35,6 +40,7 @@
casks: "google-chrome",
mas: "1Password",
whalebrew: "whalebrew/imagemagick",
vscode: "shopify.ruby-lsp",
}

combinations = 1.upto(types_and_deps.length).flat_map do |i|
Expand All @@ -48,7 +54,12 @@
verb = (options_list.length == 1 && "is") || "are"

context "when #{opts} #{verb} passed" do
let(:options) { args_hash }
let(:brews) { args_hash[:brews] }
let(:casks) { args_hash[:casks] }
let(:taps) { args_hash[:taps] }
let(:mas) { args_hash[:mas] }
let(:whalebrew) { args_hash[:whalebrew] }
let(:vscode) { args_hash[:vscode] }

it "shows only #{words}" do
expected = options_list.map { |opt| types_and_deps[opt] }.join("\n")
Expand Down
2 changes: 1 addition & 1 deletion spec/bundle/dumper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
end

it "generates output" do
expect(dumper.build_brewfile).to eql("cask \"google-chrome\"\ncask \"java\"\ncask \"iterm2-beta\"\n")
expect(dumper.build_brewfile(describe: false, no_restart: false, brews: true, taps: true, casks: true, mas: true, whalebrew: true, vscode: true)).to eql("cask \"google-chrome\"\ncask \"java\"\ncask \"iterm2-beta\"\n")

Check failure on line 39 in spec/bundle/dumper_spec.rb

View workflow job for this annotation

GitHub Actions / tests (ubuntu-latest)

Layout/LineLength: Line is too long. [221/118]

Check failure on line 39 in spec/bundle/dumper_spec.rb

View workflow job for this annotation

GitHub Actions / tests (macOS-latest)

Layout/LineLength: Line is too long. [221/118]
end

it "determines the brewfile correctly" do
Expand Down

0 comments on commit a15c4b9

Please sign in to comment.