diff --git a/Library/Homebrew/cask/lib/hbc.rb b/Library/Homebrew/cask/lib/hbc.rb index 737c930d10..5530683523 100644 --- a/Library/Homebrew/cask/lib/hbc.rb +++ b/Library/Homebrew/cask/lib/hbc.rb @@ -18,7 +18,7 @@ require "hbc/installer" require "hbc/macos" require "hbc/pkg" require "hbc/staged" -require "hbc/system_command" +require "system_command" require "hbc/topological_hash" require "hbc/utils" require "hbc/verify" diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb index 8b52fcde2e..2472c88e49 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb @@ -1,4 +1,4 @@ -require "hbc/system_command" +require "system_command" module Hbc class DSL diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb deleted file mode 100644 index e86fa8f6c7..0000000000 --- a/Library/Homebrew/cask/lib/hbc/system_command.rb +++ /dev/null @@ -1,194 +0,0 @@ -require "open3" -require "vendor/plist/plist" -require "shellwords" - -require "extend/io" -require "extend/hash_validator" -using HashValidator - -module Hbc - class SystemCommand - extend Predicable - - def self.run(executable, **options) - new(executable, **options).run! - end - - def self.run!(command, **options) - run(command, **options, must_succeed: true) - end - - def run! - @merged_output = [] - @processed_output = { stdout: "", stderr: "" } - odebug command.shelljoin - - each_output_line do |type, line| - case type - when :stdout - puts line.chomp if print_stdout? - processed_output[:stdout] << line - @merged_output << [:stdout, line] - when :stderr - $stderr.puts Formatter.error(line.chomp) if print_stderr? - processed_output[:stderr] << line - @merged_output << [:stderr, line] - end - end - - assert_success if must_succeed? - result - end - - def initialize(executable, args: [], sudo: false, input: [], print_stdout: false, print_stderr: true, must_succeed: false, env: {}, **options) - @executable = executable - @args = args - @sudo = sudo - @input = [*input] - @print_stdout = print_stdout - @print_stderr = print_stderr - @must_succeed = must_succeed - options.assert_valid_keys!(:chdir) - @options = options - @env = env - - @env.keys.grep_v(/^[\w&&\D]\w*$/) do |name| - raise ArgumentError, "Invalid variable name: '#{name}'" - end - end - - def command - [*sudo_prefix, *env_args, executable.to_s, *expanded_args] - end - - private - - attr_reader :executable, :args, :input, :options, :processed_output, :processed_status, :env - - attr_predicate :sudo?, :print_stdout?, :print_stderr?, :must_succeed? - - def env_args - return [] if env.empty? - - variables = env.map do |name, value| - sanitized_name = Shellwords.escape(name) - sanitized_value = Shellwords.escape(value) - "#{sanitized_name}=#{sanitized_value}" - end - - ["env", *variables] - end - - def sudo_prefix - return [] unless sudo? - askpass_flags = ENV.key?("SUDO_ASKPASS") ? ["-A"] : [] - ["/usr/bin/sudo", *askpass_flags, "-E", "--"] - end - - def assert_success - return if processed_status&.success? - raise ErrorDuringExecution.new(command, - status: processed_status, - output: @merged_output) - end - - def expanded_args - @expanded_args ||= args.map do |arg| - if arg.respond_to?(:to_path) - File.absolute_path(arg) - elsif arg.is_a?(Integer) || arg.is_a?(Float) - arg.to_s - else - arg.to_str - end - end - end - - def each_output_line(&b) - executable, *args = command - - raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = - Open3.popen3([executable, executable], *args, **options) - - write_input_to(raw_stdin) - raw_stdin.close_write - each_line_from [raw_stdout, raw_stderr], &b - - @processed_status = raw_wait_thr.value - end - - def write_input_to(raw_stdin) - input.each(&raw_stdin.method(:write)) - end - - def each_line_from(sources) - loop do - readable_sources, = IO.select(sources) - - readable_sources = readable_sources.reject(&:eof?) - - break if readable_sources.empty? - - readable_sources.each do |source| - begin - line = source.readline_nonblock || "" - type = (source == sources[0]) ? :stdout : :stderr - yield(type, line) - rescue IO::WaitReadable, EOFError - next - end - end - end - - sources.each(&:close_read) - end - - def result - Result.new(command, - processed_output[:stdout], - processed_output[:stderr], - processed_status.exitstatus) - end - - class Result - attr_accessor :command, :stdout, :stderr, :exit_status - - def initialize(command, stdout, stderr, exit_status) - @command = command - @stdout = stdout - @stderr = stderr - @exit_status = exit_status - end - - def success? - @exit_status.zero? - end - - def plist - @plist ||= begin - output = stdout - - if /\A(?.*?)<\?\s*xml/m =~ output - output = output.sub(/\A#{Regexp.escape(garbage)}/m, "") - warn_plist_garbage(garbage) - end - - if %r{<\s*/\s*plist\s*>(?.*?)\Z}m =~ output - output = output.sub(/#{Regexp.escape(garbage)}\Z/, "") - warn_plist_garbage(garbage) - end - - Plist.parse_xml(output) - end - end - - def warn_plist_garbage(garbage) - return unless ARGV.verbose? - return unless garbage =~ /\S/ - opoo "Received non-XML output from #{Formatter.identifier(command.first)}:" - $stderr.puts garbage.strip - end - private :warn_plist_garbage - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb index 16798d7fa1..088150d389 100644 --- a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb +++ b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb @@ -7,7 +7,7 @@ module Hbc attr_reader :cask, :downloaded_path - def initialize(cask, downloaded_path, command = Hbc::SystemCommand) + def initialize(cask, downloaded_path, command = SystemCommand) @command = command @cask = cask @downloaded_path = downloaded_path diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb index 249987b33b..fb6fcac8a7 100644 --- a/Library/Homebrew/readall.rb +++ b/Library/Homebrew/readall.rb @@ -76,6 +76,13 @@ module Readall # Retrieve messages about syntax errors/warnings printed to `$stderr`, but # discard a `Syntax OK` printed to `$stdout` (in absence of syntax errors). messages = Utils.popen_read("#{RUBY_PATH} -c -w #{rb} 2>&1 >/dev/null") + + # Ignore unnecessary warning about named capture conflicts. + # See https://bugs.ruby-lang.org/issues/12359. + messages = messages.lines + .reject { |line| line.include?("named capture conflicts a local variable") } + .join + $stderr.print messages # Only syntax errors result in a non-zero status code. To detect syntax diff --git a/Library/Homebrew/system_command.rb b/Library/Homebrew/system_command.rb new file mode 100644 index 0000000000..8095acfd65 --- /dev/null +++ b/Library/Homebrew/system_command.rb @@ -0,0 +1,192 @@ +require "open3" +require "vendor/plist/plist" +require "shellwords" + +require "extend/io" +require "extend/hash_validator" +using HashValidator + +class SystemCommand + extend Predicable + + def self.run(executable, **options) + new(executable, **options).run! + end + + def self.run!(command, **options) + run(command, **options, must_succeed: true) + end + + def run! + @merged_output = [] + @processed_output = { stdout: "", stderr: "" } + odebug command.shelljoin + + each_output_line do |type, line| + case type + when :stdout + puts line.chomp if print_stdout? + processed_output[:stdout] << line + @merged_output << [:stdout, line] + when :stderr + $stderr.puts Formatter.error(line.chomp) if print_stderr? + processed_output[:stderr] << line + @merged_output << [:stderr, line] + end + end + + assert_success if must_succeed? + result + end + + def initialize(executable, args: [], sudo: false, input: [], print_stdout: false, print_stderr: true, must_succeed: false, env: {}, **options) + @executable = executable + @args = args + @sudo = sudo + @input = [*input] + @print_stdout = print_stdout + @print_stderr = print_stderr + @must_succeed = must_succeed + options.assert_valid_keys!(:chdir) + @options = options + @env = env + + @env.keys.grep_v(/^[\w&&\D]\w*$/) do |name| + raise ArgumentError, "Invalid variable name: '#{name}'" + end + end + + def command + [*sudo_prefix, *env_args, executable.to_s, *expanded_args] + end + + private + + attr_reader :executable, :args, :input, :options, :processed_output, :processed_status, :env + + attr_predicate :sudo?, :print_stdout?, :print_stderr?, :must_succeed? + + def env_args + return [] if env.empty? + + variables = env.map do |name, value| + sanitized_name = Shellwords.escape(name) + sanitized_value = Shellwords.escape(value) + "#{sanitized_name}=#{sanitized_value}" + end + + ["env", *variables] + end + + def sudo_prefix + return [] unless sudo? + askpass_flags = ENV.key?("SUDO_ASKPASS") ? ["-A"] : [] + ["/usr/bin/sudo", *askpass_flags, "-E", "--"] + end + + def assert_success + return if processed_status&.success? + raise ErrorDuringExecution.new(command, + status: processed_status, + output: @merged_output) + end + + def expanded_args + @expanded_args ||= args.map do |arg| + if arg.respond_to?(:to_path) + File.absolute_path(arg) + elsif arg.is_a?(Integer) || arg.is_a?(Float) + arg.to_s + else + arg.to_str + end + end + end + + def each_output_line(&b) + executable, *args = command + + raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = + Open3.popen3([executable, executable], *args, **options) + + write_input_to(raw_stdin) + raw_stdin.close_write + each_line_from [raw_stdout, raw_stderr], &b + + @processed_status = raw_wait_thr.value + end + + def write_input_to(raw_stdin) + input.each(&raw_stdin.method(:write)) + end + + def each_line_from(sources) + loop do + readable_sources, = IO.select(sources) + + readable_sources = readable_sources.reject(&:eof?) + + break if readable_sources.empty? + + readable_sources.each do |source| + begin + line = source.readline_nonblock || "" + type = (source == sources[0]) ? :stdout : :stderr + yield(type, line) + rescue IO::WaitReadable, EOFError + next + end + end + end + + sources.each(&:close_read) + end + + def result + Result.new(command, + processed_output[:stdout], + processed_output[:stderr], + processed_status.exitstatus) + end + + class Result + attr_accessor :command, :stdout, :stderr, :exit_status + + def initialize(command, stdout, stderr, exit_status) + @command = command + @stdout = stdout + @stderr = stderr + @exit_status = exit_status + end + + def success? + @exit_status.zero? + end + + def plist + @plist ||= begin + output = stdout + + if /\A(?.*?)<\?\s*xml/m =~ output + output = output.sub(/\A#{Regexp.escape(garbage)}/m, "") + warn_plist_garbage(garbage) + end + + if %r{<\s*/\s*plist\s*>(?.*?)\Z}m =~ output + output = output.sub(/#{Regexp.escape(garbage)}\Z/, "") + warn_plist_garbage(garbage) + end + + Plist.parse_xml(output) + end + end + + def warn_plist_garbage(garbage) + return unless ARGV.verbose? + return unless garbage =~ /\S/ + opoo "Received non-XML output from #{Formatter.identifier(command.first)}:" + $stderr.puts garbage.strip + end + private :warn_plist_garbage + end +end diff --git a/Library/Homebrew/test/cask/accessibility_spec.rb b/Library/Homebrew/test/cask/accessibility_spec.rb index 26613aa20c..2ba7d2a8ae 100644 --- a/Library/Homebrew/test/cask/accessibility_spec.rb +++ b/Library/Homebrew/test/cask/accessibility_spec.rb @@ -2,7 +2,7 @@ # that class is abstracted from installer.rb. describe "Accessibility Access", :cask do let(:cask) { Hbc::CaskLoader.load(cask_path("with-accessibility-access")) } - let(:fake_system_command) { class_double(Hbc::SystemCommand) } + let(:fake_system_command) { class_double(SystemCommand) } let(:installer) { Hbc::Installer.new(cask, command: fake_system_command) } before do diff --git a/Library/Homebrew/test/cask/artifact/alt_target_spec.rb b/Library/Homebrew/test/cask/artifact/alt_target_spec.rb index 2168ac6063..e78a353e6c 100644 --- a/Library/Homebrew/test/cask/artifact/alt_target_spec.rb +++ b/Library/Homebrew/test/cask/artifact/alt_target_spec.rb @@ -5,7 +5,7 @@ describe Hbc::Artifact::App, :cask do let(:install_phase) { lambda do cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end end } diff --git a/Library/Homebrew/test/cask/artifact/app_spec.rb b/Library/Homebrew/test/cask/artifact/app_spec.rb index aa6085bf16..305b3af37c 100644 --- a/Library/Homebrew/test/cask/artifact/app_spec.rb +++ b/Library/Homebrew/test/cask/artifact/app_spec.rb @@ -1,6 +1,6 @@ describe Hbc::Artifact::App, :cask do let(:cask) { Hbc::CaskLoader.load(cask_path("local-caffeine")) } - let(:command) { Hbc::SystemCommand } + let(:command) { SystemCommand } let(:force) { false } let(:app) { cask.artifacts.find { |a| a.is_a?(described_class) } } diff --git a/Library/Homebrew/test/cask/artifact/binary_spec.rb b/Library/Homebrew/test/cask/artifact/binary_spec.rb index 448c10dd1e..cdee0860f6 100644 --- a/Library/Homebrew/test/cask/artifact/binary_spec.rb +++ b/Library/Homebrew/test/cask/artifact/binary_spec.rb @@ -24,7 +24,7 @@ describe Hbc::Artifact::Binary, :cask do it "links the binary to the proper directory" do artifacts.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect(expected_path).to be_a_symlink @@ -45,7 +45,7 @@ describe Hbc::Artifact::Binary, :cask do .with("+x", cask.staged_path.join("naked_non_executable")).and_call_original artifacts.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect(expected_path).to be_a_symlink @@ -58,7 +58,7 @@ describe Hbc::Artifact::Binary, :cask do expect { artifacts.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end }.to raise_error(Hbc::CaskError) @@ -69,7 +69,7 @@ describe Hbc::Artifact::Binary, :cask do expected_path.make_symlink("/tmp") artifacts.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect(File.readlink(expected_path)).not_to eq("/tmp") @@ -79,7 +79,7 @@ describe Hbc::Artifact::Binary, :cask do FileUtils.rmdir Hbc::Config.global.binarydir artifacts.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect(expected_path.exist?).to be true @@ -94,10 +94,10 @@ describe Hbc::Artifact::Binary, :cask do it "links the binary to the proper directory" do cask.artifacts.select { |a| a.is_a?(Hbc::Artifact::App) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end artifacts.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect(expected_path).to be_a_symlink diff --git a/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb b/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb index 5502d83ed7..981228917f 100644 --- a/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb +++ b/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb @@ -4,7 +4,7 @@ describe Hbc::Artifact::Artifact, :cask do let(:install_phase) { lambda do cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end end } diff --git a/Library/Homebrew/test/cask/artifact/installer_spec.rb b/Library/Homebrew/test/cask/artifact/installer_spec.rb index 7e4c551125..d566440c0f 100644 --- a/Library/Homebrew/test/cask/artifact/installer_spec.rb +++ b/Library/Homebrew/test/cask/artifact/installer_spec.rb @@ -2,7 +2,7 @@ describe Hbc::Artifact::Installer, :cask do let(:staged_path) { mktmpdir } let(:cask) { instance_double("Cask", staged_path: staged_path, config: nil) } subject(:installer) { described_class.new(cask, **args) } - let(:command) { Hbc::SystemCommand } + let(:command) { SystemCommand } let(:args) { {} } diff --git a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb b/Library/Homebrew/test/cask/artifact/nested_container_spec.rb index f9cd056f8a..92486fc7f8 100644 --- a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb +++ b/Library/Homebrew/test/cask/artifact/nested_container_spec.rb @@ -6,7 +6,7 @@ describe Hbc::Artifact::NestedContainer, :cask do end cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect(cask.staged_path.join("MyNestedApp.app")).to be_a_directory diff --git a/Library/Homebrew/test/cask/artifact/pkg_spec.rb b/Library/Homebrew/test/cask/artifact/pkg_spec.rb index 74dfa5e5fd..4605eeaf81 100644 --- a/Library/Homebrew/test/cask/artifact/pkg_spec.rb +++ b/Library/Homebrew/test/cask/artifact/pkg_spec.rb @@ -1,6 +1,6 @@ describe Hbc::Artifact::Pkg, :cask do let(:cask) { Hbc::CaskLoader.load(cask_path("with-installable")) } - let(:fake_system_command) { class_double(Hbc::SystemCommand) } + let(:fake_system_command) { class_double(SystemCommand) } before do InstallHelper.install_without_artifacts(cask) diff --git a/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb b/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb index 18cc4ca91a..a49c900fcf 100644 --- a/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb +++ b/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb @@ -12,7 +12,7 @@ describe Hbc::Artifact::PostflightBlock, :cask do end cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect(called).to be true @@ -33,7 +33,7 @@ describe Hbc::Artifact::PostflightBlock, :cask do end cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.uninstall_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.uninstall_phase(command: NeverSudoSystemCommand, force: false) end expect(called).to be true diff --git a/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb b/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb index 405cdbd6f8..7a00839e27 100644 --- a/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb +++ b/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb @@ -12,7 +12,7 @@ describe Hbc::Artifact::PreflightBlock, :cask do end cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect(called).to be true @@ -33,7 +33,7 @@ describe Hbc::Artifact::PreflightBlock, :cask do end cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.uninstall_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.uninstall_phase(command: NeverSudoSystemCommand, force: false) end expect(called).to be true diff --git a/Library/Homebrew/test/cask/artifact/suite_spec.rb b/Library/Homebrew/test/cask/artifact/suite_spec.rb index 2602bb2ad0..55cd1d9ce5 100644 --- a/Library/Homebrew/test/cask/artifact/suite_spec.rb +++ b/Library/Homebrew/test/cask/artifact/suite_spec.rb @@ -4,7 +4,7 @@ describe Hbc::Artifact::Suite, :cask do let(:install_phase) { lambda do cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end end } diff --git a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb index 7c5f862141..4c56428d78 100644 --- a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb +++ b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb @@ -5,7 +5,7 @@ describe Hbc::Artifact::App, :cask do let(:install_phase) { lambda do cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end end } diff --git a/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb b/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb index 7edfb9e1ce..31ed8d4ff4 100644 --- a/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb +++ b/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb @@ -1,7 +1,7 @@ shared_examples "#uninstall_phase or #zap_phase" do let(:artifact_dsl_key) { described_class.dsl_key } let(:artifact) { cask.artifacts.find { |a| a.is_a?(described_class) } } - let(:fake_system_command) { Hbc::FakeSystemCommand } + let(:fake_system_command) { FakeSystemCommand } subject { artifact.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) } @@ -26,40 +26,40 @@ shared_examples "#uninstall_phase or #zap_phase" do end it "works when job is owned by user" do - Hbc::FakeSystemCommand.stubs_command( + FakeSystemCommand.stubs_command( launchctl_list_cmd, service_info, ) - Hbc::FakeSystemCommand.stubs_command( + FakeSystemCommand.stubs_command( sudo(launchctl_list_cmd), unknown_response, ) - Hbc::FakeSystemCommand.expects_command(launchctl_remove_cmd) + FakeSystemCommand.expects_command(launchctl_remove_cmd) subject end it "works when job is owned by system" do - Hbc::FakeSystemCommand.stubs_command( + FakeSystemCommand.stubs_command( launchctl_list_cmd, unknown_response, ) - Hbc::FakeSystemCommand.stubs_command( + FakeSystemCommand.stubs_command( sudo(launchctl_list_cmd), service_info, ) - Hbc::FakeSystemCommand.expects_command(sudo(launchctl_remove_cmd)) + FakeSystemCommand.expects_command(sudo(launchctl_remove_cmd)) subject end end context "using :pkgutil" do - let(:fake_system_command) { class_double(Hbc::SystemCommand) } + let(:fake_system_command) { class_double(SystemCommand) } let(:cask) { Hbc::CaskLoader.load(cask_path("with-#{artifact_dsl_key}-pkgutil")) } @@ -89,19 +89,19 @@ shared_examples "#uninstall_phase or #zap_phase" do let(:kext_id) { "my.fancy.package.kernelextension" } it "is supported" do - Hbc::FakeSystemCommand.stubs_command( + FakeSystemCommand.stubs_command( sudo(%W[/usr/sbin/kextstat -l -b #{kext_id}]), "loaded" ) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( sudo(%W[/sbin/kextunload -b #{kext_id}]), ) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( sudo(%W[/usr/sbin/kextfind -b #{kext_id}]), "/Library/Extensions/FancyPackage.kext\n" ) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( sudo(["/bin/rm", "-rf", "/Library/Extensions/FancyPackage.kext"]), ) @@ -117,11 +117,11 @@ shared_examples "#uninstall_phase or #zap_phase" do end it "is supported" do - Hbc::FakeSystemCommand.stubs_command( + FakeSystemCommand.stubs_command( %w[/bin/launchctl list], "999\t0\t#{bundle_id}\n" ) - Hbc::FakeSystemCommand.stubs_command( + FakeSystemCommand.stubs_command( %w[/bin/launchctl list], ) @@ -136,7 +136,7 @@ shared_examples "#uninstall_phase or #zap_phase" do let(:unix_pids) { [12_345, 67_890] } it "is supported" do - Hbc::FakeSystemCommand.stubs_command( + FakeSystemCommand.stubs_command( %w[/bin/launchctl list], unix_pids.map { |pid| [pid, 0, bundle_id].join("\t") }.join("\n") ) @@ -171,7 +171,7 @@ shared_examples "#uninstall_phase or #zap_phase" do end end - let(:fake_system_command) { Hbc::NeverSudoSystemCommand } + let(:fake_system_command) { NeverSudoSystemCommand } let(:cask) { Hbc::CaskLoader.load(cask_path("with-#{artifact_dsl_key}-#{directive}")) } before(:each) do @@ -197,7 +197,7 @@ shared_examples "#uninstall_phase or #zap_phase" do end context "using :rmdir" do - let(:fake_system_command) { Hbc::NeverSudoSystemCommand } + let(:fake_system_command) { NeverSudoSystemCommand } let(:cask) { Hbc::CaskLoader.load(cask_path("with-#{artifact_dsl_key}-rmdir")) } let(:empty_directory) { Pathname.new("#{TEST_TMPDIR}/empty_directory_path") } let(:ds_store) { empty_directory.join(".DS_Store") } @@ -224,7 +224,7 @@ shared_examples "#uninstall_phase or #zap_phase" do [:script, :early_script].each do |script_type| context "using #{script_type.inspect}" do - let(:fake_system_command) { Hbc::NeverSudoSystemCommand } + let(:fake_system_command) { NeverSudoSystemCommand } let(:token) { "with-#{artifact_dsl_key}-#{script_type}".tr("_", "-") } let(:cask) { Hbc::CaskLoader.load(cask_path(token.to_s)) } let(:script_pathname) { cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool") } @@ -255,7 +255,7 @@ shared_examples "#uninstall_phase or #zap_phase" do let(:cask) { Hbc::CaskLoader.load(cask_path("with-#{artifact_dsl_key}-login-item")) } it "is supported" do - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( ["/usr/bin/osascript", "-e", 'tell application "System Events" to delete every login ' \ 'item whose name is "Fancy"'], ) diff --git a/Library/Homebrew/test/cask/audit_spec.rb b/Library/Homebrew/test/cask/audit_spec.rb index 8d5b2fdd59..170af5b101 100644 --- a/Library/Homebrew/test/cask/audit_spec.rb +++ b/Library/Homebrew/test/cask/audit_spec.rb @@ -38,7 +38,7 @@ describe Hbc::Audit, :cask do let(:cask) { instance_double(Hbc::Cask) } let(:download) { false } let(:check_token_conflicts) { false } - let(:fake_system_command) { class_double(Hbc::SystemCommand) } + let(:fake_system_command) { class_double(SystemCommand) } let(:audit) { Hbc::Audit.new(cask, download: download, check_token_conflicts: check_token_conflicts, diff --git a/Library/Homebrew/test/cask/cli/list_spec.rb b/Library/Homebrew/test/cask/cli/list_spec.rb index fc1ffb5e2d..968afcca26 100644 --- a/Library/Homebrew/test/cask/cli/list_spec.rb +++ b/Library/Homebrew/test/cask/cli/list_spec.rb @@ -73,7 +73,7 @@ describe Hbc::CLI::List, :cask do casks.each(&InstallHelper.method(:install_without_artifacts_with_caskfile)) transmission.artifacts.select { |a| a.is_a?(Hbc::Artifact::App) }.each do |artifact| - artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) + artifact.install_phase(command: NeverSudoSystemCommand, force: false) end expect { diff --git a/Library/Homebrew/test/cask/cli/zap_spec.rb b/Library/Homebrew/test/cask/cli/zap_spec.rb index e85120f5f7..308c832695 100644 --- a/Library/Homebrew/test/cask/cli/zap_spec.rb +++ b/Library/Homebrew/test/cask/cli/zap_spec.rb @@ -38,13 +38,13 @@ describe Hbc::CLI::Zap, :cask do # # with_zap.must_be :installed? # - # Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app"'], '1') - # Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app" to quit']) - # Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app.from.uninstall"'], '1') - # Hbc::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app.from.uninstall" to quit']) + # FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app"'], '1') + # FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app" to quit']) + # FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app.from.uninstall"'], '1') + # FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app.from.uninstall" to quit']) # - # Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', with_zap.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please']) - # Hbc::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-rf', '--', + # FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', with_zap.staged_path.join('MyFancyPkg','FancyUninstaller.tool'), '--please']) + # FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-rf', '--', # Pathname.new('~/Library/Preferences/my.fancy.app.plist').expand_path]) # # Hbc::CLI::Zap.run('with-zap') diff --git a/Library/Homebrew/test/cask/container/dmg_spec.rb b/Library/Homebrew/test/cask/container/dmg_spec.rb index df99a6264a..a11d798ea7 100644 --- a/Library/Homebrew/test/cask/container/dmg_spec.rb +++ b/Library/Homebrew/test/cask/container/dmg_spec.rb @@ -6,7 +6,7 @@ describe Hbc::Container::Dmg, :cask do dmg = Hbc::Container::Dmg.new( transmission, Pathname(transmission.url.path), - Hbc::SystemCommand, + SystemCommand, ) dmg.mount do |mounts| diff --git a/Library/Homebrew/test/cask/container/naked_spec.rb b/Library/Homebrew/test/cask/container/naked_spec.rb index f147b06b9d..4f3ec2e3d3 100644 --- a/Library/Homebrew/test/cask/container/naked_spec.rb +++ b/Library/Homebrew/test/cask/container/naked_spec.rb @@ -8,9 +8,9 @@ describe Hbc::Container::Naked, :cask do path = Pathname("/tmp/downloads/kevin-spacey.pkg") expected_destination = cask.staged_path.join("kevin spacey.pkg") - container = Hbc::Container::Naked.new(cask, path, Hbc::FakeSystemCommand) + container = Hbc::Container::Naked.new(cask, path, FakeSystemCommand) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( ["/usr/bin/ditto", "--", path, expected_destination], ) diff --git a/Library/Homebrew/test/cask/download_strategy_spec.rb b/Library/Homebrew/test/cask/download_strategy_spec.rb index 3a69edaaf4..0769bb0679 100644 --- a/Library/Homebrew/test/cask/download_strategy_spec.rb +++ b/Library/Homebrew/test/cask/download_strategy_spec.rb @@ -205,7 +205,7 @@ describe "download strategies", :cask do describe Hbc::SubversionDownloadStrategy do let(:url_options) { { using: :svn } } - let(:fake_system_command) { class_double(Hbc::SystemCommand) } + let(:fake_system_command) { class_double(SystemCommand) } let(:downloader) { Hbc::SubversionDownloadStrategy.new(cask, command: fake_system_command) } before do diff --git a/Library/Homebrew/test/cask/dsl/postflight_spec.rb b/Library/Homebrew/test/cask/dsl/postflight_spec.rb index 4ac3ae7cf7..a7877d1abf 100644 --- a/Library/Homebrew/test/cask/dsl/postflight_spec.rb +++ b/Library/Homebrew/test/cask/dsl/postflight_spec.rb @@ -3,7 +3,7 @@ require "test/support/helper/spec/shared_examples/hbc_staged" describe Hbc::DSL::Postflight, :cask do let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) } - let(:dsl) { Hbc::DSL::Postflight.new(cask, Hbc::FakeSystemCommand) } + let(:dsl) { Hbc::DSL::Postflight.new(cask, FakeSystemCommand) } it_behaves_like Hbc::DSL::Base diff --git a/Library/Homebrew/test/cask/dsl/preflight_spec.rb b/Library/Homebrew/test/cask/dsl/preflight_spec.rb index f78944c504..1d152e06ad 100644 --- a/Library/Homebrew/test/cask/dsl/preflight_spec.rb +++ b/Library/Homebrew/test/cask/dsl/preflight_spec.rb @@ -3,7 +3,7 @@ require "test/support/helper/spec/shared_examples/hbc_staged" describe Hbc::DSL::Preflight, :cask do let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) } - let(:dsl) { Hbc::DSL::Preflight.new(cask, Hbc::FakeSystemCommand) } + let(:dsl) { Hbc::DSL::Preflight.new(cask, FakeSystemCommand) } it_behaves_like Hbc::DSL::Base diff --git a/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb b/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb index b2af700dbd..189e526e29 100644 --- a/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb +++ b/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb @@ -2,7 +2,7 @@ require "test/support/helper/spec/shared_examples/hbc_dsl_base" describe Hbc::DSL::UninstallPostflight, :cask do let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) } - let(:dsl) { Hbc::DSL::UninstallPostflight.new(cask, Hbc::FakeSystemCommand) } + let(:dsl) { Hbc::DSL::UninstallPostflight.new(cask, FakeSystemCommand) } it_behaves_like Hbc::DSL::Base end diff --git a/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb b/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb index 8e7fa47eb4..8f4164b07d 100644 --- a/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb +++ b/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb @@ -3,7 +3,7 @@ require "test/support/helper/spec/shared_examples/hbc_staged" describe Hbc::DSL::UninstallPreflight, :cask do let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) } - let(:dsl) { Hbc::DSL::UninstallPreflight.new(cask, Hbc::FakeSystemCommand) } + let(:dsl) { Hbc::DSL::UninstallPreflight.new(cask, FakeSystemCommand) } it_behaves_like Hbc::DSL::Base diff --git a/Library/Homebrew/test/cask/pkg_spec.rb b/Library/Homebrew/test/cask/pkg_spec.rb index eda4f82ce1..2c1f38f0a7 100644 --- a/Library/Homebrew/test/cask/pkg_spec.rb +++ b/Library/Homebrew/test/cask/pkg_spec.rb @@ -1,6 +1,6 @@ describe Hbc::Pkg, :cask do describe "#uninstall" do - let(:fake_system_command) { Hbc::NeverSudoSystemCommand } + let(:fake_system_command) { NeverSudoSystemCommand } let(:empty_response) { double(stdout: "", plist: { "volume" => "/", "install-location" => "", "paths" => {} }) } let(:pkg) { described_class.new("my.fake.pkg", fake_system_command) } @@ -101,7 +101,7 @@ describe Hbc::Pkg, :cask do end describe "#info" do - let(:fake_system_command) { class_double(Hbc::SystemCommand) } + let(:fake_system_command) { class_double(SystemCommand) } let(:volume) { "/" } let(:install_location) { "tmp" } @@ -148,7 +148,7 @@ describe Hbc::Pkg, :cask do "/usr/sbin/pkgutil", args: ["--pkg-info-plist", pkg_id], ).and_return( - Hbc::SystemCommand::Result.new(nil, pkg_info_plist, nil, 0), + SystemCommand::Result.new(nil, pkg_info_plist, nil, 0), ) info = pkg.info diff --git a/Library/Homebrew/test/support/helper/cask/fake_system_command.rb b/Library/Homebrew/test/support/helper/cask/fake_system_command.rb index 4e7e53a956..b8f8aa4347 100644 --- a/Library/Homebrew/test/support/helper/cask/fake_system_command.rb +++ b/Library/Homebrew/test/support/helper/cask/fake_system_command.rb @@ -2,73 +2,71 @@ def sudo(*args) ["/usr/bin/sudo", "-E", "--"] + args.flatten end -module Hbc - class FakeSystemCommand - def self.responses - @responses ||= {} - end +class FakeSystemCommand + def self.responses + @responses ||= {} + end - def self.expectations - @expectations ||= {} - end + def self.expectations + @expectations ||= {} + end - def self.system_calls - @system_calls ||= Hash.new(0) - end + def self.system_calls + @system_calls ||= Hash.new(0) + end - def self.clear - @responses = nil - @expectations = nil - @system_calls = nil - end + def self.clear + @responses = nil + @expectations = nil + @system_calls = nil + end - def self.stubs_command(command, response = "") - command = command.map(&:to_s) - responses[command] = response - end + def self.stubs_command(command, response = "") + command = command.map(&:to_s) + responses[command] = response + end - def self.expects_command(command, response = "", times = 1) - command = command.map(&:to_s) - stubs_command(command, response) - expectations[command] = times - end + def self.expects_command(command, response = "", times = 1) + command = command.map(&:to_s) + stubs_command(command, response) + expectations[command] = times + end - def self.verify_expectations! - expectations.each do |command, times| - unless system_calls[command] == times - raise("expected #{command.inspect} to be run #{times} times, but got #{system_calls[command]}") - end + def self.verify_expectations! + expectations.each do |command, times| + unless system_calls[command] == times + raise("expected #{command.inspect} to be run #{times} times, but got #{system_calls[command]}") end end + end - def self.run(command_string, options = {}) - command = Hbc::SystemCommand.new(command_string, options).command - puts command - unless responses.key?(command) - raise("no response faked for #{command.inspect}, faked responses are: #{responses.inspect}") - end - system_calls[command] += 1 - - response = responses[command] - if response.respond_to?(:call) - response.call(command_string, options) - else - Hbc::SystemCommand::Result.new(command, response, "", 0) - end + def self.run(command_string, options = {}) + command = SystemCommand.new(command_string, options).command + puts command + unless responses.key?(command) + raise("no response faked for #{command.inspect}, faked responses are: #{responses.inspect}") end + system_calls[command] += 1 - def self.run!(command, options = {}) - run(command, options.merge(must_succeed: true)) + response = responses[command] + if response.respond_to?(:call) + response.call(command_string, options) + else + SystemCommand::Result.new(command, response, "", 0) end end + + def self.run!(command, options = {}) + run(command, options.merge(must_succeed: true)) + end end RSpec.configure do |config| config.after(:each) do begin - Hbc::FakeSystemCommand.verify_expectations! + FakeSystemCommand.verify_expectations! ensure - Hbc::FakeSystemCommand.clear + FakeSystemCommand.clear end end end diff --git a/Library/Homebrew/test/support/helper/cask/never_sudo_system_command.rb b/Library/Homebrew/test/support/helper/cask/never_sudo_system_command.rb index eb8b677f27..7842d4b178 100644 --- a/Library/Homebrew/test/support/helper/cask/never_sudo_system_command.rb +++ b/Library/Homebrew/test/support/helper/cask/never_sudo_system_command.rb @@ -1,9 +1,7 @@ -require "hbc/system_command" +require "system_command" -module Hbc - class NeverSudoSystemCommand < SystemCommand - def self.run(command, options = {}) - super(command, options.merge(sudo: false)) - end +class NeverSudoSystemCommand < SystemCommand + def self.run(command, options = {}) + super(command, options.merge(sudo: false)) end end diff --git a/Library/Homebrew/test/support/helper/spec/shared_examples/hbc_staged.rb b/Library/Homebrew/test/support/helper/spec/shared_examples/hbc_staged.rb index b69c116fdb..1f2eb5b5d0 100644 --- a/Library/Homebrew/test/support/helper/spec/shared_examples/hbc_staged.rb +++ b/Library/Homebrew/test/support/helper/spec/shared_examples/hbc_staged.rb @@ -14,7 +14,7 @@ shared_examples Hbc::Staged do end it "can run system commands with list-form arguments" do - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( ["echo", "homebrew-cask", "rocks!"], ) @@ -28,7 +28,7 @@ shared_examples Hbc::Staged do it "can execute commands on the Info.plist file" do allow(staged).to receive(:bundle_identifier).and_return("com.example.BasicCask") - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( ["/usr/libexec/PlistBuddy", "-c", "Print CFBundleIdentifier", staged.info_plist_file], ) @@ -38,7 +38,7 @@ shared_examples Hbc::Staged do it "can set a key in the Info.plist file" do allow(staged).to receive(:bundle_identifier).and_return("com.example.BasicCask") - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( ["/usr/libexec/PlistBuddy", "-c", "Set :JVMOptions:JVMVersion 1.6+", staged.info_plist_file], ) @@ -49,7 +49,7 @@ shared_examples Hbc::Staged do fake_pathname = existing_path allow(staged).to receive(:Pathname).and_return(fake_pathname) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( ["/bin/chmod", "-R", "--", "777", fake_pathname], ) @@ -60,7 +60,7 @@ shared_examples Hbc::Staged do fake_pathname = existing_path allow(staged).to receive(:Pathname).and_return(fake_pathname) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( ["/bin/chmod", "-R", "--", "777", fake_pathname, fake_pathname], ) @@ -79,7 +79,7 @@ shared_examples Hbc::Staged do allow(staged).to receive(:current_user).and_return("fake_user") allow(staged).to receive(:Pathname).and_return(fake_pathname) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( sudo("/usr/sbin/chown", "-R", "--", "fake_user:staff", fake_pathname), ) @@ -92,7 +92,7 @@ shared_examples Hbc::Staged do allow(staged).to receive(:current_user).and_return("fake_user") allow(staged).to receive(:Pathname).and_return(fake_pathname) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( sudo("/usr/sbin/chown", "-R", "--", "fake_user:staff", fake_pathname, fake_pathname), ) @@ -104,7 +104,7 @@ shared_examples Hbc::Staged do allow(staged).to receive(:Pathname).and_return(fake_pathname) - Hbc::FakeSystemCommand.expects_command( + FakeSystemCommand.expects_command( sudo("/usr/sbin/chown", "-R", "--", "other_user:other_group", fake_pathname), ) diff --git a/Library/Homebrew/test/cask/system_command_result_spec.rb b/Library/Homebrew/test/system_command_result_spec.rb similarity index 97% rename from Library/Homebrew/test/cask/system_command_result_spec.rb rename to Library/Homebrew/test/system_command_result_spec.rb index 84d8b55fe8..fe2a8df80f 100644 --- a/Library/Homebrew/test/cask/system_command_result_spec.rb +++ b/Library/Homebrew/test/system_command_result_spec.rb @@ -1,6 +1,6 @@ -require "hbc/system_command" +require "system_command" -describe Hbc::SystemCommand::Result, :cask do +describe SystemCommand::Result, :cask do describe "#plist" do subject { described_class.new(command, stdout, "", 0).plist } diff --git a/Library/Homebrew/test/cask/system_command_spec.rb b/Library/Homebrew/test/system_command_spec.rb similarity index 99% rename from Library/Homebrew/test/cask/system_command_spec.rb rename to Library/Homebrew/test/system_command_spec.rb index eb6f8e0515..b1d732ac30 100644 --- a/Library/Homebrew/test/cask/system_command_spec.rb +++ b/Library/Homebrew/test/system_command_spec.rb @@ -1,4 +1,4 @@ -describe Hbc::SystemCommand, :cask do +describe SystemCommand, :cask do describe "#initialize" do let(:env_args) { ["bash", "-c", 'printf "%s" "${A?}" "${B?}" "${C?}"'] }