Spec-Zone.ru › Homebrew

Руководство по Cask

Каждый cask — это блок Ruby, начинающийся со специальной строки заголовка. Само определение cask всегда заключено в блок do … end. Пример:

cask "anybar" do
  version "0.2.3"
  sha256 "c87dbc6aff5411676a471e84905d69c671b62b93b1210bd95c9d776d087de95c"

  url "https://github.com/tonsky/AnyBar/releases/download/#{version}/AnyBar-#{version}.zip"
  name "AnyBar"
  desc "Menu bar status indicator"
  homepage "https://github.com/tonsky/AnyBar"

  app "AnyBar.app"
end
  • Язык cask является декларативным
  • Подробности о строке заголовка
  • Порядок директив
  • Директивы
    • Обязательные директивы
    • Также требуется как минимум одна директива артефакта
    • Доверие к артефактам cask и изоляция в песочнице
    • Необязательные директивы
  • Описание директив
    • Директива: app
    • Директива: binary
    • Директива: rename
    • Директива: caveats
    • Директива: conflicts_with
    • Директива: depends_on
    • Директива: deprecate! / disable!
    • Директива: desc
    • Директива: *flight
    • Директива: generate_completions_from_executable
    • Директива: installer
    • Директива: language
    • Директива: livecheck
    • Директива: no_autobump!
    • Директива: name
    • Директива: pkg
    • Директива: sha256
    • Директива: suite
    • Директива: uninstall
    • Директива: url
    • Директива: version
    • Директива: zap
  • Условные конструкции
    • Обработка различных конфигураций системы
    • Переключение между языками или регионами
  • Произвольные методы Ruby
  • Справочник по токенам
    • Назначение
    • Определение упрощённого названия дистрибутива поставщика
    • Преобразование упрощённого названия в токен
    • Имена файлов cask
    • Заголовки cask
    • Примеры токенов cask
    • Специальные аффиксы

Язык cask является декларативным

Каждый cask содержит набор директив (или «полей»), которые объявляют, как следует получить и установить программное обеспечение. В декларативном языке автору не нужно беспокоиться о порядке. Если присутствуют все необходимые поля, Homebrew Cask сам определит, что нужно сделать во время установки.

Для упрощения сопровождения директивы, которые обновляются чаще всего, обычно размещают в начале. Но это соглашение, а не правило.

Исключение: блоки do, такие как postflight, могут содержать блок чистого кода Ruby. Строки внутри такого блока следуют процедурной парадигме (зависящей от порядка).

Подробности о строке заголовка

Имя cask (<cask-token>) в строке заголовка cask <cask-token> do должно совпадать с именем файла cask без расширения .rb и быть заключено в двойные кавычки.

В настоящее время для токенов cask действуют некоторые произвольные ограничения, которые постепенно отменяются. GitHub Actions выявит ошибки в ходе этого перехода.

Порядок директив

Единый порядок директив упрощает обновление и разбор cask. Ниже приведена полная последовательность директив (ни в одном cask не будут присутствовать все директивы). Пустые строки, показанные здесь, также важны: они помогают визуально отделить информацию.

arch
os

version
sha256

language

url
name
desc
homepage

livecheck

no_autobump!

deprecate!
disable!

auto_updates
conflicts_with
depends_on
container

rename

suite
app
pkg
installer
binary
manpage
bash_completion
fish_completion
zsh_completion
colorpicker
dictionary
font
input_method
internet_plugin
keyboard_layout
prefpane
mdimporter
screen_saver
service
audio_unit_plugin
vst_plugin
vst3_plugin
artifact, target: # target: shown here as is required with `artifact`
stage_only

preflight
preflight_steps

postflight
postflight_steps

uninstall_preflight
uninstall_preflight_steps

uninstall_postflight
uninstall_postflight_steps

uninstall

zap

caveats

Обратите внимание: у каждой директивы с дополнительными параметрами (:symbols после ,) параметры должны располагаться на отдельных строках, по одному на строку, в алфавитном порядке. Исключение — target:, которая обычно состоит из коротких строк.

Директивы

Обязательные директивы

Каждая из следующих директив обязательна для любого cask.

имя допускаются повторения? значение
version нет Версия приложения или специальное значение :latest.
sha256 нет Контрольная сумма SHA-256 файла, загруженного из url, вычисленная командой shasum -a 256 <file>, или специальное значение :no_check.
url нет URL файла .dmg/.zip/.tgz (или другого распространённого формата архива), содержащего приложение. Если домены в директивах url и homepage различаются, следует добавить комментарий.
name да Строка с полным официальным названием, указанным поставщиком.
desc нет Краткое описание cask в одну строку. Отображается при запуске brew info.
homepage нет Домашняя страница приложения; используется командой brew home.
livecheck нет Блок Ruby с описанием способа поиска обновлений для этого cask. Заменяет appcast.
depends_on да Список зависимостей и требований для этого cask.
zap да Дополнительные действия для более полного удаления, включая пользовательские файлы и общие ресурсы.

Также требуется как минимум одна директива артефакта

Каждый cask должен объявлять один или несколько артефактов (то есть того, что нужно установить).

имя допускаются повторения? значение
app да Относительный путь к .app, который при установке следует переместить в папку /Applications.
suite да Относительный путь к содержащему файлы каталогу, который при установке следует переместить в папку /Applications.
pkg да Относительный путь к файлу .pkg, содержащему дистрибутив.
installer да Описывает исполняемый файл, который необходимо запустить для завершения установки.
binary да Относительный путь к бинарному файлу, на который при установке следует создать ссылку в папке $(brew --prefix)/bin.
manpage да Относительный путь к справочной странице man, на которую при установке следует создать ссылку в соответствующей папке man, например /opt/homebrew/share/man/man3 для my_app.3.
bash_completion да Относительный путь к файлу автодополнения Bash, на который при установке следует создать ссылку в папке $(brew --prefix)/etc/bash_completion.d.
fish_completion да Относительный путь к файлу автодополнения fish, на который при установке следует создать ссылку в папке $(brew --prefix)/share/fish/vendor_completions.d.
zsh_completion да Относительный путь к файлу автодополнения Zsh, на который при установке следует создать ссылку в папке $(brew --prefix)/share/zsh/site-functions.
generate_completions_from_executable да Команда и аргументы для создания автодополнения оболочки из исполняемого файла во время установки.
colorpicker да Относительный путь к плагину ColorPicker, который при установке следует переместить в папку ~/Library/ColorPickers.
dictionary да Относительный путь к словарю, который при установке следует переместить в папку ~/Library/Dictionaries.
font да Относительный путь к шрифту, который при установке следует переместить в папку ~/Library/Fonts.
input_method да Относительный путь к методу ввода, который при установке следует переместить в папку ~/Library/Input Methods.
internet_plugin да Относительный путь к интернет-плагину, который при установке следует переместить в папку ~/Library/Internet Plug-Ins.
keyboard_layout да Относительный путь к раскладке клавиатуры, которую при установке следует переместить в папку /Library/Keyboard Layouts.
prefpane да Относительный путь к панели настроек, которую при установке следует переместить в папку ~/Library/PreferencePanes.
mdimporter да Относительный путь к импортеру метаданных Spotlight, который при установке следует переместить в папку ~/Library/Spotlight.
screen_saver да Относительный путь к заставке, которую при установке следует переместить в папку ~/Library/Screen Savers.
service да Относительный путь к службе, которую при установке следует переместить в папку ~/Library/Services.
audio_unit_plugin да Относительный путь к плагину Audio Unit, который при установке следует переместить в папку ~/Library/Audio/Components.
vst_plugin да Относительный путь к плагину VST, который при установке следует переместить в папку ~/Library/Audio/VST.
vst3_plugin да Относительный путь к плагину VST3, который при установке следует переместить в папку ~/Library/Audio/VST3.
artifact да Относительный путь к произвольному пути, который следует переместить при установке. Абсолютный путь необходимо указать как target. (Пример: free-gpgmail.rb) Используется только в нестандартных случаях; при перемещении комплектов .app настоятельно рекомендуется директива app.
stage_only нет true. Указывает, что cask не содержит активируемых артефактов.

Доверие к артефактам cask и изоляция в песочнице

После принятия cask Homebrew считает артефакты установки cask доверенными действиями по установке, выполняемыми поставщиком. Директивы артефактов, такие как app, pkg и installer script, предназначены для установки программного обеспечения и могут записывать данные за пределами Caskroom с помощью перемещений, управляемых Homebrew, служб установки macOS или кода установщика поставщика.

Артефакты автодополнения создаются иначе: generate_completions_from_executable запускает установленный исполняемый файл только для формирования текста автодополнения оболочки. Если Homebrew располагает подходящей песочницей, выполнение происходит в ней. Песочница разрешает чтение подготовленного cask и запись временных файлов и файлов кэша, но блокирует доступ к сети. Это ограничивает побочные эффекты команд, которые должны лишь выводить данные автодополнения.

