Skip to content
Snippets Groups Projects
doctor.rb 3.74 KiB
Newer Older
module Hbc
  class CLI
    class Doctor < AbstractCommand
Markus Reiter's avatar
Markus Reiter committed
      def initialize(*)
        super
        return if args.empty?
        raise ArgumentError, "#{self.class.command_name} does not take arguments."
      end

      def run
        ohai "Homebrew-Cask Version", Hbc.full_version
Markus Reiter's avatar
Markus Reiter committed
        ohai "Homebrew-Cask Install Location", self.class.render_install_location
        ohai "Homebrew-Cask Staging Location", self.class.render_staging_location(Hbc.caskroom)
        ohai "Homebrew-Cask Cached Downloads", self.class.render_cached_downloads
        ohai "Homebrew-Cask Taps:"
Markus Reiter's avatar
Markus Reiter committed
        puts self.class.render_taps(Hbc.default_tap, *self.class.alt_taps)
        ohai "Contents of $LOAD_PATH", self.class.render_load_path($LOAD_PATH)
        ohai "Environment Variables"

        environment_variables = [
          "RUBYLIB",
          "RUBYOPT",
          "RUBYPATH",
          "RBENV_VERSION",
          "CHRUBY_VERSION",
          "GEM_HOME",
          "GEM_PATH",
          "BUNDLE_PATH",
          "PATH",
          "SHELL",
        ]

Markus Reiter's avatar
Markus Reiter committed
        (self.class.locale_variables + environment_variables).sort.each(&self.class.method(:render_env_var))
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed

      def self.locale_variables
        ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed

      def self.none_string
        "<NONE>"
      end
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed

      def self.error_string(string = "Error")
Markus Reiter's avatar
Markus Reiter committed
        Formatter.error("(#{string})")
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed

      def self.render_with_none(string)
        return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty?
        none_string
      end
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed

      def self.alt_taps
Markus Reiter's avatar
Markus Reiter committed
        Tap.select { |t| t.cask_dir.exist? && t != Hbc.default_tap }
      end

      def self.cask_count_for_tap(tap)
        count = tap.cask_files.count
        "#{count} #{count == 1 ? "cask" : "casks"}"
      rescue StandardError
        "0 #{error_string "error reading #{tap.path}"}"
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed

      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)})"
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed
      end

      def self.render_env_var(var)
        return unless ENV.key?(var)
        var = %Q(#{var}="#{ENV[var]}")
        puts user_tilde(var)
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed

      def self.user_tilde(path)
        path.gsub(ENV["HOME"], "~")
      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 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
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed
      end

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

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

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

      def self.help
        "checks for configuration issues"
      end
    end
AnastasiaSulyagina's avatar
AnastasiaSulyagina committed
  end
end