Руководство по 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 является декларативным
- Подробности о строке заголовка
- Порядок директив
- Директивы
-
Описание директив
- Директива:
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 содержит набор директив (или «полей»), которые объявляют, как следует получить и установить программное обеспечение. В декларативном языке автору не нужно беспокоиться о порядке. Если присутствуют все необходимые поля, 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 пакетов в файле пакета:
- Распакуйте
/path/to/my.pkg(замените его именем своего пакета) с помощьюpkgutil --expand /path/to/my.pkg /tmp/expanded.unpkg. - Распакованный пакет представляет собой папку. ID пакетов содержатся в файлах с именем
PackageInfo. Найти эти файлы можно командойfind /tmp/expanded.unpkg -name PackageInfo. -
Файлы
PackageInfo— это XML-файлы; ID пакетов находятся в атрибутахidentifierтегов<pkg-info>вида<pkg-info ... identifier="com.oracle.jdk7u51" ... >(лишние атрибуты опущены и заменены многоточиями). - Расширения ядра в пакетах также описываются в файлах
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" ... />. - После определения 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и caskappium-desktop, формулаangbandи caskangband-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