installer script: не запускается в песочнице. Многие скрипты установки являются установщиками поставщиков, которым необходима широкая запись в файловую систему, службы macOS или sudo; песочница macOS не работает для процессов с правами root, а ограничение списка разрешённых для записи путей только каталогом Caskroom и путями удаления или zap нарушило бы работу установщиков, которым обоснованно нужно записывать данные в другие места. Кроме того, это изменило бы задокументированное поведение SystemCommand, например sudo:, must_succeed: и обработку вывода.

Артефакты pkg также не запускаются в песочнице cask. Их устанавливает /usr/sbin/installer macOS, который применяет содержимое пакета, скрипты и записи в соответствии с метаданными пакета.

Необязательные директивы

имя допускаются повторения? значение
uninstall да Действия по удалению cask. Необязательна, если не используется директива артефакта pkg или installer.
conflicts_with да Список конфликтов с этим cask.
caveats да Строка или блок Ruby с информацией о cask, предназначенной для пользователя и отображаемой во время установки.
deprecate! нет Дата в виде строки в формате YYYY-MM-DD и строка или символ с указанием причины.
disable! нет Дата в виде строки в формате YYYY-MM-DD и строка или символ с указанием причины.
preflight да Блок Ruby с операциями перед установкой (нужен только в очень редких случаях).
preflight_steps да Декларативные шаги подготовки файлов, выполняемые перед установкой артефактов.
postflight да Блок Ruby с операциями после установки.
postflight_steps да Декларативные шаги подготовки файлов, выполняемые после установки артефактов.
uninstall_preflight да Блок Ruby с операциями перед удалением (нужен только в очень редких случаях).
uninstall_preflight_steps да Декларативные шаги подготовки файлов, выполняемые перед удалением артефактов.
uninstall_postflight да Блок Ruby с операциями после удаления.
uninstall_postflight_steps да Декларативные шаги подготовки файлов, выполняемые после удаления артефактов.
language обязательно Блок Ruby, вызываемый с параметрами кода языка и содержащий другие директивы и/или возвращаемое значение.
container nested: нет Относительный путь к внутреннему контейнеру, который необходимо распаковать перед продолжением установки. Это позволяет поддерживать .dmg внутри .tar, .zip внутри .dmg и т. д. (Пример: blocs.rb)
container type: нет Символ для переопределения автоматического определения типа контейнера. Возможные значения: :air, :bz2, :cab, :dmg, :generic_unar, :gzip, :otf, :pkg, :rar, :seven_zip, :sit, :tar, :ttf, :xar, :zip, :naked. (Пример: parse.rb)
auto_updates нет true. Указывает, что артефакты cask обновляются автоматически. Используйте, если в меню приложения есть Check for Updates… или аналогичный пункт, но не используйте, если он лишь открывает веб-страницу и не выполняет загрузку и установку самостоятельно.
no_autobump! нет Допустимый символ или строка. Если задано, cask исключается из автоматического обновления версий.
rename да Пара строк.

Описание директив

Директива: app

В простом случае, когда аргументом app является строка, исходный файл перемещается в целевой каталог /Applications. Например:

app "Alfred 2.app"

по умолчанию перемещает исходный файл в:

/Applications/Alfred 2.app

Переименование целевого объекта

Можно переименовать целевой объект, который появляется в каталоге /Applications, добавив ключ target: в app. Пример (из scala-ide.rb):

app "eclipse.app", target: "Scala IDE.app"

target может содержать абсолютный путь

Если target: начинается с косой черты, он трактуется как абсолютный путь. Если содержащий абсолютный путь каталог ещё не существует, он будет создан. Пример (из sapmachine-jdk.rb):

artifact "sapmachine-jdk-#{version}.jdk", target: "/Library/Java/JavaVirtualMachines/sapmachine-jdk-#{version}.jdk"

target работает с большинством типов артефактов

Ключ target: аналогичным образом работает с большинством артефактов cask, например app, binary, bash_completion, fish_completion, zsh_completion, colorpicker, dictionary, font, input_method, internet_plugin, keyboard_layout, prefpane, mdimporter, screen_saver, service, suite, audio_unit_plugin, vst_plugin, vst3_plugin и artifact.

target следует использовать только в отдельных случаях

Не используйте target: из эстетических соображений, например чтобы убрать номера версий (app "Slack #{version}.app", target: "Slack.app"). Используйте его, когда это функционально оправдано, и чётко укажите причину в cask, воспользовавшись одним из шаблонов: для ясности; для единообразия; для предотвращения конфликтов; по рекомендации разработчика.

Директива: binary

В простом случае, когда аргументом binary является строка, при установке создаётся ссылка на исходный файл в каталоге $(brew --prefix)/bin. Например (из operadriver.rb):

binary "operadriver_mac64/operadriver"

создаёт символическую ссылку на:

$(brew --prefix)/bin/operadriver

из исходного файла, например:

$(brew --caskroom)/operadriver/106.0.5249.119/operadriver_mac64/operadriver

Один или несколько бинарных файлов также могут находиться внутри комплекта приложения:

app "Atom.app"
binary "#{appdir}/Atom.app/Contents/Resources/app/apm/bin/apm"

Целевой объект, который появляется в каталоге бинарных файлов, можно переименовать, добавив ключ target: в binary:

binary "#{appdir}/Atom.app/Contents/Resources/app/atom.sh", target: "atom"

Поведение и использование target: такие же, как у app. Однако для binary указанные ограничения применяются менее строго. Допустимо проявлять больше свободы при задании target:, чтобы обеспечить единообразие с другими инструментами командной строки, например изменить регистр, удалить расширение или упростить имя.

Директива: rename

Директива rename предоставляет вспомогательный метод для переименования файлов, чтобы упростить доступ к ним. Эту директиву следует использовать редко; она предназначена для случаев, когда невозможно заранее определить путь к файлу или каталогу.

Пример ниже можно использовать, если путь pkg содержит, например, метку времени, которую невозможно определить, не распаковав архив, в котором она находится.

# Upstream provides a `pkg` - "foobar-<timestamp>.pkg"
rename "foobar-*.pkg", "foobar.pkg"

Директива: caveats

Иногда установка программного обеспечения имеет особенности, которые Homebrew Cask не может или не должен обрабатывать программно. В таких случаях пользователю сообщают об этом с помощью caveats. Информация из caveats отображается при вызове cask с install или info.

Чтобы не перегружать пользователей сообщениями и не притуплять их внимание к важным уведомлениям, caveats следует использовать редко и только для вопросов, связанных с установкой. Если вы не уверены, относится ли найденный вами caveat к установке, спросите сопровождающего. Как правило, если ваш случай ещё не описан в нашем подробном справочнике caveats mini-DSL, его вряд ли примут.

caveats в виде строки

Если caveats — строка, она вычисляется во время компиляции. Для подстановки доступны следующие методы, если caveats находится в стандартном месте в конце cask:

метод описание
token токен cask
version версия cask
homepage домашняя страница cask
caskroom_path каталог, содержащий этот cask: $(brew --caskroom)/<token> (доступен только при использовании формы с блоком)
staged_path каталог подготовки этого cask, включая номер версии: $(brew --caskroom)/<token>/<version> (доступен только при использовании формы с блоком)

Пример:

caveats "Using #{token} may be hazardous to your health."

caveats в виде блока

Если caveats — блок Ruby, вычисление откладывается до момента установки. Внутри блока можно обращаться к переменной экземпляра @cask и вызывать любой метод, доступный для @cask.

Мини-DSL caveats

Внутри блоков caveats доступен мини-DSL.

Для создания стандартных предупреждений можно вызывать следующие методы:

метод описание
path_environment_variable "path" Пользователям следует убедиться, что path указана в переменной среды PATH.
zsh_path_helper "path" Пользователям zsh необходимо выполнить дополнительные действия, чтобы убедиться, что path указана в переменной среды PATH.
depends_on_java "version" Пользователям следует убедиться, что установлена указанная версия Java. Значение version может быть точным (например, 6), минимальным (например, 7+) или отсутствовать (если подходит любая версия).
requires_rosetta Для запуска cask на Apple Silicon требуется Rosetta 2.
logout Для завершения установки пользователям следует выйти из системы и войти снова.
reboot Для завершения установки пользователям следует перезагрузить компьютер.
files_in_usr_local Cask устанавливает файлы в /usr/local, что может сбить Homebrew с толку.
kext Возможно, пользователям потребуется включить свои kext в разделе Системные настройки → Конфиденциальность и безопасность (или Системные настройки → Защита и безопасность → Основные в более ранних версиях macOS).
unsigned_accessibility Поскольку приложение не подписано, пользователям потребуется повторно разрешать его запуск после каждого обновления в разделе Системные настройки → Конфиденциальность и безопасность (или Системные настройки → Защита и безопасность → Конфиденциальность в более ранних версиях macOS).
license "web_page" Лицензию на использование программы можно найти по адресу web_page.
free_license "web_page" Официальную лицензию на использование программы можно получить по адресу web_page.

Пример:

caveats do
  path_environment_variable "/usr/texbin"
end

Директива: conflicts_with

conflicts_with используется для объявления конфликтов, которые мешают установить cask или нарушают его работу.

conflicts_with cask

Значением должен быть токен другого cask.

