Class: Cask::Artifact::AppImage Private
- Defined in:
- cask/artifact/appimage.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.
Artifact corresponding to the app_image stanza.
Constant Summary
Constants inherited from AbstractArtifact
Cask::Artifact::AbstractArtifact::DirectivesType
Instance Attribute Summary
Attributes inherited from AbstractArtifact
Instance Method Summary collapse
- #install_phase(adopt: false, auto_updates: false, force: false, verbose: false, predecessor: nil, successor: nil, reinstall: false, command: SystemCommand) ⇒ void private
- #resolve_target(target, base_dir: nil) ⇒ Pathname private
- #uninstall_phase(skip: false, force: false, adopt: false, verbose: false, successor: nil, upgrade: false, reinstall: false, command: SystemCommand) ⇒ void private
Methods inherited from Moved
#adopted?, #backup_copy_args, english_description, #summarize_installed
Methods included from OS::Linux::Cask::Artifact::Moved
Methods included from OS::Mac::Cask::Artifact::Moved
#backup_copy_args, #undeletable?
Methods inherited from Relocated
#add_altname_metadata, from_args, #initialize, #source, #summarize, #target, #to_a
Methods included from OS::Linux::Cask::Artifact::Relocated
Methods inherited from AbstractArtifact
#cask_sandbox, #config, dirmethod, dsl_key, english_article, english_name, #initialize, read_script_arguments, #requires_sudo?, #run_cask_sandbox, #sort_order, #staged_path_join_executable, #summarize, #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_once, #opoo_outside_github_actions, #opoo_without_github_actions_annotation, #pretty_cannot_install, #pretty_deprecated, #pretty_disabled, #pretty_duration, #pretty_install_status, #pretty_installed, #pretty_removed, #pretty_uninstalled, #pretty_unmarked, #pretty_upgradable, #pretty_warning
Constructor Details
This class inherits a constructor from Cask::Artifact::Relocated
Instance Method Details
#install_phase(adopt: false, auto_updates: false, force: false, verbose: false, predecessor: nil, successor: nil, reinstall: false, command: SystemCommand) ⇒ 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.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 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 119 120 121 122 123 124 |
# File 'cask/artifact/appimage.rb', line 28 def install_phase(adopt: false, auto_updates: false, force: false, verbose: false, predecessor: nil, successor: nil, reinstall: false, command: SystemCommand) # Some apps self-integrate their entries, which can be prevented by setting this var. # Ref: https://github.com/AppImage/AppImageSpec/blob/master/draft.md#desktop-integration environment = { "DESKTOPINTEGRATION" => "1" } # Read the desktop entries from the staged AppImage # so a conflicting entry fails the install before anything is moved. make_executable(source, command:) if source.file? desktop_entries = Dir.mktmpdir("appimage-", HOMEBREW_TEMP) do |tmpdir| extract_root = Pathname(tmpdir)/"squashfs-root" extract_from_appimage("*.desktop", extract_root:, command:) .each_with_object({}) do |, entries| # Filter out large non-text binaries named `*.desktop` (e.g. cask opencode-desktop) next if !.file? || .size > DESKTOP_ENTRY_MAX_BYTES desktop_file = DesktopFileParser.new(.read) unless desktop_file.desktop_entry? odebug "Skipping '#{.basename}' as it is not a desktop entry" next end begin desktop_file.replace_program(target.to_s, environment:) rescue ArgumentError odebug "Skipping '#{.basename}' due to malformed `Exec`" next end # The AppImage spec puts the icon `Icon` names at the root of the image. # A path would point outside it, usually to the developer's machine. icon_name = desktop_file.get("Icon").to_s if icon_name.present? && icon_name.exclude?("/") = extract_from_appimage("#{icon_name}.*", extract_root:, command:).find do |path| path.file? && DESKTOP_ENTRY_ICON_EXTENSIONS.include?(path.extname) end icon_extension = &.extname end # Fall back to the spec's `.DirIcon`, the only icon in e.g. cask vscodium, # typed by its contents as it has no extension. ||= extract_from_appimage(".DirIcon", extract_root:, command:).find(&:file?) icon_extension ||= case &.binread(DESKTOP_ENTRY_ICON_HEADER_BYTES) when /\A\x89PNG/n then ".png" when /<svg/ then ".svg" when %r{\A/\* XPM \*/} then ".xpm" end if && icon_extension # Name it after the entry, as `Icon` may be a path. icon = cask.staged_path/"#{.basename(".desktop")}#{icon_extension}" FileUtils.cp , icon desktop_file.update("Icon") { icon.to_s } end entries[.basename.to_s] = desktop_file end rescue SystemCallError => e odebug "Failed to extract the desktop entries from #{source}: #{e}" {} end desktop_entry_dir = Pathname(ENV.fetch("HOMEBREW_XDG_DATA_HOME", "~/.local/share"))./"applications" desktop_entries.each_key do |desktop_entry_name| desktop_entry = desktop_entry_dir/desktop_entry_name next if !desktop_entry.exist? && !desktop_entry.symlink? = "It seems there is already a desktop entry at '#{desktop_entry}'" # An upgrade rewrites the entry whatever it contains. raise CaskError, "#{}. Use `--force` to overwrite." if !force && !adopt && !predecessor opoo "#{}; overwriting." end super make_executable(target, command:) desktop_entries.each do |desktop_entry_name, desktop_file| desktop_entry_dir.mkpath desktop_entry = desktop_entry_dir/desktop_entry_name ohai "Creating desktop entry '#{desktop_entry}'" if desktop_entry.exist? || desktop_entry.symlink? # Take over the entry from any other cask that links to it, # so uninstalling that cask doesn't remove this one's entry. Caskroom.path.glob("*/*/*.desktop").each do |desktop_entry_link| desktop_entry_link.unlink if desktop_entry_link.symlink? && desktop_entry_link.readlink == desktop_entry end desktop_entry.unlink end desktop_entry.write(desktop_file.to_s) FileUtils.ln_sf desktop_entry, cask.staged_path/desktop_entry_name end # Update mimetype cache if possible return if desktop_entries.values.none? { |desktop_file| desktop_file.get("MimeType") } update_mime_info_cache(desktop_entry_dir, command:) end |
#resolve_target(target, base_dir: nil) ⇒ Pathname
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.
12 13 14 |
# File 'cask/artifact/appimage.rb', line 12 def resolve_target(target, base_dir: nil) Pathname.new("#{config.appimagedir}/#{target}") end |
#uninstall_phase(skip: false, force: false, adopt: false, verbose: false, successor: nil, upgrade: false, reinstall: false, command: SystemCommand) ⇒ 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.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'cask/artifact/appimage.rb', line 138 def uninstall_phase(skip: false, force: false, adopt: false, verbose: false, successor: nil, upgrade: false, reinstall: false, command: SystemCommand) desktop_entry_dirs_with_mime_types = cask.staged_path.glob("*.desktop").select(&:symlink?) .filter_map do |desktop_entry_link| desktop_entry = desktop_entry_link.readlink desktop_entry_link.unlink next if !desktop_entry.exist? && !desktop_entry.symlink? mime_types = DesktopFileParser.new(desktop_entry.read).get("MimeType") if desktop_entry.file? ohai "Removing desktop entry '#{desktop_entry}'" desktop_entry.unlink desktop_entry.dirname if mime_types.present? end # Stop the mimetype cache from offering the removed entries desktop_entry_dirs_with_mime_types.uniq.each do |desktop_entry_dir| update_mime_info_cache(desktop_entry_dir, command:) end # Migration shim for the `Symlinked` -> `Moved` transition. # Old installs have the real AppImage in the versioned Caskroom `source` # and a symlink at `target` pointing back to it, # which `Moved#move_back` cannot reverse # (a non-forced uninstall errors; a skipping one leaves the target behind). # The old layout is identified by `target` being that back-symlink # (in the new layout, `target` is the real file), # regardless of whether `source` still exists: # the very breakage this stanza fixes # is a self-updater having already deleted the versioned `source`, # leaving `target` dangling. Reverse the old layout directly instead. # This can be removed once pre-transition installs have aged out. if target.symlink? && target.dirname.join(target.readlink) == source Utils.(target, command:) # Preserve `source` during an upgrade # so that it is captured in the staged-directory backup # that `revert_upgrade` restores (and reinstalls from) # if the new install fails; # a successful upgrade purges that backup afterwards. Utils.(source, command:) unless upgrade return end super end |