Class: Hbc::CLI::Doctor

Inherits:
AbstractCommand show all
Includes:
Hbc::Checkable
Defined in:
Library/Homebrew/cask/lib/hbc/cli/doctor.rb

Instance Attribute Summary

Attributes inherited from AbstractCommand

#args

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Hbc::Checkable

#add_error, #add_warning, #errors, #errors?, #result, #summary, #warnings, #warnings?

Methods inherited from AbstractCommand

abstract?, command_name, needs_init?, run, visible

Methods included from Options

included, #process_arguments

Constructor Details

#initializeDoctor

Returns a new instance of Doctor

Raises:

  • (ArgumentError)


9
10
11
12
13
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 9

def initialize(*)
  super
  return if args.empty?
  raise ArgumentError, "#{self.class.command_name} does not take arguments."
end

Class Method Details

.alt_tapsObject



175
176
177
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 175

def self.alt_taps
  Tap.select { |t| t.cask_dir.exist? && t != Hbc.default_tap }
end

.cask_count_for_tap(tap) ⇒ Object



179
180
181
182
183
184
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 179

def self.cask_count_for_tap(tap)
  Formatter.pluralize(tap.cask_files.count, "cask")
rescue StandardError
  add_error "Unable to read from Tap: #{tap.path}"
  "0"
end

.check_sipObject



149
150
151
152
153
154
155
156
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 149

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

.error_string(string = "Error") ⇒ Object



166
167
168
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 166

def self.error_string(string = "Error")
  Formatter.error("(#{string})")
end

.helpObject



246
247
248
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 246

def self.help
  "checks for configuration issues"
end

.locale_variablesObject



158
159
160
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 158

def self.locale_variables
  ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort
end

.none_stringObject



162
163
164
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 162

def self.none_string
  "<NONE>"
end

.render_cached_downloadsObject



237
238
239
240
241
242
243
244
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 237

def self.render_cached_downloads
  cleanup = CLI::Cleanup.new
  count = cleanup.cache_files.count
  size = cleanup.disk_cleanup_size
  msg = user_tilde(Hbc.cache.to_s)
  msg << " (#{number_readable(count)} files, #{disk_usage_readable(size)})" unless count.zero?
  msg
end

.render_env_var(var) ⇒ Object



196
197
198
199
200
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 196

def self.render_env_var(var)
  return unless ENV.key?(var)
  var = %Q(#{var}="#{ENV[var]}")
  puts user_tilde(var)
end

.render_install_locationObject

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.



209
210
211
212
213
214
215
216
217
218
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 209

def self.render_install_location
  locations = Dir.glob(HOMEBREW_CELLAR.join("brew-cask", "*")).reverse
  if locations.empty?
    none_string
  else
    locations.collect do |l|
      "#{l} #{error_string 'error: legacy install. Run "brew uninstall --force brew-cask".'}"
    end
  end
end

.render_load_path(paths) ⇒ Object



231
232
233
234
235
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 231

def self.render_load_path(paths)
  paths.map(&method(:user_tilde))
  return "#{none_string} #{error_string}" if [*paths].empty?
  paths
end

.render_staging_location(path) ⇒ Object



220
221
222
223
224
225
226
227
228
229
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 220

def self.render_staging_location(path)
  path = Pathname.new(user_tilde(path.to_s))
  if !path.exist?
    "#{path} #{error_string "error: path does not exist"}"
  elsif !path.writable?
    "#{path} #{error_string "error: not writable by current user"}"
  else
    path
  end
end

.render_taps(*taps) ⇒ Object



186
187
188
189
190
191
192
193
194
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 186

def self.render_taps(*taps)
  taps.collect do |tap|
    if tap.path.nil? || tap.path.to_s.empty?
      none_string
    else
      "#{tap.path} (#{cask_count_for_tap(tap)})"
    end
  end
end

.render_with_none(string) ⇒ Object



170
171
172
173
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 170

def self.render_with_none(string)
  return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty?
  none_string
end

.user_tilde(path) ⇒ Object



202
203
204
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 202

def self.user_tilde(path)
  path.gsub(ENV["HOME"], "~")
end

Instance Method Details

#cask_count_for_tap(tap) ⇒ Object



137
138
139
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 137

def cask_count_for_tap(tap)
  self.class.cask_count_for_tap(tap)
end

#check_cached_downloadsObject



73
74
75
76
77
78
79
80
81
82
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 73

def check_cached_downloads
  ohai "Homebrew-Cask Cached Downloads"

  cleanup = CLI::Cleanup.new
  count = cleanup.cache_files.count
  size = cleanup.disk_cleanup_size
  msg = user_tilde(Hbc.cache.to_s)
  msg << " (#{number_readable(count)} files, #{disk_usage_readable(size)})" unless count.zero?
  puts msg
end

#check_environment_variablesObject



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 112

def check_environment_variables
  ohai "Environment Variables"

  environment_variables = %w[
    RUBYLIB
    RUBYOPT
    RUBYPATH
    RBENV_VERSION
    CHRUBY_VERSION
    GEM_HOME
    GEM_PATH
    BUNDLE_PATH
    PATH
    SHELL
  ]

  locale_variables = ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort

  (locale_variables + environment_variables).sort.each(&method(:render_env_var))
end

#check_install_locationObject

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.



45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 45

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

#check_load_pathObject



100
101
102
103
104
105
106
107
108
109
110
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 100

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

#check_software_versionsObject



35
36
37
38
39
40
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 35

def check_software_versions
  ohai "Homebrew-Cask Version", Hbc.full_version
  ohai "macOS", MacOS.full_version
  ohai "SIP", self.class.check_sip
  ohai "Java", SystemConfig.describe_java
end

#check_staging_locationObject



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 59

def check_staging_location
  ohai "Homebrew-Cask Staging Location"

  path = Pathname.new(user_tilde(Hbc.caskroom.to_s))

  if !path.exist?
    add_error "The staging path #{path} does not exist."
  elsif !path.writable?
    add_error "The staging path #{path} is not writable by the current user."
  end

  puts path
end

#check_tapsObject



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 84

def check_taps
  ohai "Homebrew-Cask Taps:"

  default_tap = [Hbc.default_tap]

  alt_taps = Tap.select { |t| t.cask_dir.exist? && t != Hbc.default_tap }

  (default_tap + alt_taps).each do |tap|
    if tap.path.nil? || tap.path.to_s.empty?
      puts none_string
    else
      puts "#{tap.path} (#{cask_count_for_tap(tap)})"
    end
  end
end

#none_stringObject



141
142
143
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 141

def none_string
  self.class.none_string
end

#render_env_var(var) ⇒ Object



145
146
147
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 145

def render_env_var(var)
  self.class.render_env_var(var)
end

#runObject

Raises:



23
24
25
26
27
28
29
30
31
32
33
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 23

def run
  check_software_versions
  check_install_location
  check_staging_location
  check_taps
  check_load_path
  check_environment_variables

  puts summary unless success?
  raise CaskError, "There are some problems with your setup." unless success?
end

#success?Boolean

Returns:

  • (Boolean)


15
16
17
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 15

def success?
  !(errors? || warnings?)
end

#summary_headerObject



19
20
21
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 19

def summary_header
  "Cask's Doctor Checkup"
end

#user_tilde(path) ⇒ Object



133
134
135
# File 'Library/Homebrew/cask/lib/hbc/cli/doctor.rb', line 133

def user_tilde(path)
  self.class.user_tilde(path)
end