Пример: macFUSE, который конфликтует с macfuse-dev.

conflicts_with cask: "macfuse-dev"

Строфа: depends_on

depends_on используется для объявления зависимостей и требований для cask. depends_on проверяется только при попытке выполнить install.

ключ описание
cask: обязательные токены Homebrew cask в виде строки или массива
formula: обязательные имена формул Homebrew в виде строки или массива
macos: требования к версии macOS в виде символа, массива или строкового выражения сравнения
arch: требования к оборудованию в виде символа или массива
java: заглушка — пока не работает

depends_on cask

Значение должно содержать один или несколько токенов cask, необходимых текущему cask, в виде строки или массива строк.

Пример: NTFSTool, которому требуется macFUSE.

depends_on cask: "macfuse"

depends_on formula

Значение должно содержать одно или несколько имён формул, необходимых текущему cask, в виде строки или массива строк.

Пример: некоторые дистрибутивы представлены в форматах архивов, таких как 7z, которые не поддерживаются стандартными инструментами Apple. В таких случаях при установке можно подключить более функциональный архиватор, объявив зависимость от формулы unar:

depends_on formula: "unar"

depends_on macos

Указание минимальной версии macOS

depends_on :macos верхнего уровня помечает cask как предназначенный только для macOS. depends_on macos: верхнего уровня помечает cask как предназначенный только для macOS и объявляет минимальную совместимую версию macOS. Значения поддерживаемых версий macOS можно найти в документации класса MacOSVersion.

Указываются только основные версии (номера 10.x с одной точкой или целые числа, начиная с macOS 11). Для наглядности используется форма с символом:

depends_on macos: :big_sur

depends_on macos: по-прежнему принимает строку, начинающуюся с оператора сравнения, например >=, за которым следует версия macOS в указанном выше формате. Ниже приведено допустимое выражение со значением «не ниже macOS Big Sur (11.0)»:

depends_on macos: ">= :big_sur"

Используйте == в строковой форме только в том случае, если cask должен работать на одной конкретной версии macOS. Если cask должен работать на одной из точно заданных версий macOS, также принимается массив символов:

depends_on macos: [
  :catalina,
  :big_sur,
]

depends_on maximum_macos: верхнего уровня помечает cask как предназначенный только для macOS и объявляет максимальную совместимую версию macOS:

depends_on maximum_macos: :ventura

Для cask, поддерживающего macOS и Linux, но требующего определённую версию macOS, поместите требование к версии macOS внутрь on_macos:

on_macos do
  depends_on macos: :big_sur
end

depends_on linux

depends_on :linux верхнего уровня помечает cask как предназначенный только для Linux.

depends_on arch

Значение depends_on arch: может быть символом или массивом символов, перечисляющим требования совместимости оборудования для cask. Требование считается выполненным при установке, если любое из указанных значений arch: соответствует оборудованию пользователя.

Доступные символы для оборудования:

символ значение
:arm64 Apple Silicon
:x86_64 64-разрядный Intel
:intel 64-разрядный Intel

Все приведённые ниже выражения допустимы:

depends_on arch: :arm64
depends_on arch: :intel
depends_on arch: :x86_64            # same meaning as above
depends_on arch: [:x86_64]          # same meaning as above

Строфа: deprecate! / disable!

deprecate! и disable! используются, чтобы объявить, что cask больше не работает или не поддерживается. Cask со строфой deprecate! всё ещё можно установить, но при установке или обновлении будет выведено предупреждение. Cask со строфой disable! нельзя установить или обновить; вместо этого будет выведено сообщение об ошибке.

Синтаксис обеих строф одинаков:

deprecate! date: "YYYY-MM-DD", because: "is ..."
disable! date: "YYYY-MM-DD", because: "is ..."

# Or with a preset reason and suggested replacement (see the parameter sections below)
deprecate! date: "YYYY-MM-DD", because: :discontinued, replacement_formula: "another"
disable! date: "YYYY-MM-DD", because: :unmaintained, replacement_cask: "alternative"

Параметр date:

Параметр date: определяет, когда вступит в силу устаревание или отключение. Cask со строфой deprecate!, в которой указана будущая дата, не будет считаться устаревшим до наступления этой даты. Cask со строфой disable!, в которой указана будущая дата, будет автоматически считаться устаревшим до этой даты, после чего будет отключено.

Параметр because:

Параметр because: принимает причину, по которой cask устарел или отключён. Информационное сообщение будет иметь вид <cask> is deprecated because it <reason>!, поэтому сформулируйте причину так, чтобы она подходила к этому предложению. Например, because: "is broken" приведёт к сообщению <cask> is deprecated because it is broken!.

Параметр because: также принимает символ, соответствующий предустановленной причине, например:

deprecate! date: "YYYY-MM-DD", because: :discontinued

Полный список допустимых символов приведён в документации модуля DeprecateDisable.

Параметр replacement_formula: / replacement_cask:

Параметры replacement_formula: и replacement_cask: принимают строку с рекомендацией пользователю заменить формулу или cask.

Подробнее о процессе устаревания cask и кода Homebrew см. в разделе Устаревание, отключение и удаление.

Строфа: desc

desc принимает однострочную строку UTF-8 с кратким описанием программного обеспечения. Поскольку описание помогает находить и различать программы, оно должно кратко объяснять, что делает программа (или что с её помощью можно сделать).

desc не предназначена для слоганов приложений! Описания разработчиков часто переполнены общими прилагательными вроде «современный» и «лёгкий». Это бессодержательная маркетинговая шелуха (вы когда-нибудь видели, чтобы приложения с гордостью называли себя устаревшими и громоздкими?), которую необходимо удалить. Можно взять за основу информацию с сайта программы, но почти всегда её придётся отредактировать.

Что следует и чего не следует делать

  • Следует начинать с заглавной буквы.

    - desc "sound and music editor"
    + desc "Sound and music editor"
  • Следует писать кратко, то есть использовать менее 80 символов.

    - desc "Sound and music editor which comes with effects, instruments, sounds and all kinds of creative features"
    + desc "Sound and music editor"
  • Следует описывать, что делает программа или что она собой представляет.

    - desc "Development of musical ideas made easy"
    + desc "Sound and music editor"
  • Не следует указывать платформу. Cask всегда работают в macOS, поэтому такая информация избыточна.

    - desc "Sound and music editor for macOS"
    + desc "Sound and music editor"
  • Не следует включать в описание название cask.

    - desc "Ableton Live is a sound and music editor"
    + desc "Sound and music editor"
  • Не следует указывать разработчика. Вместо этого добавьте его в название cask.

    - desc "Sound and music editor made by Ableton"
    + desc "Sound and music editor"
  • Не следует использовать местоимения, обращённые к пользователю.

    - desc "Edit your music files"
    + desc "Sound and music editor"
  • Не следует использовать бессодержательный маркетинговый жаргон.

    - desc "Beautiful and powerful modern sound and music editor"
    + desc "Sound and music editor"

Строфа: *flight

Строфы preflight, postflight, uninstall_preflight и uninstall_postflight определяют операции, выполняемые до или после установки либо удаления.

Для простой подготовки файлов предпочитайте preflight_steps, postflight_steps, uninstall_preflight_steps или uninstall_postflight_steps. Эти шаги сохраняются в JSON API и избавляют от загрузки Ruby-кода cask для типовых операций.

preflight_steps do
  mkdir_p "Shared"
  touch "Shared/state"
end

postflight_steps do
  mv "payload", "Shared/payload"
  ln_s "Shared/payload", "Payload", source_base: :relative
end

Блок steps может содержать только поддерживаемые вызовы шагов с литеральными аргументами; в нём нельзя вызывать DSL cask или произвольный код Ruby. Для каждой фазы можно определить либо Ruby-блок flight, либо соответствующий ему блок steps, но не оба сразу.

Шаги подготовки файлов

Для относительных путей по умолчанию используется staged_path для base:, source_base: и target_base:. В шагах с символическими ссылками можно использовать uninstall: true, чтобы удалить ссылку при удалении программы.

  • mkdir: создать один каталог; пример: mkdir "Shared".
  • mkdir_p: создать каталог и все отсутствующие родительские каталоги; пример: mkdir_p "Shared".
  • touch: создать файл или обновить его временную метку; пример: touch "Shared/state".
  • move: переместить один файл или каталог; пример: move "payload", "Shared/payload".
  • mv: псевдоним для move; пример: mv "payload", "Shared/payload".
  • move_children: переместить содержимое одного каталога в другой; пример: move_children "payload", "Shared/payload".
  • symlink: создать символическую ссылку; пример: symlink "Shared/payload", "Payload", source_base: :relative.
  • ln_s: псевдоним для symlink; пример: ln_s "Shared/payload", "Payload", source_base: :relative.
  • ln_sf: создать или заменить символическую ссылку; пример: ln_sf "Shared/payload", "Payload", source_base: :relative, uninstall: true.
  • write: записать буквальное содержимое в файл, если он ещё не существует; пример: write "Shared/foo.conf", "key = value". Передайте overwrite: true, чтобы всегда заменять файл. В конце добавляется перевод строки, если содержимое ещё не заканчивается на него. В содержимом можно использовать ,, а tokens, which are expanded at install time; any other остаётся без изменений.

