Class: Cask::Artifact::AbstractUninstall Private

Inherits:
AbstractArtifact show all
Includes:
OS::Mac::Cask::Artifact::AbstractUninstall, SystemCommand::Mixin
Defined in:
cask/artifact/abstract_uninstall.rb

Overview

This class is part of a private API. This class may only be used in the Homebrew/brew repository. Third parties should avoid using this class if possible, as it may be removed or changed without warning.

Abstract superclass for uninstall artifacts.

Direct Known Subclasses

Uninstall, Zap

Constant Summary collapse

ORDERED_DIRECTIVES =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

[
  :early_script,
  :launchctl,
  :quit,
  :signal,
  :login_item,
  :kext,
  :script,
  :pkgutil,
  :delete,
  :trash,
  :rmdir,
].freeze
METADATA_KEYS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

[
  :on_upgrade,
].freeze

Constants inherited from AbstractArtifact

Cask::Artifact::AbstractArtifact::DirectivesType

Instance Attribute Summary collapse

Attributes inherited from AbstractArtifact

#cask

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SystemCommand::Mixin

#system_command, #system_command!

Methods inherited from AbstractArtifact

#cask_sandbox, #cask_sandbox_command, #config, dirmethod, dsl_key, english_article, english_name, read_script_arguments, #run_cask_sandbox, #sort_order, #staged_path_join_executable, #to_args

Methods included from Utils::Output::Mixin

#issue_reporting_message, #odebug, #odeprecated, #odie, #odisabled, #ofail, #oh1, #oh1_title, #ohai, #ohai_title, #onoe, #opoo, #opoo_outside_github_actions, #opoo_without_github_actions_annotation, #pretty_deprecated, #pretty_disabled, #pretty_duration, #pretty_install_status, #pretty_installed, #pretty_uninstalled, #pretty_unmarked, #pretty_upgradable, #pretty_warning

Constructor Details

#initialize(cask, **directives) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'cask/artifact/abstract_uninstall.rb', line 47

def initialize(cask, **directives)
  directives.assert_valid_keys(*ORDERED_DIRECTIVES, *METADATA_KEYS)

  super
  directives[:signal] = Array(directives[:signal]).flatten.each_slice(2).to_a
  @directives = directives

  # This is already included when loading from the API.
  return if cask.loaded_from_api?
  return unless directives.key?(:kext)

  cask.caveats do
    T.bind(self, ::Cask::DSL::Caveats)
    kext
  end
end

Instance Attribute Details

#directivesHash{Symbol => DirectivesType} (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



44
45
46
# File 'cask/artifact/abstract_uninstall.rb', line 44

def directives
  @directives
end

Class Method Details

.from_args(cask, **directives) ⇒ AbstractUninstall

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



39
40
41
# File 'cask/artifact/abstract_uninstall.rb', line 39

def self.from_args(cask, **directives)
  new(cask, **directives)
end

Instance Method Details

#bundle_ids_to_reopenArray<String>

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



75
76
77
# File 'cask/artifact/abstract_uninstall.rb', line 75

def bundle_ids_to_reopen
  @bundle_ids_to_reopen ||= T.let([], T.nilable(T::Array[String]))
end

#each_resolved_path(action, paths, &_block) ⇒ T.untyped

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This returns T::Enumerable[[Pathname, T::Array[Pathname]]] when called without a block, but sorbet doesn't support overloads.

Parameters:

Returns:

  • (T.untyped)


129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'cask/artifact/abstract_uninstall.rb', line 129

def each_resolved_path(action, paths, &_block)
  return enum_for(:each_resolved_path, action, paths) unless block_given?

  paths.each do |path|
    resolved_path = Pathname.new(path.to_s.sub(%r{^~(?=(/|$))}, Dir.home))

    if resolved_path.relative?
      opoo "Skipping #{Formatter.identifier(action)} for relative path '#{path}'."
      next
    end

    if resolved_path.each_filename.any? { |part| [".", ".."].include?(part) }
      opoo "Skipping #{Formatter.identifier(action)} for path with relative segments '#{path}'."
      next
    end

    begin
      resolved_paths = Pathname.glob(resolved_path).reject do |target|
        next false unless undeletable?(target)

        opoo "Skipping #{Formatter.identifier(action)} for undeletable path '#{target}'."
        true
      end
      yield path, resolved_paths
    rescue Errno::EPERM
      raise if ::Cask::Utils.full_disk_access_enabled?

      odie "Unable to remove some files. Please enable Full Disk Access for your terminal under " \
           "#{::Cask::Utils.privacy_security_preference_pane("Full Disk Access")}."
    end
  end
end

#find_launchctl_with_wildcard(search) ⇒ Array<String>

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



163
164
165
166
167
168
169
170
171
# File 'cask/artifact/abstract_uninstall.rb', line 163

def find_launchctl_with_wildcard(search)
  regex = Regexp.escape(search).gsub("\\*", ".*")
  system_command!("/bin/launchctl", args: ["list"])
    .stdout.lines.drop(1) # skip stdout column headers
    .filter_map do |line|
      pid, _state, id = line.chomp.split(/\s+/)
      id if pid.to_i.nonzero? && T.must(id).match?(regex)
    end
end

#summarizeString

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



70
71
72
# File 'cask/artifact/abstract_uninstall.rb', line 70

def summarize
  to_h.flat_map { |key, val| Array(val).map { |v| "#{key.inspect} => #{v.inspect}" } }.join(", ")
end

#to_hHash{Symbol => DirectivesType}

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



65
66
67
# File 'cask/artifact/abstract_uninstall.rb', line 65

def to_h
  directives.to_h
end

#uninstall_quit(*bundle_ids, command: nil, upgrade: false, **_kwargs) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method returns an undefined value.

:quit/:signal must come before :kext so the kext will not be in use by a running process

Parameters:

  • bundle_ids (String)
  • command (T.class_of(SystemCommand), nil) (defaults to: nil)
  • upgrade (Boolean) (defaults to: false)
  • _kwargs (T.anything)


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'cask/artifact/abstract_uninstall.rb', line 88

def uninstall_quit(*bundle_ids, command: nil, upgrade: false, **_kwargs)
  bundle_ids.each do |bundle_id|
    next unless running?(bundle_id)

    unless T.must(User.current).gui?
      opoo "Not logged into a GUI; skipping quitting application ID '#{bundle_id}'."
      next
    end

    ohai "Quitting application '#{bundle_id}'..."

    quit_succeeded = T.let(false, T::Boolean)
    begin
      Timeout.timeout(10) do
        Kernel.loop do
          next unless quit(bundle_id).success?

          next if running?(bundle_id)

          puts "Application '#{bundle_id}' quit successfully."
          quit_succeeded = true
          break
        end
      end
    rescue Timeout::Error
      opoo "Application '#{bundle_id}' did not quit. #{automation_access_instructions}"
    end

    bundle_ids_to_reopen << bundle_id if upgrade && quit_succeeded
  end
end