| 
									
										
										
										
											2017-11-03 08:37:06 +10:00
										 |  |  | require "system_config" | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  | require "hbc/checkable" | 
					
						
							| 
									
										
										
										
											2017-11-03 08:37:06 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  | module Hbc | 
					
						
							|  |  |  |   class CLI | 
					
						
							| 
									
										
										
										
											2017-05-20 19:08:03 +02:00
										 |  |  |     class Doctor < AbstractCommand | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |       include Checkable | 
					
						
							| 
									
										
										
										
											2017-11-03 19:09:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-21 00:15:56 +02:00
										 |  |  |       def initialize(*) | 
					
						
							|  |  |  |         super | 
					
						
							|  |  |  |         return if args.empty? | 
					
						
							|  |  |  |         raise ArgumentError, "#{self.class.command_name} does not take arguments." | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |       def success? | 
					
						
							|  |  |  |         !(errors? || warnings?) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def summary_header | 
					
						
							| 
									
										
										
										
											2018-01-29 13:43:21 +00:00
										 |  |  |         "Cask's Doctor Checkup" | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-21 00:15:56 +02:00
										 |  |  |       def run | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |         check_software_versions | 
					
						
							|  |  |  |         check_install_location | 
					
						
							|  |  |  |         check_staging_location | 
					
						
							|  |  |  |         check_taps | 
					
						
							|  |  |  |         check_load_path | 
					
						
							|  |  |  |         check_environment_variables | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         puts summary unless success? | 
					
						
							| 
									
										
										
										
											2018-01-29 13:43:21 +00:00
										 |  |  |         raise CaskError, "There are some problems with your setup." unless success? | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def check_software_versions | 
					
						
							| 
									
										
										
										
											2017-02-05 06:48:08 +01:00
										 |  |  |         ohai "Homebrew-Cask Version", Hbc.full_version | 
					
						
							| 
									
										
										
										
											2017-11-03 08:37:06 +10:00
										 |  |  |         ohai "macOS", MacOS.full_version | 
					
						
							| 
									
										
										
										
											2018-01-13 08:47:05 +10:00
										 |  |  |         ohai "SIP", self.class.check_sip | 
					
						
							| 
									
										
										
										
											2017-11-03 08:37:06 +10:00
										 |  |  |         ohai "Java", SystemConfig.describe_java | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # This could be done by calling into Homebrew, but the situation | 
					
						
							|  |  |  |       # where "doctor" is needed is precisely the situation where such | 
					
						
							|  |  |  |       # things are less dependable. | 
					
						
							|  |  |  |       def check_install_location | 
					
						
							|  |  |  |         ohai "Homebrew-Cask Install Location" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         locations = Dir.glob(HOMEBREW_CELLAR.join("brew-cask", "*")).reverse | 
					
						
							|  |  |  |         if locations.empty? | 
					
						
							|  |  |  |           puts self.class.none_string | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           locations.collect do |l| | 
					
						
							|  |  |  |             add_error "Legacy install at #{l}. Run \"brew uninstall --force brew-cask\"." | 
					
						
							|  |  |  |             puts l | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def check_staging_location | 
					
						
							|  |  |  |         ohai "Homebrew-Cask Staging Location" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-09 23:50:32 +01:00
										 |  |  |         path = Caskroom.path | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-09 11:32:49 +02:00
										 |  |  |         if path.exist? && !path.writable? | 
					
						
							| 
									
										
										
										
											2018-06-09 23:50:32 +01:00
										 |  |  |           add_error "The staging path #{user_tilde(path.to_s)} is not writable by the current user." | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-09 23:50:32 +01:00
										 |  |  |         puts user_tilde(path.to_s) | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def check_taps | 
					
						
							| 
									
										
										
										
											2018-06-09 10:13:28 +02:00
										 |  |  |         default_tap = Tap.default_cask_tap | 
					
						
							|  |  |  |         alt_taps = Tap.select { |t| t.cask_dir.exist? && t != default_tap } | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-09 10:13:28 +02:00
										 |  |  |         ohai "Homebrew-Cask Taps:" | 
					
						
							|  |  |  |         [default_tap, *alt_taps].each do |tap| | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |           if tap.path.nil? || tap.path.to_s.empty? | 
					
						
							|  |  |  |             puts none_string | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             puts "#{tap.path} (#{cask_count_for_tap(tap)})" | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def check_load_path | 
					
						
							|  |  |  |         ohai "Contents of $LOAD_PATH" | 
					
						
							|  |  |  |         paths = $LOAD_PATH.map(&method(:user_tilde)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if paths.empty? | 
					
						
							|  |  |  |           puts none_string | 
					
						
							|  |  |  |           add_error "$LOAD_PATH is empty" | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           puts paths | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def check_environment_variables | 
					
						
							| 
									
										
										
										
											2017-02-05 06:48:08 +01:00
										 |  |  |         ohai "Environment Variables" | 
					
						
							| 
									
										
										
										
											2017-02-04 21:53:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 18:24:52 +01:00
										 |  |  |         environment_variables = %w[
 | 
					
						
							|  |  |  |           RUBYLIB | 
					
						
							|  |  |  |           RUBYOPT | 
					
						
							|  |  |  |           RUBYPATH | 
					
						
							|  |  |  |           RBENV_VERSION | 
					
						
							|  |  |  |           CHRUBY_VERSION | 
					
						
							|  |  |  |           GEM_HOME | 
					
						
							|  |  |  |           GEM_PATH | 
					
						
							|  |  |  |           BUNDLE_PATH | 
					
						
							|  |  |  |           PATH | 
					
						
							|  |  |  |           SHELL | 
					
						
							| 
									
										
										
										
											2018-03-23 11:40:58 +10:00
										 |  |  |           HOMEBREW_CASK_OPTS | 
					
						
							| 
									
										
										
										
											2017-02-04 21:53:35 +01:00
										 |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |         locale_variables = ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         (locale_variables + environment_variables).sort.each(&method(:render_env_var)) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def user_tilde(path) | 
					
						
							|  |  |  |         self.class.user_tilde(path) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def cask_count_for_tap(tap) | 
					
						
							|  |  |  |         self.class.cask_count_for_tap(tap) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def none_string | 
					
						
							|  |  |  |         self.class.none_string | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2017-11-03 19:09:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |       def render_env_var(var) | 
					
						
							|  |  |  |         self.class.render_env_var(var) | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-08-18 22:11:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-13 08:47:05 +10:00
										 |  |  |       def self.check_sip | 
					
						
							|  |  |  |         csrutil = "/usr/bin/csrutil" | 
					
						
							|  |  |  |         return "N/A" unless File.executable?(csrutil) | 
					
						
							|  |  |  |         Open3.capture2(csrutil, "status")[0] | 
					
						
							|  |  |  |              .gsub("This is an unsupported configuration, likely to break in the future and leave your machine in an unknown state.", "") | 
					
						
							|  |  |  |              .gsub("System Integrity Protection status: ", "") | 
					
						
							|  |  |  |              .delete("\t\.").capitalize.strip | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       def self.locale_variables | 
					
						
							| 
									
										
										
										
											2017-02-04 21:53:35 +01:00
										 |  |  |         ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-08-18 22:11:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       def self.none_string | 
					
						
							|  |  |  |         "<NONE>" | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-08-18 22:11:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       def self.error_string(string = "Error") | 
					
						
							| 
									
										
										
										
											2016-08-30 21:38:13 +02:00
										 |  |  |         Formatter.error("(#{string})") | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-08-18 22:11:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 00:36:38 +01:00
										 |  |  |       def self.alt_taps | 
					
						
							| 
									
										
										
										
											2018-06-09 10:13:28 +02:00
										 |  |  |         Tap.select { |t| t.cask_dir.exist? && t != Tap.default_cask_tap } | 
					
						
							| 
									
										
										
										
											2017-01-25 00:36:38 +01:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       def self.cask_count_for_tap(tap) | 
					
						
							| 
									
										
										
										
											2017-05-29 17:50:13 +02:00
										 |  |  |         Formatter.pluralize(tap.cask_files.count, "cask") | 
					
						
							| 
									
										
										
										
											2017-01-25 00:36:38 +01:00
										 |  |  |       rescue StandardError | 
					
						
							| 
									
										
										
										
											2017-12-02 00:53:54 +00:00
										 |  |  |         add_error "Unable to read from Tap: #{tap.path}" | 
					
						
							|  |  |  |         "0" | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-08-18 22:11:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       def self.render_env_var(var) | 
					
						
							| 
									
										
										
										
											2017-02-04 21:53:35 +01:00
										 |  |  |         return unless ENV.key?(var) | 
					
						
							|  |  |  |         var = %Q(#{var}="#{ENV[var]}") | 
					
						
							|  |  |  |         puts user_tilde(var) | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-08-18 22:11:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-04 21:52:04 +01:00
										 |  |  |       def self.user_tilde(path) | 
					
						
							|  |  |  |         path.gsub(ENV["HOME"], "~") | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-24 13:52:43 +02:00
										 |  |  |       def self.help | 
					
						
							|  |  |  |         "checks for configuration issues" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-08-18 22:11:42 +03:00
										 |  |  |   end | 
					
						
							|  |  |  | end |