В настоящее время блоки flight выполняются вне песочницы cask. Пишите их так, будто в будущем они могут выполняться в песочнице: отдавайте предпочтение приведённым ниже помощникам мини-DSL и ограничивайте запись файловой системы путями, принадлежащими cask.

Блоки всегда выполняются с отложенной обработкой

Блоки Ruby, определённые этими строфами, выполняются только во время установки или удаления. Внутри блока можно обращаться к переменной экземпляра @cask и вызывать любой метод, доступный в @cask.

Мини-DSL *flight

Внутри этих блоков доступен мини-DSL.

Для выполнения стандартных задач можно вызывать следующие методы:

метод доступность описание
set_ownership(paths) preflight, postflight, uninstall_preflight Установить владельца и группу для paths. (Пример: docker-toolbox.rb)
set_permissions(paths, permissions_str) preflight, postflight, uninstall_preflight Установить права доступа в paths на permissions_str. (Пример: ngrok.rb)

По умолчанию set_ownership(paths) назначает владельцем текущего пользователя, а группой — staff. Эти значения можно изменить, передав дополнительные параметры: set_ownership(paths, user: "user", group: "group"). (Пример: hummingbird.rb)

Строфа: generate_completions_from_executable

generate_completions_from_executable запускает установленный исполняемый файл во время установки cask, чтобы создать сценарии автодополнения для оболочек. Первый аргумент — путь к исполняемому файлу (относительно подготовленного каталога cask или абсолютный). Все последующие позиционные аргументы — подкоманды, передаваемые ему.

generate_completions_from_executable "My App.app/Contents/MacOS/my-app", "completions"

Необязательные именованные аргументы:

аргумент описание
shells: Массив оболочек, для которых нужно создать автодополнения. По умолчанию — [:bash, :zsh, :fish]. Используйте [:bash, :zsh, :fish, :pwsh], чтобы добавить PowerShell.
base_name: Базовое имя создаваемых сценариев автодополнения. По умолчанию используется базовое имя исполняемого файла или токен cask, если базовое имя пусто.
shell_parameter_format: Способ передачи имени оболочки исполняемому файлу. По умолчанию имя передаётся как обычный позиционный аргумент. Допустимые значения приведены в таблице ниже.
значение shell_parameter_format: передаваемый аргумент оболочки
(не указано) имя оболочки как обычный аргумент (bash, zsh и т. д.)
:arg --shell=<shell>
:clap устанавливает переменную окружения COMPLETE=<shell>; аргумент не передаётся
:click устанавливает переменную окружения _<PROGNAME>_COMPLETE=<shell>_source; аргумент не передаётся
:cobra completion <shell>; также по умолчанию включает :pwsh
:flag --<shell>
:none аргумент не передаётся
:typer --show-completion <shell>; также по умолчанию включает :pwsh
"<prefix>" (пользовательская строка) префикс, объединённый с именем оболочки
generate_completions_from_executable "My App.app/Contents/MacOS/my-app",
                                     shell_parameter_format: :cobra,
                                     base_name:              "my-app"

Строфа: installer

Эта строфа всегда должна сопровождаться строфой uninstall.

Строфа installer принимает последовательность пар «ключ — значение», первым ключом которой должен быть manual: или script:.

installer manual

installer manual: принимает единственное строковое значение — путь к интерактивному установщику, который пользователь должен запустить позднее. Путь может быть абсолютным или относительным к cask. Пример (из rubymotion.rb):

installer manual: "RubyMotion Installer.app"

installer script

installer script: принимает последовательность пар «ключ — значение», описывающих команду, которая автоматизирует завершение установки. Эту строфу ни в коем случае нельзя использовать для интерактивных установок. Форма аналогична uninstall script::

ключ значение
executable: путь к запускаемому сценарию установки
args: массив аргументов сценария установки
input: массив строк ввода, передаваемых в stdin сценария
must_succeed: установить в false, если выполнение сценария может завершиться ошибкой
print_stderr: установить в false, чтобы подавить вывод stderr
print_stdout: установить в false, чтобы подавить вывод stdout
sudo: установить в true, если сценарию требуется sudo

Сценарии установщика выполняются вне песочницы cask. Используйте их только в том случае, если разработчик предоставляет команду установщика, которую нельзя описать более конкретной строфой артефакта, например app или pkg.

Путь может быть абсолютным или относительным к cask. Пример (из miniforge.rb):

installer script: {
  executable: "Miniforge3-#{version}-MacOSX-x86_64.sh",
  args:       ["-b", "-p", "#{caskroom_path}/base"],
}

Если installer script: не требует никаких пар «ключ — значение», достаточно указать путь к сценарию установки:

installer script: "#{staged_path}/install.sh"

Строфа: language

Строфа language может сопоставлять коды языков ISO 639-1, коды письменностей (ISO 15924) и региональные идентификаторы (ISO 3166-1 Alpha 2), а также их комбинации.

По умолчанию всегда следует использовать английский язык США:

language "zh", "CN" do
  "zh_CN"
end

language "de" do
  "de_DE"
end

language "en-GB" do
  "en_GB"
end

language "en", default: true do
  "en_US"
end

Обратите внимание, что следующие варианты не равнозначны:

language "en", "GB" do
  # matches all locales containing "en" or "GB"
end

language "en-GB" do
  # matches only locales containing "en" and "GB"
end

Возвращаемое значение соответствующего блока language можно получить простым вызовом language.

homepage "https://example.org/#{language}"

Примеры: firefox.rb, battle-net.rb

Установка

Чтобы установить cask на определённом языке, можно передать параметр --language= команде brew install:

brew install firefox --language=it

Строфа: livecheck

Строфа livecheck используется для автоматического получения последней версии cask из журналов изменений, заметок о выпусках, appcast и других источников.

Каждый блок livecheck должен содержать url — строку или символ, указывающий на другие URL в cask (:url или :homepage).

Инструкции по написанию блока livecheck см. в документации brew livecheck.

Строфа: no_autobump!

Строфа no_autobump! исключает cask из списка автоматического обновления. Это означает, что все обновления необходимо выполнять вручную, отправляя pull request в репозиторий Homebrew/homebrew-cask.

Для no_autobump! необходимо указать причину с помощью параметра because:. Он принимает строку или символ, соответствующий предустановленной причине, например:

no_autobump! because: :incompatible_version_format

Полный список допустимых символов приведён в NO_AUTOBUMP_REASONS_LIST.

Cask, в блоке livecheck которых используется strategy :extract_plist или которые содержат version :latest, всегда исключаются из списка автоматического обновления; объявлять no_autobump! не требуется.

Дополнительные сведения об автоматическом обновлении в Homebrew см. на странице Автоматическое обновление.

Строфа: name

name принимает строку UTF-8, определяющую название программы, включая регистр букв и пунктуацию. Она помогает находить и различать программы.

В отличие от токена, который упрощён и ограничен набором символов, строфа name может содержать официальное написание названия программы, включая регистр, пробелы и знаки препинания. Для различения программ рекомендуется указывать полное название приложения, включая название разработчика, если это необходимо. Хороший пример — cask pycharm-ce, название которого указано полностью — Jetbrains PyCharm Community Edition, хотя, скорее всего, оно нигде больше не используется в таком виде.

Дополнительные сведения о программе можно указать в строфе desc.

Строфу name можно повторять несколько раз, если есть полезные альтернативные названия. В первом экземпляре следует использовать латинский алфавит. Например, см. cask cave-story, оригинальное название которого записано не латиницей.

Строфа: pkg

Эта строфа всегда должна сопровождаться строфой uninstall.

Первым аргументом строфы pkg должен быть относительный путь к устанавливаемому файлу .pkg. Пример:

pkg "Unity.pkg"

Последующие аргументы pkg — это пары «ключ — значение», изменяющие процесс установки. В настоящее время поддерживается только ключ choices:.

pkg choices

pkg choices: можно использовать, чтобы переопределить стандартные параметры установки .pkg с помощью -applyChoiceChangesXML. Используется десериализованная версия списка свойств choiceChanges (см. раздел CHOICE CHANGES FILE страницы руководства installer, открываемой командой man -P 'less --pattern "^CHOICE CHANGES FILE"' installer).

Выполнение этой команды macOS installer:

installer -showChoicesXML -pkg '/path/to/my.pkg'

выведет XML, из которого можно извлечь значения choices:, а также соответствующие им параметры графического интерфейса.

Примеры процедуры см. в этом pull request для wireshark-chmodbpf и этом — для wine-staging.

Пример (из lando.rb):

pkg "LandoInstaller.pkg",
    choices: [
      {
        "choiceIdentifier" => "choiceDocker",
        "choiceAttribute"  => "selected",
        "attributeSetting" => 0,
      },
      {
        "choiceIdentifier" => "choiceLando",
        "choiceAttribute"  => "selected",
        "attributeSetting" => 1,
      },
    ]

Пример (из microsoft-office.rb):

pkg "Microsoft_365_and_Office_#{version}_Installer.pkg",
    choices: [
      {
        "choiceIdentifier" => "com.microsoft.autoupdate", # Office16_all_autoupdate.pkg
        "choiceAttribute"  => "selected",
        "attributeSetting" => 0,
      },
    ]

Строфа: sha256

Вычисление SHA-256

Значение sha256 обычно вычисляется командой shasum:

shasum --algorithm 256 <file>

Специальное значение :no_check

Специальное значение sha256 :no_check используется для отключения проверки SHA, если вычисление контрольной суммы непрактично из-за конфигурации исходного проекта, например когда url не меняется между выпусками.

Для sha256 :no_check требуется version :latest, и такое сочетание встречается часто. Однако sha256 :no_check не требует version :latest.

По возможности мы всегда используем контрольную сумму.

Строфа: suite

Некоторые дистрибутивы включают набор из нескольких приложений или приложение с необходимыми данными, которые следует установить вместе в подкаталог /Applications.

Для таких cask используйте строфу suite, чтобы указать каталог с набором приложений. Пример (из racket.rb):

suite "Racket v#{version}"

Значение suite — это всегда обычный каталог, а не пакет .app.

Строфа: uninstall

Если вам не удаётся составить работающую строфу uninstall, всё равно отправьте свой cask. Сопровождающие помогут написать строфу uninstall — просто попросите!

Строфа uninstall обязательна для cask, устанавливаемых с помощью pkg или installer

Для большинства cask действия по удалению определяются автоматически, поэтому явная строфа uninstall не нужна. Однако cask со строфой pkg или installer не сможет корректно удалиться, если не указана строфа uninstall.

Поэтому, хотя DSL cask и не требует этого, пользователям будет гораздо удобнее, если для каждого pkg и installer будет указана соответствующая строфа uninstall.

Строфа uninstall доступна и для других типов артефактов и полезна в некоторых особых случаях. Однако приведённая ниже документация посвящена наиболее типичному случаю — использованию uninstall для определения процедур удаления pkg.

Существует несколько способов удаления

Поскольку установщики pkg могут выполнять произвольные действия, для удаления в каждом случае требуются разные способы. В качестве аргументов uninstall может потребоваться указать одну или несколько следующих пар «ключ — значение».

uninstall pkgutil: — самый простой и полезный способ

Самая простая и полезная директива uninstall — pkgutil:. Она подходит для большинства случаев.

Краткое описание ключей

  • early_script: (строка или хеш) — как script:, но выполняется раньше (для особых случаев; лучше избегать)
  • launchctl: (строка или массив) — идентификаторы заданий launchd, которые следует удалить
  • quit: (строка или массив) — идентификаторы пакетов запущенных приложений, которые нужно закрыть
  • signal: (массив массивов) — номера сигналов и идентификаторы пакетов запущенных приложений, которым нужно отправить сигнал Unix, если quit: не работает (не выполняется, если удаление запущено через brew upgrade или brew reinstall, если это не указано в on_upgrade:)
  • on_upgrade: (символ или массив) — установите в :signal (или [:signal]), чтобы также выполнить директиву signal: во время brew upgrade и brew reinstall
  • login_item: (строка или массив) — названия объектов входа, которые следует удалить
  • kext: (строка или массив) — идентификаторы пакетов расширений ядра, которые следует выгрузить из системы
  • script: (строка или хеш) — относительный путь к сценарию удаления, который будет выполнен через sudo; используйте хеш, если нужны аргументы
  • pkgutil: (строка, регулярное выражение или массив строк и регулярных выражений) — строки или регулярные выражения для сопоставления с идентификаторами пакетов, удаляемых с помощью pkgutil
  • delete: (строка или массив) — заключённые в двойные кавычки абсолютные пути к файлам или деревьям каталогов, которые следует удалить. Используйте только в крайнем случае; настоятельно рекомендуется pkgutil:.
  • rmdir: (строка или массив) — заключённые в двойные кавычки абсолютные пути к каталогам, которые следует удалить, если они пусты; работает рекурсивно
  • trash: (строка или массив) — заключённые в двойные кавычки абсолютные пути к файлам или деревьям каталогов, которые следует переместить в Корзину

Каждый способ uninstall применяется в указанном выше порядке. Порядок расположения ключей uninstall в файле cask не учитывается.

Чтобы подобрать подходящие значения для ключей uninstall, воспользуйтесь вспомогательными сценариями, находящимися в каталоге developer/bin репозитория Homebrew Cask. Каждый из этих сценариев выводит дополнительную документацию при указании параметра -help.

Проще всего составить строфу uninstall в системе, где пакет уже установлен и работает. Инструкции по работе с неустановленным файлом .pkg см. в разделе «Ручная работа с файлом .pkg» ниже.

uninstall pkgutil

Это наиболее полезный ключ удаления. Часто pkgutil: достаточно для полного удаления pkg; его настоятельно рекомендуется использовать вместо delete:.

Идентификаторы недавно установленных пакетов можно вывести с помощью list_recent_pkg_ids:

"$(brew --repository homebrew/cask)/developer/bin/list_recent_pkg_ids"

pkgutil: также принимает регулярное выражение для сопоставления с несколькими идентификаторами пакетов. Эти регулярные выражения несколько отличаются от стандартных. Чтобы проверить регулярное выражение pkgutil: на установленных пакетах, воспользуйтесь list_pkg_ids_by_regexp:

"$(brew --repository homebrew/cask)/developer/bin/list_pkg_ids_by_regexp" <regular-expression>

Список файлов, связанных с идентификатором пакета

Если вам известен ID установленного пакета (см. выше), можно вывести список всех файлов в системе, связанных с этим ID пакета, с помощью команды macOS pkgutil:

pkgutil --files <package.id.goes.here>

Список связанных файлов поможет определить, содержит ли пакет задания launchd или расширения ядра (kext).

uninstall launchctl

ID текущих загруженных заданий launchd можно вывести с помощью скрипта list_loaded_launchjob_ids:

"$(brew --repository homebrew/cask)/developer/bin/list_loaded_launchjob_ids"

ID всех установленных заданий launchd можно вывести с помощью скрипта list_installed_launchjob_ids:

"$(brew --repository homebrew/cask)/developer/bin/list_installed_launchjob_ids"

uninstall quit

quit: отправляет приложению стандартное событие Apple для завершения работы в macOS (эквивалент Cmd+Q), позволяя приложению показать диалоговые окна сохранения перед закрытием. Эта директива выполняется как при brew uninstall, так и при brew upgrade/brew reinstall.

ID пакетов запущенных приложений можно вывести с помощью скрипта list_running_app_ids:

"$(brew --repository homebrew/cask)/developer/bin/list_running_app_ids"

ID пакетов в приложении на диске можно вывести с помощью скрипта list_ids_in_app:

"$(brew --repository homebrew/cask)/developer/bin/list_ids_in_app" '/path/to/application.app'

uninstall signal

signal: должна понадобиться только в редком случае, когда процесс не реагирует на quit:.

ID пакетов для целей signal: можно получить так же, как и для quit:. Значение signal: представляет собой массив массивов, каждая ячейка которого содержит два элемента: нужный сигнал Unix, за которым следует соответствующий ID пакета.

Сигнал Unix можно указать в числовом или строковом формате (подробности см. на справочной странице kill(1)).

Элементы массива signal: применяются по порядку, только если существует процесс, связанный с ID пакета; выполнение прекращается после завершения этого процесса. ID пакета можно повторить, чтобы отправить одному процессу несколько сигналов.

Для остановки процесса лучше использовать наименее строгие из подходящих сигналов. В частности, сигнал KILL может вызывать нежелательные побочные эффекты.

Пример с часто используемыми сигналами в порядке возрастания строгости:

uninstall signal: [
  ["TERM", "fr.madrau.switchresx.daemon"],
  ["QUIT", "fr.madrau.switchresx.daemon"],
  ["INT",  "fr.madrau.switchresx.daemon"],
  ["HUP",  "fr.madrau.switchresx.daemon"],
  ["KILL", "fr.madrau.switchresx.daemon"],
]

Обратите внимание: если указанному ID пакета соответствуют несколько запущенных процессов, сигнал будет отправлен всем подходящим процессам.

В отличие от директив quit:, сигналы Unix отправляются от имени текущего пользователя, а не суперпользователя. Это считается мерой безопасности, поскольку суперпользователь может вывести систему из строя с помощью сигналов. Однако это несоответствие также можно считать ошибкой, которую, возможно, каким-либо образом исправят в будущей версии.

Директивы signal: пропускаются при выполнении brew upgrade и brew reinstall. Чтобы разрешить выполнение этой директивы при обновлении или повторной установке, добавьте on_upgrade: :signal:

uninstall signal:     [["TERM", "com.example.daemon"]],
          on_upgrade: :signal

Чтобы выполнять и quit:, и signal: при обновлении или повторной установке:

uninstall quit:       "com.example.app",
          signal:     [["TERM", "com.example.app"]],
          on_upgrade: :signal

uninstall login_item

Элементы входа, связанные с приложением на диске, можно вывести с помощью скрипта list_login_items_for_app:

"$(brew --repository homebrew/cask)/developer/bin/list_login_items_for_app" '/path/to/application.app'

Обратите внимание: скорее всего, приложение нужно хотя бы один раз открыть, чтобы появились элементы входа.

uninstall kext

ID загруженных в данный момент расширений ядра можно вывести с помощью скрипта list_loaded_kext_ids:

"$(brew --repository homebrew/cask)/developer/bin/list_loaded_kext_ids"

ID в пакете расширения ядра на диске можно вывести с помощью скрипта list_id_in_kext:

"$(brew --repository homebrew/cask)/developer/bin/list_id_in_kext" '/path/to/name.kext'

uninstall script

uninstall script: задаёт набор пар «ключ—значение», описывающих команду для автоматизации завершения удаления. Формат аналогичен installer script::

ключ значение
executable: путь к запускаемому скрипту удаления
args: массив аргументов скрипта удаления
input: массив строк ввода, передаваемых в stdin скрипта
must_succeed: установите в false, если скрипту разрешено завершиться с ошибкой
print_stderr: установите в false, чтобы подавить вывод stderr
print_stdout: установите в false, чтобы подавить вывод stdout
sudo: установите в true, если скрипту требуется sudo

Путь может быть абсолютным или относительным к cask. Пример (из virtualbox.rb):

uninstall script:  {
            executable: "VirtualBox_Uninstall.tool",
            args:       ["--unattended"],
            sudo:       true,
          },
          pkgutil: "org.virtualbox.pkg.*",
          delete:  "/usr/local/bin/vboximg-mount"

Важно отметить, что, хотя script: в приведённом выше примере действительно пытается полностью удалить pkg, её не следует использовать вместо pkgutil:, а только в дополнение к ней, если это возможно.

uninstall delete

delete: следует использовать только в крайнем случае, если другие методы uninstall недостаточны.

Для аргументов uninstall delete: действуют следующие основные правила:

  • Для путей выполняется базовая подстановка тильды: начальная ~ заменяется домашним каталогом.
  • Пути должны быть абсолютными.
  • Подстановка шаблонов выполняется с использованием стандартного набора символов.

Чтобы удалять пользовательские файлы, используйте секцию zap.

uninstall trash

Для аргументов trash: действуют те же правила, что и для delete: выше.

Работа с файлом .pkg вручную

Опытные пользователи могут захотеть вручную работать с файлом .pkg, не устанавливая пакет.

Список файлов, которые могут быть установлены из файла .pkg, можно получить с помощью скрипта list_payload_in_pkg:

"$(brew --repository homebrew/cask)/developer/bin/list_payload_in_pkg" '/path/to/my.pkg'

С помощью скрипта list_apps_in_pkg из файла .pkg можно получить возможные названия приложений, которые помогут определить имя cask:

"$(brew --repository homebrew/cask)/developer/bin/list_apps_in_pkg" '/path/to/my.pkg'

Возможные ID пакетов, которые могут пригодиться для ключа pkgutil:, можно получить из файла .pkg с помощью скрипта list_ids_in_pkg:

"$(brew --repository homebrew/cask)/developer/bin/list_ids_in_pkg" '/path/to/my.pkg'

Ниже описан полностью ручной способ поиска ID пакетов в файле пакета:

  1. Распакуйте /path/to/my.pkg (замените его именем своего пакета) с помощью pkgutil --expand /path/to/my.pkg /tmp/expanded.unpkg.
  2. Распакованный пакет представляет собой папку. ID пакетов содержатся в файлах с именем PackageInfo. Найти эти файлы можно командой find /tmp/expanded.unpkg -name PackageInfo.
  3. Файлы PackageInfo — это XML-файлы; ID пакетов находятся в атрибутах identifier тегов <pkg-info> вида <pkg-info ... identifier="com.oracle.jdk7u51" ... > (лишние атрибуты опущены и заменены многоточиями).
  4. Расширения ядра в пакетах также описываются в файлах PackageInfo. Если присутствуют расширения ядра, команда find /tmp/expanded.unpkg -name PackageInfo -print0 | xargs -0 grep -i kext должна вернуть тег <bundle id> с атрибутом path, содержащим расширение .kext, например <bundle id="com.wavtap.driver.WavTap" ... path="./WavTap.kext" ... />.
  5. После определения ID пакетов распакованный каталог пакета можно удалить.

Секция: url

Предпочтительно использовать HTTPS URL

Если доступен HTTPS URL, предпочтительно использовать его. Обычный HTTP URL следует использовать только при отсутствии безопасной альтернативы.

Дополнительные параметры url

Если простой строки URL недостаточно для загрузки файла, загрузчику на основе curl можно передать дополнительные сведения в виде пар «ключ—значение», добавленных к url:

ключ значение
verified: строка, повторяющая начало url, для проверки
using: единственные допустимые значения — символы :post и :homebrew_curl
cookies: хеш файлов cookie, которые будут установлены для запроса загрузки (пример: oracle-jdk-javadoc.rb)
referer: строка с URL, который будет указан в качестве referer для запроса загрузки (пример: firealpaca.rb)
header: строка или массив строк с заголовками, которые будут заданы для запроса загрузки (примеры: pull-6545, issue-15590)
user_agent: строка с user agent для запроса загрузки. Также можно задать символ :fake, который будет использовать универсальную строку user agent, имитирующую браузер. Если сервер не требует определённого user agent, мы предпочитаем :fake.
data: хеш параметров для POST-запроса (пример: segger-jlink.rb)

Если домены URL и домашней страницы различаются, добавьте verified:

Если домены url и homepage различаются, это несоответствие следует задокументировать параметром verified:, указав минимально возможную часть URL, однозначно идентифицирующую приложение или поставщика, без протокола. (Пример: 1password-cli.rb)

Это необходимо, чтобы пользователь, проверяющий cask, знал: команда Homebrew Cask подтвердила, что URL предоставлен поставщиком, даже если он может выглядеть неофициальным. При добавлении (или последующем изменении, кроме обновления версии) мы, сопровождающие Homebrew Cask, обязаны проверить сведения о url и homepage.

Этот параметр не означает, что источнику следует доверять безоговорочно, однако мы одобряем только те cask, подлинность которых пользователи могут легко проверить простыми способами, например посетив официальную домашнюю страницу или общедоступный репозиторий. Иногда могут применяться несколько более сложные методы, например проверка URL livecheck, который мы определили как официальный. В случаях, когда такая быстрая проверка невозможна (например, если URL загрузки доступен только после регистрации), применяются более строгие правила.

Сложности с поиском URL

По разным причинам веб-браузеры могут скрывать прямой url загрузки. Homebrew Cask предоставляет скрипт list_url_attributes_on_file, который считывает расширенные атрибуты файла и извлекает фактический исходный URL большинства файлов, загруженных браузером в macOS. Обычно скрипт выводит несколько возможных URL; возможно, придётся проверить каждый из них:

$(brew --repository homebrew/cask)/developer/bin/list_url_attributes_on_file <file>

URL Subversion

В редких случаях дистрибутив может быть недоступен через обычный HTTP(S). Поддерживаются также URL Subversion; их можно указать, добавив к url следующие пары «ключ—значение»:

ключ значение
using: единственное допустимое значение — символ :svn
revision: строка, указывающая ревизию Subversion для загрузки
trust_cert: установите в true, чтобы автоматически доверять сертификату, предоставленному сервером (без интерактивного запроса)

URL Git

Артефакты также могут распространяться через репозитории Git. URL, заканчивающиеся на .git, автоматически считаются репозиториями Git; к url можно добавить следующие пары «ключ—значение»:

ключ значение
using: единственное допустимое значение — символ :git
tag: строка, указывающая тег Git для загрузки
revision: строка, указывающая ревизию Git для загрузки
branch: строка, указывающая ветку Git для загрузки
only_path: путь в репозитории, ограничивающий область извлечения. Если требуется только один каталог из большого репозитория, этот параметр может значительно ускорить загрузку. Если параметр указан, пути к артефактам считаются относительными к этому пути. (Пример: font-geo.rb)

URL SourceForge/OSDN

Проекты SourceForge и OSDN (ранее SourceForge.JP) часто используются для распространения бинарных файлов, однако для доступа к ним предлагается множество форматов URL.

Мы предпочитаем URL следующего формата:

https://downloads.sourceforge.net/<project_name>/<filename>.<ext>

Если файл размещён на OSDN, где <subdomain> обычно имеет вид dl или <user>.dl, используйте:

http://<subdomain>.osdn.jp/<project_name>/<release_id>/<filename>.<ext>

Если эти форматы недоступны, а приложение предназначено только для macOS (иначе при загрузке из командной строки по умолчанию будет выбрана версия для Windows), мы предпочитаем использовать следующий формат:

https://sourceforge.net/projects/<project_name>/files/latest/download

Некоторые провайдеры блокируют загрузки из командной строки

Некоторые хостинг-провайдеры активно блокируют HTTP-клиенты командной строки. Такие URL нельзя использовать в cask.

Другие провайдеры могут использовать URL, которые периодически меняются или даже меняются при каждом посещении (например, FossHub). Обычно в таких случаях поставщик активно пытается предотвратить автоматическую загрузку, поэтому мы предпочитаем не добавлять соответствующие cask в основной репозиторий.

Секция: version

version связана с версионированием самого приложения, но не обязана в точности ему соответствовать. Часто её немного изменяют, чтобы её можно было интерполировать в других секциях, обычно в url, создавая cask, для обновления которого нужно менять только version и sha256. При необходимости это можно сделать и более гибко с помощью методов Ruby String.

Например, вместо:

version "1.2.3"
url "https://example.com/file-version-123.dmg"

можно написать:

version "1.2.3"
url "https://example.com/file-version-#{version.delete(".")}.dmg"

Можно также воспользоваться возможностями регулярных выражений. Например, вместо:

version "1.2.3build4"
url "https://example.com/1.2.3/file-version-1.2.3build4.dmg"

можно написать:

version "1.2.3build4"
url "https://example.com/#{version.sub(/build\d+/, "")}/file-version-#{version}.dmg"

Методы version

Однако приведённые выше примеры могут быть трудны для чтения. Поскольку многие из этих преобразований встречаются часто, мы предоставляем ряд вспомогательных методов, помогающих ясно выражать иначе малопонятные случаи:

метод входное значение результат
major 1.2.3-a45,ccdd88 1
minor 1.2.3-a45,ccdd88 2
patch 1.2.3-a45,ccdd88 3-a45
major_minor 1.2.3-a45,ccdd88 1.2
major_minor_patch 1.2.3-a45,ccdd88 1.2.3-a45
minor_patch 1.2.3-a45,ccdd88 2.3-a45
csv.first 1.2.3-a45,ccdd88 1.2.3-a45
csv.second 1.2.3-a45,ccdd88 ccdd88
dots_to_hyphens 1.2.3-a45,ccdd88 1-2-3-a45,ccdd88
no_dots 1.2.3-a45,ccdd88 123-a45,ccdd88

Как и для dots_to_hyphens, мы предоставляем методы для всех логических вариантов {dots,hyphens,underscores}_to_{dots,hyphens,underscores}. То же самое относится к no_dots в виде no_{dots,hyphens,underscores}, а дополнительный no_dividers применяет их все сразу.

Наконец, есть csv, который возвращает массив значений, разделённых запятыми, и заменяет устаревшие методы before_comma и after_comma. Версии со значениями, разделёнными запятыми, следует использовать только в сложных случаях; в идеале на один version должно приходиться не более двух экземпляров ,, хотя доступны методы вплоть до csv.fifth.

Специальное значение :latest

Специальное значение version :latest используется в следующих случаях:

  • url не содержит сведений о версии, и получить версию с помощью livecheck невозможно; или
  • указать правильное значение для version слишком сложно или непрактично даже с использованием наших автоматизированных систем. Например, chromium.rb, для которого выпускается несколько версий в день.

В обоих случаях также требуется использовать специальное значение sha256 :no_check. Cask, использующие version :latest, исключаются из автоматического обновления версии.

Секция: zap

Назначение zap

Секция zap описывает более полное удаление файлов, связанных с cask. Процедуры zap никогда не выполняются по умолчанию, а запускаются только если пользователь использует --zap для uninstall:

brew uninstall --zap firefox

Секции zap могут удалять:

  • Файлы настроек и кэш, хранящиеся в каталоге пользователя ~/Library.
  • Общие ресурсы, например средства обновления приложений. Удаление общих ресурсов может повлиять на другие приложения в результате выполнения brew uninstall --zap. Ответственность за понимание этих последствий несёт конечный пользователь.

Секции zap не должны удалять:

  • Файлы, созданные непосредственно пользователем.

Добавление --force к команде позволит выполнить эти действия, даже если cask больше не установлен:

brew uninstall --zap --force firefox

Синтаксис zap

Формат секции zap соответствует секции uninstall. Доступны все те же директивы. Ключ trash: предпочтительнее delete:.

Пример: dropbox.rb

Создание zap

Самый простой способ — использовать brew generate-zap, который сканирует систему в поисках связанных файлов и каталогов и автоматически формирует секцию. Целевое приложение должно быть запущено хотя бы один раз, чтобы файлы настроек и кэш появились на диске. В некоторых случаях скрипт может ничего не найти, и тогда потребуется создать секцию вручную.

При создании вручную могут помочь:

  • Некоторые из вспомогательных скриптов в каталоге developer/bin
  • sudo find / -iname "*<search item>*"
  • Средство удаления, например AppCleaner
  • Проверка стандартных путей, например /Library/{'Application Support',LaunchAgents,LaunchDaemons,Frameworks,Logs,Preferences,PrivilegedHelperTools} и ~/Library/{'Application Support',Caches,Containers,LaunchAgents,Logs,Preferences,'Saved Application State'}

Если дополнительные файлы не обнаружены, вместо секции zap добавьте следующий комментарий:

# No zap stanza required

Условные операторы

Обработка различных конфигураций системы

Cask могут предоставлять разные версии артефактов в зависимости от текущего выпуска macOS или архитектуры процессора: для этого можно адаптировать секции url / sha256 / version, использовать синтаксис on_<system> (заменяющий условные операторы с MacOS.version или Hardware::CPU) либо применить оба способа.

Если артефакт cask предлагается для архитектур Apple Silicon и Intel в виде отдельных загрузок, вероятно, для них будут доступны немного различающиеся URL. Чтобы настроить URL в зависимости от текущей архитектуры процессора, укажите отдельный хеш для каждого из параметров arm: и intel: в sha256 и используйте специальную секцию arch, чтобы определить уникальные компоненты соответствующих URL для подстановки в url. Дополнительные подстановки можно задать, напрямую вызвав on_arch_conditional. Пример (из libreoffice.rb):

cask "libreoffice" do
  arch arm: "aarch64", intel: "x86-64"
  folder = on_arch_conditional arm: "aarch64", intel: "x86_64"

  version "7.6.0"
  sha256 arm:   "81eab945a33622fc156951e804024d23aa9a745c06743b4947215ed9303ad1c4",
         intel: "ede541af151487f60eb518e310d20dad1a973f3dbe9ff78d782dd29b14ba2946"

  url "https://download.documentfoundation.org/libreoffice/stable/#{version}/mac/#{folder}/LibreOffice_#{version}_MacOS_#{arch}.dmg",
      verified: "download.documentfoundation.org/libreoffice/stable/"
end

Если номер версии различается для разных архитектур, поместите уникальные секции version и (если они проверяются) sha256 в блоки on_arm и on_intel. Пример (из inkscape.rb):

cask "inkscape" do
  arch arm: "arm64", intel: "x86_64"

  on_arm do
    version "1.3.0,42339"
    sha256 "e37b5f8b8995a0ecc41ca7fcae90d79bcd652b7a25d2f6e52c4e2e79aef7fec1"
  end
  on_intel do
    version "1.3.0,42338"
    sha256 "e97de6804d8811dd2f1bc45d709d87fb6fe45963aae710c24a4ed655ecd8eb8a"
  end

  url "https://inkscape.org/gallery/item/#{version.csv.second}/Inkscape-#{version.csv.first}_#{arch}.dmg"
end

Чтобы настроить установленную версию в зависимости от текущего выпуска macOS, используйте ряд блоков on_<system>, охватывающих диапазон поддерживаемых выпусков. Каждый блок может содержать секции, задающие версию для загрузки и настраивающие установку, удаление и поведение livecheck для одного или нескольких выпусков. Пример (из calibre.rb):

cask "calibre" do
  on_sonoma :or_older do
    version "3.48.0"
    sha256 "68829cd902b8e0b2b7d5cf7be132df37bcc274a1e5720b4605d2dd95f3a29168"

    livecheck do
      skip "Legacy version"
    end
  end
  on_sequoia do
    # ...
  end
  on_tahoe :or_newer do
    version "6.25.0"
    sha256 "a7ed19ae0526630ccb138b9afee6dc5169904180b02f7a3089e78d3e0022753b"

    livecheck do
      url "https://github.com/kovidgoyal/calibre"
      strategy :github_latest
    end
  end
end

Такие блоки on_<system> можно вкладывать друг в друга; они могут содержать и другие секции, не перечисленные здесь. Однако требования macOS, зависящие от версии, следует помещать в блоки on_macos, а не в отдельные блоки для выпусков macOS. Примеры: calhash.rb, r.rb, wireshark.rb

Переключение между языками и регионами

Если cask доступен на нескольких языках, можно использовать секцию language, чтобы переключать язык или регион в зависимости от региональных настроек системы.

Произвольные методы Ruby

В исключительных случаях, когда DSL cask недостаточно, можно определить произвольные переменные и методы Ruby внутри cask, создав пространство имён Utils. Пример:

cask "myapp" do
  module Utils
    def self.arbitrary_method
      # ...
    end
  end

  version "1.0"
  sha256 "a32565cdb1673f4071593d4cc9e1c26bc884218b62fef8abc450daa47ba8fa92"

  url "https://#{Utils.arbitrary_method}"
  name "MyApp"
  homepage "https://www.example.com/"
  # ...
end

Используйте это экономно: любой метод, необходимый двум или более cask, следует добавить непосредственно в Homebrew/brew. Также важно, чтобы такие методы были очень эффективными.

Не следует определять переменные и методы вне пространства имён Utils, поскольку они могут конфликтовать с внутренними компонентами Homebrew Cask.

Справочник по токенам

В этом разделе описан алгоритм, реализованный в скрипте generate_cask_token, а также приведены подробные правила и исключения, которые обычно не требуются.

  • Назначение
  • Поиск упрощённого названия дистрибутива поставщика
  • Преобразование упрощённого названия в токен
  • Имена файлов cask
  • Заголовки cask
  • Примеры токенов cask
  • Специальные аффиксы

Назначение

Поставщики программного обеспечения часто непоследовательно называют свои продукты. Вводя строгие правила именования, мы стремимся:

  • Предотвращать повторную отправку одних и тех же пакетов
  • Сократить количество переименований
  • Однозначно сводить название программы к уникальному идентификатору
  • Избегать конфликтов с формулами Homebrew/homebrew-core

При преобразовании названия в краткий токен неизбежно теряются подробности об именах и брендах программного обеспечения. Чтобы указать полное название дистрибутива поставщика, используйте в cask секцию name, принимающую произвольную строку в кодировке UTF-8.

Поиск упрощённого названия дистрибутива поставщика

Упрощённые названия приложений

  • Начните с точного имени пакета приложения, как оно указано на диске, например Google Chrome.app.

  • Если в имени используются буквы вне диапазона A–Z, преобразуйте его в ASCII, как описано в разделе Преобразование в ASCII.

  • Удалите .app в конце.

  • Удалите в конце строку «app», если поставщик оформляет имя в виде «Software App.app».

    • Исключение: если «app» — неотъемлемая часть имени, без которой оно теряет смысл, как в случае с whatsapp.rb.
  • Удалите в конце номера версий или обозначения промежуточных выпусков, например «alpha», «beta» или «release candidate». В настоящее время допускаются строки, обозначающие разные возможности или кодовые базы, например «Community Edition».

    • Исключение: если число обозначает не промежуточный выпуск, а отличает другой продукт другого поставщика, как в случае с kdiff3.rb.
  • Если номер версии расположен в середине имени приложения, его тоже следует удалить.

  • Удалите в конце «Launcher», «Quick Launcher», «Desktop», «for Desktop».

    • Исключение: если суффикс является неотъемлемой частью названия продукта, как в случае с Docker Desktop.app.
  • Удалите в конце строки вроде «Mac», «for Mac», «for OS X», «macOS», «for macOS». Эти термины обычно добавляют к портированному программному обеспечению, например «MAME OS X.app».

    • Исключение: если программное обеспечение не является портом, а «Mac» — неотъемлемая часть имени, без которой оно теряет смысл, как в случае с PlayOnMac.app.
  • Удалите в конце обозначения аппаратной платформы, например «for x86», «32-bit», «ARM».

  • Удалите в конце названия программных платформ, например «Cocoa», «Qt», «Gtk», «Wx», «Java», «Oracle JVM» и т. д.

    • Исключение: если сама платформа является продуктом, для которого создаётся cask.
  • Удалите в конце строки локализации, например «en-US».

  • Если в результате получилось общее название, например «Macintosh Installer», попробуйте добавить в начало имя поставщика или разработчика, отделив его дефисом. Если это не поможет, просто подберите наиболее подходящее название на основе веб-страницы поставщика.

  • Если получившееся название совпадает с именем существующего cask или формулы Homebrew/homebrew-core, добавьте в начало имя поставщика или разработчика, отделив его дефисом, чтобы сделать название уникальным. Пример: unison.rb и panic-unison.rb.

  • Если получившееся название всё ещё совпадает с именем существующей формулы Homebrew/homebrew-core, измените его так, чтобы оно точнее описывало различие, например добавив -app. Пример: формула appium и cask appium-desktop, формула angband и cask angband-app.

  • Некоторые исключения неизбежно не подпадают под эти правила. Если возникла проблема, не стесняйтесь обратиться на форум.

Преобразование в ASCII

  • Если поставщик предоставляет строку локализации на английском языке, предпочтительно использовать её. Вот где её можно найти, в порядке предпочтения:

    • CFBundleDisplayName в главном файле Info.plist пакета приложения
    • CFBundleName в главном файле Info.plist пакета приложения
    • CFBundleDisplayName в InfoPlist.strings каталога локализации en.lproj
    • CFBundleName в InfoPlist.strings каталога локализации en.lproj
    • CFBundleDisplayName в InfoPlist.strings каталога локализации English.lproj
    • CFBundleName в InfoPlist.strings каталога локализации English.lproj
  • Если строки локализации от поставщика нет, выполните романизацию имени с помощью транслитерации или декомпозиции.

  • В крайнем случае переведите имя пакета приложения на английский язык.

Упрощённые названия установщиков на основе pkg

  • Упрощённое название pkg может быть определить сложнее, чем название приложения. Если pkg устанавливает приложение, используйте название этого приложения, следуя приведённым выше правилам. В противном случае просто подберите наиболее подходящее название на основе веб-страницы поставщика.

Упрощённые названия программного обеспечения, не являющегося приложением

  • В настоящее время правила создания токенов для панелей настроек, плагинов Quick Look и нескольких других типов программного обеспечения, устанавливаемого с помощью Homebrew Cask, чётко не определены. Просто подберите наиболее подходящее название на основе имени файла на диске или веб-страницы поставщика. Следите за тем, чтобы названия не дублировались.

    В будущем токены для программного обеспечения, не являющегося приложением, должны стать более стандартизированными.

Преобразование упрощённого названия в токен

Токен — основной идентификатор cask; это уникальная строка, по которой пользователи обращаются к ним при работе.

Чтобы преобразовать упрощённое название приложения (см. выше) в токен:

  • Преобразуйте все буквы в строчные.
  • Замените символ + отдельным английским словом: -plus-.
  • Замените символ @ отдельным английским словом: -at-.
  • Замените пробелы дефисами.
  • Замените подчёркивания дефисами.
  • Замените средние точки/интерпункты дефисами.
  • Оставьте дефисы без изменений.
  • Оставьте цифры без изменений.
  • Удалите все символы, кроме буквенно-цифровых символов и дефисов.
  • Замените несколько дефисов подряд одним дефисом.
  • Удалите дефисы в начале и в конце.

Cask, закреплённые за определёнными версиями

Для cask, закреплённых за определённой версией приложения (например, carbon-copy-cloner@5), следует использовать тот же токен, что и для стандартного cask, с суффиксом @<version-number>. Для Carbon Copy Cloner (carbon-copy-cloner), закреплённого за версией 6, токен будет carbon-copy-cloner@6.

Cask, закреплённые за каналами разработки

Для cask, использующих канал разработки, например бета-версии, следует использовать тот же токен, что и для стандартного cask, с суффиксом @<channel>. Для Google Chrome (google-chrome), использующего канал «beta», токен должен быть google-chrome@beta.

Имена файлов cask

Cask определяются в файле Ruby, названном в соответствии с токеном и имеющем расширение .rb.

Заголовки cask

Токен также указывается в строке заголовка каждого cask.

Примеры токенов cask

В этих примерах показано большинство правил создания токенов:

Имя приложения на диске Упрощённое имя приложения Токен cask Имя файла
Audio Hijack Pro.app Audio Hijack Pro audio-hijack-pro audio-hijack-pro.rb
VLC.app VLC vlc vlc.rb
BetterTouchTool.app BetterTouchTool bettertouchtool bettertouchtool.rb
LPK25 Editor.app LPK25 Editor lpk25-editor lpk25-editor.rb
Sublime Text 2.app Sublime Text sublime-text sublime-text.rb

Для cask с фиксированной версией или каналом разработки:

Токен стандартного cask Вариант Токен cask Имя файла
google-chrome Бета-канал google-chrome@beta google-chrome@beta.rb
vlc Ночной канал vlc@nightly vlc@nightly.rb
carbon-copy-cloner Закреплён за версией 5 carbon-copy-cloner@5 carbon-copy-cloner@5.rb

Специальные аффиксы

В некоторых случаях к токену требуется добавить префикс или суффикс.

Пересечение токенов

Если токен нового cask совпадает с токеном уже существующего cask, характер этого пересечения определяет токен, потенциально для обоих cask. Информацию о дальнейших действиях см. в разделе Форки и приложения с совпадающими названиями.

Потенциально вводящее в заблуждение название

Если токен неофициального программного обеспечения, взаимодействующего с популярным сервисом, может создать впечатление, что оно официальное, а поставщик не уполномочен использовать это название, для устранения неоднозначности необходимо добавить префикс.

В случаях, когда префикс неоднозначен и может создать впечатление, что приложение официальное, можно использовать суффикс -unofficial.

© 2009–present Homebrew contributors
Licensed under the BSD 2-Clause License.
https://docs.brew.sh/Cask-Cookbook

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API