From 0370294cec85f0b5293922080501bf6c25c9bb29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Galv=C3=A3o?= Date: Tue, 19 Jan 2016 20:36:14 +0000 Subject: [PATCH] initial document breaks --- Rakefile | 2 +- developer/bin/list_pkg_ids_by_regexp | 2 +- doc/CASK_LANGUAGE_REFERENCE.md | 891 ------------------ doc/cask_language_reference/all_stanzas.md | 58 ++ doc/cask_language_reference/readme.md | 116 +++ doc/cask_language_reference/stanzas/app.md | 43 + .../stanzas/appcast.md | 19 + .../stanzas/caveats.md | 48 + .../stanzas/conflicts_with.md | 14 + .../stanzas/depends_on.md | 108 +++ doc/cask_language_reference/stanzas/flight.md | 24 + doc/cask_language_reference/stanzas/gpg.md | 11 + .../stanzas/installer.md | 31 + .../stanzas/license.md | 47 + doc/cask_language_reference/stanzas/name.md | 9 + doc/cask_language_reference/stanzas/pkg.md | 17 + doc/cask_language_reference/stanzas/sha256.md | 17 + doc/cask_language_reference/stanzas/suite.md | 11 + .../stanzas/uninstall.md | 199 ++++ doc/cask_language_reference/stanzas/url.md | 89 ++ .../stanzas/version.md | 53 ++ doc/cask_language_reference/stanzas/zap.md | 24 + .../token_reference.md} | 2 +- doc/development/adding_a_cask.md | 0 doc/{ => development}/hacking.md | 2 +- doc/{ => development}/maintaining.md | 0 doc/{src => man_page}/brew-cask.1.md | 0 doc/readme.md | 12 + 28 files changed, 954 insertions(+), 895 deletions(-) delete mode 100644 doc/CASK_LANGUAGE_REFERENCE.md create mode 100644 doc/cask_language_reference/all_stanzas.md create mode 100644 doc/cask_language_reference/readme.md create mode 100644 doc/cask_language_reference/stanzas/app.md create mode 100644 doc/cask_language_reference/stanzas/appcast.md create mode 100644 doc/cask_language_reference/stanzas/caveats.md create mode 100644 doc/cask_language_reference/stanzas/conflicts_with.md create mode 100644 doc/cask_language_reference/stanzas/depends_on.md create mode 100644 doc/cask_language_reference/stanzas/flight.md create mode 100644 doc/cask_language_reference/stanzas/gpg.md create mode 100644 doc/cask_language_reference/stanzas/installer.md create mode 100644 doc/cask_language_reference/stanzas/license.md create mode 100644 doc/cask_language_reference/stanzas/name.md create mode 100644 doc/cask_language_reference/stanzas/pkg.md create mode 100644 doc/cask_language_reference/stanzas/sha256.md create mode 100644 doc/cask_language_reference/stanzas/suite.md create mode 100644 doc/cask_language_reference/stanzas/uninstall.md create mode 100644 doc/cask_language_reference/stanzas/url.md create mode 100644 doc/cask_language_reference/stanzas/version.md create mode 100644 doc/cask_language_reference/stanzas/zap.md rename doc/{cask_token_reference.md => cask_language_reference/token_reference.md} (97%) create mode 100644 doc/development/adding_a_cask.md rename doc/{ => development}/hacking.md (99%) rename doc/{ => development}/maintaining.md (100%) rename doc/{src => man_page}/brew-cask.1.md (100%) create mode 100644 doc/readme.md diff --git a/Rakefile b/Rakefile index 9f2e43e30e..05fd6e7046 100644 --- a/Rakefile +++ b/Rakefile @@ -47,5 +47,5 @@ end desc 'Generate man page from Markdown source' task :man do sh 'ronn --roff --pipe --organization=Homebrew-cask --manual=brew-cask ' \ - 'doc/src/brew-cask.1.md > man/man1/brew-cask.1' + 'doc/man_page/brew-cask.1.md > man/man1/brew-cask.1' end diff --git a/developer/bin/list_pkg_ids_by_regexp b/developer/bin/list_pkg_ids_by_regexp index e9673c7e39..87d557339c 100755 --- a/developer/bin/list_pkg_ids_by_regexp +++ b/developer/bin/list_pkg_ids_by_regexp @@ -71,7 +71,7 @@ essential system files due to an exuberant regexp. For more information, see - https://github.com/caskroom/homebrew-cask/blob/master/doc/CASK_LANGUAGE_REFERENCE.md#uninstall-stanza-details + https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/uninstall.md " exit diff --git a/doc/CASK_LANGUAGE_REFERENCE.md b/doc/CASK_LANGUAGE_REFERENCE.md deleted file mode 100644 index afb028c031..0000000000 --- a/doc/CASK_LANGUAGE_REFERENCE.md +++ /dev/null @@ -1,891 +0,0 @@ -# Cask Language Reference - -This document acts as a complete specification, and covers aspects of the Cask Domain-Specific Language (DSL) which are not needed in most cases. - -* [Casks Are Ruby Blocks](#casks-are-ruby-blocks) -* [The Cask Language Is Declarative](#the-cask-language-is-declarative) -* [Required Stanzas](#required-stanzas) -* [At Least One Artifact Stanza Is Also Required](#at-least-one-artifact-stanza-is-also-required) -* [Optional Stanzas](#optional-stanzas) -* [Conditional Statements](#conditional-statements) -* [Header Line Details](#header-line-details) -* [Name Stanza Details](#name-stanza-details) -* [Caveats Stanza Details](#caveats-stanza-details) -* [Checksum Stanza Details](#checksum-stanza-details) -* [URL Stanza Details](#url-stanza-details) -* [Appcast Stanza Details](#appcast-stanza-details) -* [License Stanza Details](#license-stanza-details) -* [GPG Stanza Details](#gpg-stanza-details) -* [App Stanza Details](#app-stanza-details) -* [Suite Stanza Details](#suite-stanza-details) -* [Pkg Stanza Details](#pkg-stanza-details) -* [Installer Stanza Details](#installer-stanza-details) -* [Depends_on Stanza Details](#depends_on-stanza-details) -* [Conflicts_with Stanza Details](#conflicts_with-stanza-details) -* [Uninstall Stanza Details](#uninstall-stanza-details) -* [\*flight Stanza Details](#flight-stanzas-details) -* [Zap Stanza Details](#zap-stanza-details) -* [Arbitrary Ruby Methods](#arbitrary-ruby-methods) - -## Casks Are Ruby Blocks - -Each Cask is a Ruby block, beginning with a special header line. The Cask definition itself is always enclosed in a `do … end` block. Example: - -```ruby -cask 'alfred' do - version '2.7.1_387' - sha256 'a3738d0513d736918a6d71535ef3d85dd184af267c05698e49ac4c6b48f38e17' - - url "https://cachefly.alfredapp.com/Alfred_#{version}.zip" - name 'Alfred' - homepage 'https://www.alfredapp.com/' - license :freemium - - app 'Alfred 2.app' - app 'Alfred 2.app/Contents/Preferences/Alfred Preferences.app' - - postflight do - suppress_move_to_applications key: 'suppressMoveToApplications' - end -end -``` - -## The Cask Language Is Declarative - -Each Cask contains a series of stanzas (or “fields”) which *declare* how the software is to be obtained and installed. In a declarative language, the author does not need to worry about **order**. As long as all the needed fields are present, Homebrew-Cask will figure out what needs to be done at install time. - -To make maintenance easier, the most-frequently-updated stanzas are usually placed at the top. But that’s a convention, not a rule. - -Exception: `do` blocks such as `postflight` may enclose a block of pure Ruby code. Lines within that block follow a procedural (order-dependent) paradigm. - -## Required Stanzas - -Each of the following stanzas is required for every Cask. - -| name | multiple occurrences allowed? | value | -| ------------------ |------------------------------ | ----------- | -| `version` | no | application version; give value of `:latest` if versioned downloads are not offered -| `sha256` | no | SHA-256 checksum of the file downloaded from `url`, calculated by the command `shasum -a 256 `. Can be suppressed by using the special value `:no_check` (see also [Checksum Stanza Details](#checksum-stanza-details)) -| `url` | no | URL to the `.dmg`/`.zip`/`.tgz`/`.tbz2` file that contains the application. A [comment](#when-url-and-homepage-hostnames-differ-add-a-comment) should be added if the hostnames in the `url` and `homepage` stanzas differ (see also [URL Stanza Details](#url-stanza-details)) -| `name` | yes | a string providing the full and proper name defined by the vendor (see also [Name Stanza Details](#name-stanza-details)) -| `homepage` | no | application homepage; used for the `brew cask home` command -| `license` | no | a symbol identifying the license category for the application (see also [License Stanza Details](#license-stanza-details)) - -## At Least One Artifact Stanza Is Also Required - -Each Cask must declare one or more *artifacts* (i.e. something to install) - -| name | multiple occurrences allowed? | value | -| ------------------ |------------------------------ | ----------- | -| `app` | yes | relative path to an `.app` that should be linked into the `~/Applications` folder on installation (see also [App Stanza Details](#app-stanza-details)) -| `pkg` | yes | relative path to a `.pkg` file containing the distribution (see also [Pkg Stanza Details](#pkg-stanza-details)) -| `binary` | yes | relative path to a Binary that should be linked into the `/usr/local/bin` folder on installation -| `colorpicker` | yes | relative path to a ColorPicker plugin that should be linked into the `~/Library/ColorPickers` folder on installation -| `font` | yes | relative path to a Font that should be linked into the `~/Library/Fonts` folder on installation -| `input_method` | yes | relative path to a Input Method that should be linked into the `~/Library/Input Methods` folder on installation -| `internet_plugin` | yes | relative path to a Service that should be linked into the `~/Library/Internet Plug-Ins` folder on installation -| `prefpane` | yes | relative path to a Preference Pane that should be linked into the `~/Library/PreferencePanes` folder on installation -| `qlplugin` | yes | relative path to a QuickLook Plugin that should be linked into the `~/Library/QuickLook` folder on installation -| `screen_saver` | yes | relative path to a Screen Saver that should be linked into the `~/Library/Screen Savers` folder on installation -| `service` | yes | relative path to a Service that should be linked into the `~/Library/Services` folder on installation -| `audio_unit_plugin`| yes | relative path to an Audio Unit plugin that should be linked into the `~/Library/Audio/Components` folder on installation -| `vst_plugin` | yes | relative path to a VST Plugin that should be linked into the `~/Library/Audio/VST` folder on installation -| `suite` | yes | relative path to a containing directory that should be linked into the `~/Applications` folder on installation (see also [Suite Stanza Details](#suite-stanza-details)) -| `artifact` | yes | relative path to an arbitrary path that should be symlinked on installation. This is only for unusual cases. The `app` stanza is strongly preferred when linking `.app` bundles. -| `installer` | yes | describes an executable which must be run to complete the installation (see [Installer Stanza Details](#installer-stanza-details)) -| `stage_only` | no | `true`. Assert that the Cask contains no activatable artifacts. - -## Optional Stanzas - -| name | multiple occurrences allowed? | value | -| ---------------------- |------------------------------ | ----------- | -| `uninstall` | yes | procedures to uninstall a Cask. Optional unless the `pkg` stanza is used. (see also [Uninstall Stanza Details](#uninstall-stanza-details)) -| `zap` | yes | additional procedures for a more complete uninstall, including user files and shared resources (see also [Zap Stanza Details](#zap-stanza-details)) -| `appcast` | no | a URL providing an appcast feed to find updates for this Cask (see also [Appcast Stanza Details](#appcast-stanza-details)) -| `depends_on` | yes | a list of dependencies and requirements for this Cask (see also [Depends_on Stanza Details](#depends_on-stanza-details)) -| `conflicts_with` | yes | a list of conflicts with this Cask (*not yet functional* see also [Conflicts_with Stanza Details](#conflicts_with-stanza-details)) -| `caveats` | yes | a string or Ruby block providing the user with Cask-specific information at install time (see also [Caveats Stanza Details](#caveats-stanza-details)) -| `preflight` | yes | a Ruby block containing preflight install operations (needed only in very rare cases) -| `postflight` | yes | a Ruby block containing postflight install operations (see also [Postflight Stanza Details](#flight-stanzas-details)) -| `uninstall_preflight` | yes | a Ruby block containing preflight uninstall operations (needed only in very rare cases) -| `uninstall_postflight` | yes | a Ruby block containing postflight uninstall operations -| `accessibility_access` | no | `true` if the application should be granted accessibility access -| `container :nested =>` | no | relative path to an inner container that must be extracted before moving on with the installation; this allows us to support dmg inside tar, zip inside dmg, etc. -| `container :type =>` | no | a symbol to override container-type autodetect. May be one of: `:air`, `:bz2`, `:cab`, `:dmg`, `:generic_unar`, `:gzip`, `:otf`, `:pkg`, `:rar`, `:seven_zip`, `:sit`, `:tar`, `:ttf`, `:xar`, `:zip`, `:naked`. (example [parse.rb](https://github.com/caskroom/homebrew-cask/blob/ffdc9a1aa459d80a084ee0d24176409388efe71f/Casks/parse.rb#L12)) -| `gpg` | no | *stub: not yet functional.* (see also [GPG Stanza Details](#gpg-stanza-details)) -| `auto_updates` | no | `true`. Assert the Cask artifacts auto-update. (Use if `Check for Updates…` or similar is present in app menu) - -## Conditional Statements - -### Efficiency - -Conditional statements are permitted, but only if they are very efficient. -Tests on the following values are known to be acceptable: - -| value | examples -| ----------------------------|-------------------------------------- -| `MacOS.release` | [macports.rb](https://github.com/caskroom/homebrew-cask/blob/9eae0af0daf9b55f81a3af010cca3b0b1272e2db/Casks/macports.rb#L4#L20), [coconutbattery.rb](https://github.com/caskroom/homebrew-cask/blob/2c801af44be29fff7f3cb2996455fce5dd95d1cc/Casks/coconutbattery.rb#L3#L17) -| `Hardware::CPU.is_32_bit?` | [vuescan.rb](https://github.com/caskroom/homebrew-cask/blob/655bfe48b41ae94cb81b1003182b8de5fa2995ef/Casks/vuescan.rb#L5#L9) -| `Hardware::CPU.is_64_bit?` | none, see [Always Fall Through to the Newest Case](#always-fall-through-to-the-newest-case) - -### Version Comparisons - -Tests against `MacOS.release` may use either symbolic names or version -strings with numeric comparison operators: - -```ruby -if MacOS.release <= :mavericks # symbolic name -``` - -```ruby -if MacOS.release <= '10.9' # version string -``` - -The available symbols for OS X versions are: `:cheetah`, `:puma`, `:jaguar`, `:panther`, `:tiger`, `:leopard`, `:snow_leopard`, `:lion`, `:mountain_lion`, `:mavericks`, `:yosemite`, and `:el_capitan`. The corresponding numeric version strings should given as major releases containing a single dot. - -### Always Fall Through to the Newest Case - -Conditionals should be constructed so that the default is the newest OS version or hardware type. When using an `if` statement, test for older versions, and then let the `else` statement hold the latest and greatest. This makes it more likely that the Cask will work without alteration when a new OS is released. Example (from [coconutbattery.rb](https://github.com/caskroom/homebrew-cask/blob/2c801af44be29fff7f3cb2996455fce5dd95d1cc/Casks/coconutbattery.rb)): - -```ruby -if MacOS.release <= :tiger - # ... -elsif MacOS.release <= :snow_leopard - # ... -else - # ... -end -``` - -## Header Line Details - -The first non-comment line in a Cask follows the form: - -```ruby -cask '' do -``` - -`` should match the Cask filename, without the `.rb` extension, -enclosed in single quotes. - -The header line is not entirely strict Ruby: no comma is required after the Cask token. - -There are currently some arbitrary limitations on Cask tokens which are in the process of being removed. The Travis bot will catch any errors during the transition. - -## Name Stanza Details - -`name` accepts a UTF-8 string defining the full name of the software, and is used to help with searchability and disambiguation. It can be repeated multiple times if there are useful alternative names. - -Its first instance should use the latin alphabet, include the software vendor’s name, and be as verbose as possible while still making sense. - -A good example is [`pycharm-ce`](https://github.com/caskroom/homebrew-cask/blob/fc05c0353aebb28e40db72faba04b82ca832d11a/Casks/pycharm-ce.rb#L6#L7). `Jetbrains PyCharm Community Edition` makes sense even though it is likely never referenced as such anywhere, but `Jetbrains PyCharm Community Edition CE` doesn’t, hence why it has a second line. Another example are casks whose original names do not use the latin alphabet, like [`cave-story`](https://github.com/caskroom/homebrew-cask/blob/0fe48607f5656e4f1de58c6884945378b7e6f960/Casks/cave-story.rb#L7#L9). - -Note that `brew cask search` and `brew cask list` are not yet capable of using the information stored in the `name` stanza. - -## Caveats Stanza Details - -### Caveats as a String - -When `caveats` is a string, it is evaluated at compile time. The following methods are available for interpolation if `caveats` is placed in its customary position at the end of the Cask: - -| method | description | -| ------------------ | ----------- | -| `token` | the Cask token -| `version` | the Cask version -| `homepage` | the Cask homepage -| `caskroom_path` | the containing directory for all staged Casks, typically `/opt/homebrew-cask/Caskroom` (only available with block form) -| `staged_path` | the staged location for this Cask, including version number, *eg* `/opt/homebrew-cask/Caskroom/adium/1.5.10` (only available with block form) - -Example: - -```ruby -caveats "Using #{token} is hazardous to your health." -``` - -### Caveats as a Block - -When `caveats` is a Ruby block, evaluation is deferred until install time. Within a block you may refer to the `@cask` instance variable, and invoke any method available on `@cask`. - -### Caveats Mini-DSL - -There is a mini-DSL available within `caveats` blocks. - -The following methods may be called to generate standard warning messages: - -| method | description | -| --------------------------------- | ----------- | -| `path_environment_variable(path)` | users should make sure `path` is in their `$PATH` environment variable -| `zsh_path_helper(path)` | zsh users must take additional steps to make sure `path` is in their `$PATH` environment variable -| `depends_on_java(version)` | users should make sure they have the specified version of java installed. `version` can be exact (e.g. `6`), a minimum (e.g. `7+`), or omitted (when any version works). -| `logout` | users should log out and log back in to complete installation -| `reboot` | users should reboot to complete installation -| `files_in_usr_local` | the Cask installs files to `/usr/local`, which may confuse Homebrew -| `discontinued` | all software development has been officially discontinued upstream -| `free_license(web_page)` | users may get an official license to use the software at `web_page` - -Example: - -```ruby -caveats do - path_environment_variable '/usr/texbin' -end -``` - -## Checksum Stanza Details - -### Calculating the SHA256 - -The `sha256` value is usually calculated by the command: - -```bash -$ shasum -a 256 -``` - -### Special Value `:no_check` - -The special value `sha256 :no_check` is used to turn off SHA checking whenever checksumming is impractical due to the upstream configuration. - -`version :latest` requires `sha256 :no_check`, and this pairing is common. However, `sha256 :no_check` does not require `version :latest`. - -We use a checksum whenever possible. - -## URL Stanza Details - -### HTTPS URLs are Preferred - -If available, an HTTPS URL is preferred. A plain HTTP URL should only be used in the absence of a secure alternative. - -### Additional HTTP/S URL Parameters - -When a plain URL string is insufficient to fetch a file, additional information may be provided to the `curl`-based downloader, in the form of key/value pairs appended to `url`: - -| key | value | -| ------------------ | ----------- | -| `:using` | the symbol `:post` is the only legal value -| `:cookies` | a hash of cookies to be set in the download request -| `:referer` | a string holding the URL to set as referrer in the download request -| `:user_agent` | a string holding the user agent to set for the download request. Can also be set to the symbol `:fake`, which will use a generic Browser-like user agent string. We prefer `:fake` when the server does not require a specific user agent. -| `:data` | a hash of parameters to be set in the POST request - -Example of using `:cookies`: [java.rb](https://github.com/caskroom/homebrew-cask/blob/b78fb320fc303fc503386aa6fac47fdd105ecbfb/Casks/java.rb#L5#L8) - -Example of using `:referer`: [rrootage.rb](https://github.com/caskroom/homebrew-cask/blob/992d34fec0a12193207a91d57b92bfcfb25174ea/Casks/rrootage.rb#L5) - -### When URL and Homepage Hostnames Differ, Add a Comment - -When the hostnames of `url` and `homepage` differ, the discrepancy should be documented with a comment of the form: - -``` -# URL_HOSTNAME is the official download host per the vendor homepage -``` - -Examples can be seen in [visit.rb](https://github.com/caskroom/homebrew-cask/blob/cafcd7cf7922022ea607c5811c63d45863c7ed36/Casks/visit.rb#L5) and [vistrails.rb](https://github.com/caskroom/homebrew-cask/blob/cafcd7cf7922022ea607c5811c63d45863c7ed36/Casks/vistrails.rb#L5). - -These comments must be added so a user auditing the cask knows the URL is the one provided by the vendor, even though it may look unofficial or suspicious. It is our responsibility as Homebrew-Cask maintainers to verify both the `url` and `homepage` information when first added (or subsequently modified, apart from versioning). The exception to this rule is a `homepage` of `github.io` with a `url` of `github.com`, since we know this pair of hostnames is connected. - -### Difficulty Finding a URL - -Web browsers may obscure the direct `url` download location for a variety of reasons. Homebrew-Cask supplies a script which can read extended file attributes to extract the actual source URL for most files downloaded by a browser on OS X. The script usually emits multiple candidate URLs; you may have to test each of them: - -```bash -$ $(brew --repository)/Library/Taps/caskroom/homebrew-cask/developer/bin/list_url_attributes_on_file -``` - -### Subversion URLs - -In rare cases, a distribution may not be available over ordinary HTTP/S. Subversion URLs are also supported, and can be specified by appending the following key/value pairs to `url`: - -| key | value | -| ------------------ | ----------- | -| `:using` | the symbol `:svn` is the only legal value -| `:revision` | a string identifying the subversion revision to download -| `:trust_cert` | set to `true` to automatically trust the certificate presented by the server (avoiding an interactive prompt) - -## Appcast Stanza Details - -The value of the `appcast` stanza is a string, holding the URL for an appcast which provides information on future updates. - -### Required Appcast Parameters - -| key | value | -| ------------------ | ----------- | -| `:checkpoint` | a string holding a custom checksum of the most recent appcast which matches the current Cask versioning. Use `curl --compressed "{{appcast_url}}" | sed 's|[^<]*||g' | shasum --algorithm 256` to calculate it. - -Example: [`atom`](https://github.com/caskroom/homebrew-cask/blob/8f2da08f007d099e603d1d6c64c72b815f7af0b0/Casks/atom.rb#L7#L8) - -There are a few different ways the `appcast` can be determined: - - * If the app is distributed via GitHub releases, the `appcast` will be of the form `https://github.com/{{user}}/{{project}}/releases.atom`. (Example Cask: [`electron`](https://github.com/caskroom/homebrew-cask/blob/b543c9215c0af31a7e2f526429eb3011a5beb597/Casks/electron.rb#L6#L7)) - - * The popular update framework [Sparkle](http://sparkle-project.org) generally uses the `SUFeedURL` property in `Contents/Info.plist` inside `.app` bundles. You can use the script [`find_sparkle_appcast`](https://github.com/caskroom/homebrew-cask/blob/master/developer/bin/find_sparkle_appcast) to add this automatically. (Example Cask: [`glyphs`](https://github.com/caskroom/homebrew-cask/blob/b543c9215c0af31a7e2f526429eb3011a5beb597/Casks/glyphs.rb#L6#L7)) - -* An appcast can be any URL hosted by the app’s developer that changes every time a new release is out (e.g. a changelog HTML page). (Example Cask: [`shortcat`](https://github.com/caskroom/homebrew-cask/blob/b6e5b1ed2fc45f176258b4ca590a488b780555bc/Casks/shortcat.rb#L6#L7)) - -## License Stanza Details - -The `license` stanza is not free-form. A single value must be chosen from a list of valid symbols. - -The values for `license` are categories, rather than fully-specified licenses. For example, `:gpl` is a category; we do not distinguish between versions of the GPL. Similarly, `:cc` and `:bsd` comprise many variants. They must always pertain to the license of the software itself, not the vendor’s business model (a free app to access a paid service is still `:gratis`, not `:freemium`). - -The `license` stanza is intended as an aid to search/filtering of Casks. For full and complete information, the user must always rely on the vendor’s homepage. - -Note that `brew cask search` and `brew cask list` are not yet capable of using the information stored in the `license` stanza. - -### Generic Category Licenses - -Cask authors should use the most specific license category which is also correct. Generic categories are provided for difficult cases. `:unknown` is also perfectly fine if you are unsure. - -Example: [Chromium](http://www.chromium.org/chromium-os/licenses) includes code with multiple licenses, all of which are open source. Chromium licensing is described by the generic category [`:oss`](https://github.com/caskroom/homebrew-cask/blob/54a79f7dcceea9a922a5b608ac99466b9d10a191/Casks/chromium.rb#L7). - -| symbol | meaning | -| ----------- | ----------- | -| `:oss` | open-source software -| `:closed` | closed-source software -| `:unknown` | license unknown -| `:other` | license is known, but fits no category - -### Valid Licenses - -| symbol | generic category | meaning | URL | -| ---------------- | ---------------- | ------------------------------------------------------------------ | ----------- | -| `:gratis` | `:closed` | free-to-use, closed source | -| `:commercial` | `:closed` | not free to use | -| `:freemium` | `:closed` | free-to-use, payment required for full or additional functionality | -| `:affero` | `:oss` | Affero General Public License | -| `:apache` | `:oss` | Apache Public License | -| `:arphic` | `:oss` | Arphic Public License | -| `:artistic` | `:oss` | Artistic License | -| `:bsd` | `:oss` | BSD License | -| `:cc` | `:oss` | Creative Commons License | -| `:eclipse` | `:oss` | Eclipse Public License | -| `:gpl` | `:oss` | GNU Public License | -| `:isc` | `:oss` | Internet Systems Consortium License | -| `:lppl` | `:oss` | LaTeX Project Public License | -| `:ncsa` | `:oss` | University of Illinois/NCSA Open Source License | -| `:mit` | `:oss` | MIT License | -| `:mpl` | `:oss` | Mozilla Public License | -| `:ofl` | `:oss` | SIL Open Font License | -| `:public_domain` | `:oss` | not copyrighted | -| `:ubuntu_font` | `:oss` | Ubuntu Font License | -| `:x11` | `:oss` | X Consortium License | - -## GPG Stanza Details - -**This is a stub for upcoming functionality, and is not fully documented**. - -The `gpg` stanza contains signature information for GPG-signed distributions. The form is: - -```ruby -gpg , => -``` - -where `` is one of `:key_id` or `:key_url`, and `` points to the detached signature of the distribution. Commonly, the signature follows the `url` value. Example: [libreoffice.rb](https://github.com/caskroom/homebrew-cask/blob/ae2b41394f19c864c3ff9dee0818620715fcc07e/Casks/libreoffice.rb#L13#L14). - -## App Stanza Details - -In the simple case of a string argument to `app`, a symlink is created in the target `~/Applications` directory using the same basename as the source file. For example: - -```ruby -app 'Alfred 2.app' -``` - -causes the creation of this symlink: - -```bash -~/Applications/Alfred 2.app -``` - -which points to a source file such as: - -```bash -/opt/homebrew-cask/Caskroom/alfred/2.8.2_431/Alfred 2.app -``` - -### Renaming the Target - -You can rename the target link which appears in your `~/Applications` directory by adding a `:target` key to `app`. Example (from [scala-ide.rb](https://github.com/caskroom/homebrew-cask/blob/84e8df88836a2c11657e09264bd01b96783bb0d1/Casks/scala-ide.rb#L21)): - -```ruby -app 'eclipse/Eclipse.app', target: 'Scala IDE.app' -``` - -### :target May Contain an Absolute Path - -If `:target` has a leading slash, it is interpreted as an absolute path. The containing directory for the absolute path will be created if it does not already exist. Example (from [manopen.rb](https://github.com/caskroom/homebrew-cask/blob/84e8df88836a2c11657e09264bd01b96783bb0d1/Casks/manopen.rb#L12)): - -```ruby -artifact 'openman.1', target: '/usr/local/share/man/man1/openman.1' -``` - -### :target Works on Most Artifact Types - -The `:target` key works similarly for most Cask artifacts, such as `app`, `binary`, `colorpicker`, `font`, `input_method`, `prefpane`, `qlplugin`, `service`, `suite`, and `artifact`. - -### :target Should Only Be Used in Select Cases - -Don’t use `:target` for aesthetic reasons, like removing version numbers (`app "Slack #{version}.app", target: 'Slack.app'`). With `app`, use it when it makes sense functionally and document your reason cleary in the Cask: was it [for clarity](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/imagemin.rb#L11); [for consistency](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/devonthink-pro-office.rb#L14); [to prevent conflicts](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/flash-player-debugger.rb#L13)? With `binary` you can take some extra liberties to be consistent with other command-line tools, like [changing case](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/diffmerge.rb#L11) or [removing an extension](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/filebot.rb#L12). - -## Suite Stanza Details - -Some distributions provide a suite of multiple applications, or an application with required data, to be installed together in a subdirectory of `~/Applications`. - -For these Casks, use the `suite` stanza to define the directory containing the application suite. Example (from [sketchup.rb](https://github.com/caskroom/homebrew-cask/blob/b2c8d178ae8c668b233d390688812980cb3d4a29/Casks/sketchup.rb)): - -```ruby -suite 'SketchUp 2016' -``` - -The value of `suite` is never an `.app` bundle, but a plain directory. - -## Pkg Stanza Details - -The first argument to the `pkg` stanza should be a relative path to the `.pkg` file to be installed. For example: - -```ruby -pkg 'Unity.pkg' -``` - -Subsequent arguments to `pkg` are key/value pairs which modify the install process. Currently supported keys are: - -* `:allow_untrusted` — pass `-allowUntrusted` to `/usr/sbin/installer` - -Example (from [alinof-timer.rb](https://github.com/caskroom/homebrew-cask/blob/9a617c077dc238aac28dc9ad325f8924b19d6306/Casks/alinof-timer.rb)): - -```ruby -pkg 'AlinofTimer.pkg', allow_untrusted: true -``` - -## Installer Stanza Details - -The `installer` stanza takes a series of key-value pairs, the first key of which must be `:manual` or `:script`. - -### Installer :manual - -`installer :manual` takes a single string value, describing a GUI installer which must be run by the user at a later time. The path may be absolute, or relative to the Cask. Example (from [little-snitch.rb](https://github.com/caskroom/homebrew-cask/blob/fb2ac85d9fe4bf5095a63b01d58e69ca64a6c728/Casks/little-snitch.rb)): - -```ruby -installer manual: 'Little Snitch Installer.app' -``` - -### Installer :script - -`installer :script` introduces a series of key-value pairs describing a command which will automate completion of the install. The form is similar to `uninstall :script`: - -| key | value -| ----------------|------------------------------ -| `:script` | path to an install script to be run via `sudo`. (Required first key.) -| `:args` | array of arguments to the install script -| `:input` | array of lines of input to be sent to `stdin` of the script -| `:must_succeed` | set to `false` if the script is allowed to fail -| `:sudo` | set to `false` if the script does not need `sudo` - -The path may be absolute, or relative to the Cask. Example (from [adobe-air.rb](https://github.com/caskroom/homebrew-cask/blob/240320bef456fe74621d89fd160c4a6b5a7f56cc/Casks/adobe-air.rb)): - -```ruby -installer script: 'Adobe AIR Installer.app/Contents/MacOS/Adobe AIR Installer', - args: %w[-silent], - sudo: true -``` - -## Depends_on Stanza Details - -`depends_on` is used to declare dependencies and requirements for a Cask. -`depends_on` is not consulted until `install` is attempted. - -### Depends_on :cask - -The value should be another Cask token, needed by the current Cask. - -Example use: [`SSHFS`](https://github.com/caskroom/homebrew-cask/blob/feba4ec740920b73ac8bcee206bf65c945a1dc2e/Casks/sshfs.rb) depends on OSXFUSE: - -```ruby -depends_on cask: 'osxfuse' -``` - -### Depends_on :formula - -The value should name a Homebrew Formula needed by the Cask. - -Example use: some distributions are contained in archive formats such as `7z` which are not supported by stock Apple tools. For these cases, a more capable archive reader may be pulled in at install time by declaring a dependency on the Homebrew Formula `unar`: - -```ruby -depends_on formula: 'unar' -``` - -### Depends_on :macos - -#### Requiring an Exact OS X Release - -The value for `depends_on :macos` may be a symbol, string, or an array, listing the exact compatible OS X releases. - -The available values for OS X releases are: - -| symbol | corresponding string -| -------------------|---------------------- -| `:cheetah` | `'10.0'` -| `:puma` | `'10.1'` -| `:jaguar` | `'10.2'` -| `:panther` | `'10.3'` -| `:tiger` | `'10.4'` -| `:leopard` | `'10.5'` -| `:snow_leopard` | `'10.6'` -| `:lion` | `'10.7'` -| `:mountain_lion` | `'10.8'` -| `:mavericks` | `'10.9'` -| `:yosemite` | `'10.10'` -| `:el_capitan` | `'10.11'` - -Only major releases are covered (version numbers containing a single dot). The symbol form is preferred for readability. The following are all valid ways to enumerate the exact OS X release requirements for a Cask: - -```ruby -depends_on macos: :yosemite -depends_on macos: [:mavericks, :yosemite] -depends_on macos: '10.9' -depends_on macos: ['10.9', '10.10'] -``` - -#### Setting a Minimum OS X Release - -`depends_on :macos` can also accept a string starting with a comparison operator such as `>=`, followed by an OS X release in the form above. The following are both valid expressions meaning “at least OS X 10.9”: - -```ruby -depends_on macos: '>= :mavericks' -depends_on macos: '>= 10.9' -``` - -A comparison expression cannot be combined with any other form of `depends_on :macos`. - -### Depends_on :arch - -The value for `depends_on :arch` may be a symbol or an array of symbols, listing the hardware compatibility requirements for a Cask. The requirement is satisfied at install time if any one of multiple `:arch` value matches the user’s hardware. - -The available symbols for hardware are: - -| symbol | meaning | -| ---------- | -------------- | -| `:i386` | 32-bit Intel | -| `:x86_64` | 64-bit Intel | -| `:ppc_7400`| 32-bit PowerPC | -| `:ppc_64` | 64-bit PowerPC | -| `:intel` | Any Intel | -| `:ppc` | Any PowerPC | - -The following are all valid expressions: - -```ruby -depends_on arch: :x86_64 -depends_on arch: [:x86_64] # same meaning as above -depends_on arch: :intel -depends_on arch: [:i386, :x86_64] # same meaning as above -``` - -Since PowerPC hardware is no longer common, the expression most frequently needed will be: - -```ruby -depends_on arch: :x86_64 -``` - -### All Depends_on Keys - -| key | description | -| ---------- | ----------- | -| `:formula` | a Homebrew Formula -| `:cask` | a Cask token -| `:macos` | a symbol, string, array, or comparison expression defining OS X release requirements -| `:arch` | a symbol or array defining hardware requirements -| `:x11` | a Boolean indicating a dependency on X11 -| `:java` | *stub - not yet functional* - -## conflicts_with Stanza Details - -`conflicts_with` is used to declare conflicts that keep a Cask from installing or working correctly. - -Several keys are accepted by `conflicts_with`, but none of them are yet enforced by the backend implementation. It is fine to proactively add `conflicts_with` stanzas to Casks in anticipation of future backend support; they are currently just a type of structured comment. - -| key | description | -| ---------- | ----------- | -| `:formula` | *stub - not yet functional* -| `:cask` | *stub - not yet functional* -| `:macos` | *stub - not yet functional* -| `:arch` | *stub - not yet functional* -| `:x11` | *stub - not yet functional* -| `:java` | *stub - not yet functional* - -## Uninstall Stanza Details - -IF YOU CANNOT DESIGN A WORKING `UNINSTALL` STANZA, PLEASE SUBMIT YOUR CASK ANYWAY. The maintainers will help you write an `uninstall` stanza, just ask! - -### `uninstall :pkgutil` Is The Easiest and Most Useful - -`:pkgutil` is the easiest and most useful `uninstall` directive. See [Uninstall Key :pkgutil](#uninstall-key-pkgutil). - -### `uninstall` Is Required for Casks That Install a `pkg` - -For most Casks, uninstall actions are determined automatically, and an explicit `uninstall` stanza is not needed. However, a Cask which uses the `pkg` stanza will **not** know how to uninstall correctly unless an `uninstall` stanza is given. - -So, while the Cask language does not enforce the requirement, it is much better for end-users if every `pkg` has a corresponding `uninstall`. - -The `uninstall` stanza is available for non-`pkg` Casks, and is useful for a few corner cases. However, the documentation below concerns the typical case of using `uninstall` to define procedures for a `pkg`. - -### There Are Multiple Uninstall Techniques - -Since `pkg` installers can do arbitrary things, different techniques are needed to uninstall in each case. You may need to specify one, or several, of the following key/value pairs as arguments to `uninstall`. - -### Summary of Keys - -* `:early_script` (string or hash) - like `:script`, but runs early (for special cases, best avoided) -* `:launchctl` (string or array) - ids of `launchctl` jobs to remove -* `:quit` (string or array) - bundle ids of running applications to quit -* `:signal` (array of arrays) - signal numbers and bundle ids of running applications to send a Unix signal to (used when `:quit` does not work) -* `:login_item` (string or array) - names of login items to remove -* `:kext` (string or array) - bundle ids of kexts to unload from the system -* `:pkgutil` (string, regexp or array of strings and regexps) - strings or regexps matching bundle ids of packages to uninstall using `pkgutil` -* `:script` (string or hash) - relative path to an uninstall script to be run via sudo; use hash if args are needed - - `:executable` - relative path to an uninstall script to be run via sudo (required for hash form) - - `:args` - array of arguments to the uninstall script - - `:input` - array of lines of input to be sent to `stdin` of the script - - `:must_succeed` - set to `false` if the script is allowed to fail - - `:sudo` - set to `false` if the script does not need `sudo` -* `:delete` (string or array) - single-quoted, absolute paths of files or directory trees to remove. `:delete` should only be used as a last resort. `:pkgutil` is strongly preferred. -* `:rmdir` (string or array) - single-quoted, absolute paths of directories to remove if empty -* `:trash` (string or array) - currently a synonym for `:delete`. In the future this will cause files to be moved to the Trash. - -Each `uninstall` technique is applied according to the order above. The order in which `uninstall` keys appear in the Cask file is ignored. - -For assistance filling in the right values for `uninstall` keys, there are several helper scripts found under `developer/bin` in the Homebrew-Cask repository. Each of these scripts responds to the `-help` option with additional documentation. - -The easiest way to work out an `uninstall` stanza is on a system where the `pkg` is currently installed and operational. To operate on an uninstalled `pkg` file, see [Working With a pkg File Manually](#working-with-a-pkg-file-manually), below. - -### Uninstall Key :pkgutil - -This is the most useful uninstall key. `:pkgutil` is often sufficient to completely uninstall a `pkg`, and is strongly preferred over `:delete`. - -IDs for the most recently-installed packages can be listed using the command: - -```bash -$ ./developer/bin/list_recent_pkg_ids -``` - -`:pkgutil` also accepts a regular expression match against multiple package IDs. The regular expressions are somewhat nonstandard. To test a `:pkgutil` regular expression against currently-installed packages, use the command: - -```bash -$ ./developer/bin/list_pkg_ids_by_regexp -``` - -### List Files Associated With a `pkg` Id - -Once you know the ID for an installed package, (above), you can list all files on your system associated with that package ID using the OS X command: - -```bash -$ pkgutil --files -``` - -Listing the associated files can help you assess whether the package included any `launchctl` jobs or kernel extensions (kexts). - -### Uninstall Key :launchctl - -IDs for currently loaded `launchctl` jobs can be listed using the command: - -```bash -$ ./developer/bin/list_loaded_launchjob_ids -``` - -IDs for all installed `launchctl` jobs can be listed using the command: - -```bash -$ ./developer/bin/list_installed_launchjob_ids -``` - -### Uninstall Key :quit - -Bundle IDs for currently running Applications can be listed using the command: - -```bash -$ ./developer/bin/list_running_app_ids -``` - -Bundle IDs inside an Application bundle on disk can be listed using the command: - -```bash -$ ./developer/bin/list_ids_in_app -``` - -### Uninstall Key :signal - -`:signal` should only be needed in the rare case that a process does not respond to `:quit`. - -Bundle IDs for `:signal` targets may be obtained as for `:quit`. The value for `:signal` is an array-of-arrays, with each cell containing two elements: the desired Unix signal followed by the corresponding bundle ID. - -The Unix signal may be given in numeric or string form (see the `kill` man page for more details). - -The elements of the `:signal` array are applied in order, only if there is an existing process associated the bundle ID, and stopping when that process terminates. A bundle ID may be repeated to send more than one signal to the same process. - -It is better to use the least-severe signals which are sufficient to stop a process. The `KILL` signal in particular can have unwanted side-effects. - -An example, with commonly-used signals in ascending order of severity: - -```ruby - 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'], - ] -``` - -Note that when multiple running processes match the given Bundle ID, all matching processes will be signaled. - -Unlike `:quit` directives, Unix signals originate from the current user, not from the superuser. This is construed as a safety feature, since the superuser is capable of bringing down the system via signals. However, this inconsistency may also be considered a bug, and should be addressed in some fashion in a future version. - -### Uninstall key :login_item - -Login items associated with an Application bundle on disk can be listed using the command: - -```bash -$ ./developer/bin/list_login_items_for_app -``` - -Note that you will likely need to have opened the app at least once for any login items to be present. - -### Uninstall Key :kext - -IDs for currently loaded kernel extensions can be listed using the command: - -```bash -$ ./developer/bin/list_loaded_kext_ids -``` - -IDs inside a kext bundle you have located on disk can be listed using the command: - -```bash -$ ./developer/bin/list_id_in_kext -``` - -### Uninstall Key :delete - -`:delete` should only be used as a last resort, if other `uninstall` methods are insufficient. - -Arguments to `uninstall :delete` should be static, single-quoted, absolute paths. - -* Only single quotes should be used. -* Double-quotes should not be used. `ENV['HOME']` and other variables - should not be interpolated in the value. -* Basic tilde expansion is performed on paths, i.e., leading `~` is expanded to the home directory. -* Only absolute paths should be given. -* No glob expansion is performed (*eg* `*` characters are literal), though glob expansion is a desired future feature. - -To remove user-specific files, use the `zap` stanza. - -### Uninstall Key :trash - -*stub* - currently a synonym for `:delete`. In the future this will cause files to be moved to the Trash. It is best not to use this stub until it gains the proper functionality. - -### Working With a pkg File Manually - -Advanced users may wish to work with a `pkg` file manually, without having the package installed. - -A list of files which may be installed from a `pkg` can be extracted using the command: - -```bash -$ ./developer/bin/list_payload_in_pkg -``` - -Candidate application names helpful for determining the name of a Cask may be extracted from a `pkg` file using the command: - -```bash -$ ./developer/bin/list_apps_in_pkg -``` - -Candidate package IDs which may be useful in a `:pkgutil` key may be extracted from a `pkg` file using the command: - -```bash -$ ./developer/bin/list_ids_in_pkg -``` - -A fully manual method for finding bundle ids in a package file follows: - -1. Unpack `/path/to/my.pkg` (replace with your package name) with `pkgutil --expand /path/to/my.pkg /tmp/expanded.unpkg`. -2. The unpacked package is a folder. Bundle ids are contained within files named `PackageInfo`. These files can be found with the command `find /tmp/expanded.unpkg -name PackageInfo`. -3. `PackageInfo` files are XML files, and bundle ids are found within the `identifier` attributes of `` tags that look like ``, where extraneous attributes have been snipped out and replaced with ellipses. -4. Kexts inside packages are also described in `PackageInfo` files. If any kernel extensions are present, the command `find /tmp/expanded.unpkg -name PackageInfo -print0 | xargs -0 grep -i kext` should return a `` tag with a `path` attribute that contains a `.kext` extension, for example ``. -5. Once bundle ids have been identified, the unpacked package directory can be deleted. - -## \*flight Stanzas Details - -### Evaluation of Blocks is Always Deferred - -The Ruby blocks defined by `preflight`, `postflight`, `uninstall_preflight`, and `uninstall_postflight` are not evaluated until install time or uninstall time. Within a block, you may refer to the `@cask` instance variable, and invoke any method available on `@cask`. - -### \*flight Mini-DSL - -There is a mini-DSL available within these blocks. - -The following methods may be called to perform standard tasks: - -| method | availability | description | -| ----------------------------------------- | ------------------------------------------------ | ----------- | -| `plist_set(key, value)` | `preflight`, `postflight`, `uninstall_preflight` | set a value in the `Info.plist` file for the app bundle. Example: [`rubymine.rb`](https://github.com/caskroom/homebrew-cask/blob/c5dbc58b7c1b6290b611677882b205d702b29190/Casks/rubymine.rb#L12) -| `set_ownership(paths)` | `preflight`, `postflight`, `uninstall_preflight` | set user and group ownership of `paths`. Example: [`unifi-controller.rb`](https://github.com/caskroom/homebrew-cask/blob/8a452a41707af6a661049da6254571090fac5418/Casks/unifi-controller.rb#L13) -| `set_permissions(paths, permissions_str)` | `preflight`, `postflight`, `uninstall_preflight` | set permissions in `paths` to `permissions_str`. Example: [`docker-machine.rb`](https://github.com/caskroom/homebrew-cask/blob/8a452a41707af6a661049da6254571090fac5418/Casks/docker-machine.rb#L16) -| `suppress_move_to_applications` | `postflight` | suppress a dialog asking the user to move the app to the `/Applications` folder. Example: [`github.rb`](https://github.com/caskroom/homebrew-cask/blob/c5dbc58b7c1b6290b611677882b205d702b29190/Casks/github.rb#L13) - -`plist_set` currently has the limitation that it only operates on the bundle indicated by the first `app` stanza (and the Cask must contain an `app` stanza). - -`set_ownership(paths)` defaults user ownership to the current user and group ownership to `staff`. These can be changed by passing in extra options: `set_ownership(paths, user: 'user', group: 'group')`. - -`suppress_move_to_applications` optionally accepts a `:key` parameter for apps which use a nonstandard `defaults` key. Example: [`alfred.rb`](https://github.com/caskroom/homebrew-cask/blob/c5dbc58b7c1b6290b611677882b205d702b29190/Casks/alfred.rb#L13). - -## Zap Stanza Details - -### Zap Stanza Purpose - -The `zap` stanza describes a more complete uninstallation of files associated with a Cask. The `zap` procedures will never be performed by default, but only if the user invokes the `zap` verb: - -```bash -$ brew cask zap td-toolbelt # also removes org.ruby-lang.installer -``` - -`zap` stanzas may remove: - -* Preference files and caches stored within the user’s `~/Library` directory. -* Shared resources such as application updaters. Since shared resources may be removed, other applications may be affected by `brew cask zap`. Understanding that is the responsibility of the end user. - -`zap` stanzas should not remove: - -* Files created by the user directly. - -### Zap Stanza Syntax - -The form of `zap` stanza follows the [`uninstall` stanza](#uninstall-stanza-details). All of the same directives are available. Unlike with `uninstall`, however, `:delete` is not discouraged in `zap`. - -Example: [injection.rb](https://github.com/caskroom/homebrew-cask/blob/3a56867b39be1095f1247e4bad3f77eb4eb52ede/Casks/injection.rb#L16) - -## Arbitrary Ruby Methods - -In the exceptional case that the Cask DSL is insufficient, it is possible to define arbitrary Ruby variables and methods inside the Cask by creating a `Utils` namespace. Example: - -```ruby -cask 'myapp' do - module Utils - def self.arbitrary_method - ... - end - end - - name 'MyApp' - version '1.0' - sha256 'a32565cdb1673f4071593d4cc9e1c26bc884218b62fef8abc450daa47ba8fa92' - license :unknown - - url "https://#{Utils.arbitrary_method}" - homepage 'http://www.example.com/' - ... -end -``` - -This should be used sparingly: any method which is needed by two or more Casks should instead be rolled into the core. Care must also be taken that such methods be very efficient. - -Variables and methods should not be defined outside the `Utils` namespace, as they may collide with Homebrew-Cask internals. - -# <3 THANK YOU TO ALL CONTRIBUTORS! <3 diff --git a/doc/cask_language_reference/all_stanzas.md b/doc/cask_language_reference/all_stanzas.md new file mode 100644 index 0000000000..6448609360 --- /dev/null +++ b/doc/cask_language_reference/all_stanzas.md @@ -0,0 +1,58 @@ +# All stanzas + +## Required Stanzas + +Each of the following stanzas is required for every Cask. + +| name | multiple occurrences allowed? | value | +| ------------------ |------------------------------ | ----------- | +| `version` | no | application version; give value of `:latest` if versioned downloads are not offered +| `sha256` | no | SHA-256 checksum of the file downloaded from `url`, calculated by the command `shasum -a 256 `. Can be suppressed by using the special value `:no_check` (see also [Checksum Stanza Details](#checksum-stanza-details)) +| `url` | no | URL to the `.dmg`/`.zip`/`.tgz`/`.tbz2` file that contains the application. A [comment](#when-url-and-homepage-hostnames-differ-add-a-comment) should be added if the hostnames in the `url` and `homepage` stanzas differ (see also [URL Stanza Details](#url-stanza-details)) +| `name` | yes | a string providing the full and proper name defined by the vendor (see also [Name Stanza Details](#name-stanza-details)) +| `homepage` | no | application homepage; used for the `brew cask home` command +| `license` | no | a symbol identifying the license category for the application (see also [License Stanza Details](#license-stanza-details)) + +## At Least One Artifact Stanza Is Also Required + +Each Cask must declare one or more *artifacts* (i.e. something to install) + +| name | multiple occurrences allowed? | value | +| ------------------ |------------------------------ | ----------- | +| `app` | yes | relative path to an `.app` that should be linked into the `~/Applications` folder on installation (see also [App Stanza Details](#app-stanza-details)) +| `pkg` | yes | relative path to a `.pkg` file containing the distribution (see also [Pkg Stanza Details](#pkg-stanza-details)) +| `binary` | yes | relative path to a Binary that should be linked into the `/usr/local/bin` folder on installation +| `colorpicker` | yes | relative path to a ColorPicker plugin that should be linked into the `~/Library/ColorPickers` folder on installation +| `font` | yes | relative path to a Font that should be linked into the `~/Library/Fonts` folder on installation +| `input_method` | yes | relative path to a Input Method that should be linked into the `~/Library/Input Methods` folder on installation +| `internet_plugin` | yes | relative path to a Service that should be linked into the `~/Library/Internet Plug-Ins` folder on installation +| `prefpane` | yes | relative path to a Preference Pane that should be linked into the `~/Library/PreferencePanes` folder on installation +| `qlplugin` | yes | relative path to a QuickLook Plugin that should be linked into the `~/Library/QuickLook` folder on installation +| `screen_saver` | yes | relative path to a Screen Saver that should be linked into the `~/Library/Screen Savers` folder on installation +| `service` | yes | relative path to a Service that should be linked into the `~/Library/Services` folder on installation +| `audio_unit_plugin`| yes | relative path to an Audio Unit plugin that should be linked into the `~/Library/Audio/Components` folder on installation +| `vst_plugin` | yes | relative path to a VST Plugin that should be linked into the `~/Library/Audio/VST` folder on installation +| `suite` | yes | relative path to a containing directory that should be linked into the `~/Applications` folder on installation (see also [Suite Stanza Details](#suite-stanza-details)) +| `artifact` | yes | relative path to an arbitrary path that should be symlinked on installation. This is only for unusual cases. The `app` stanza is strongly preferred when linking `.app` bundles. +| `installer` | yes | describes an executable which must be run to complete the installation (see [Installer Stanza Details](#installer-stanza-details)) +| `stage_only` | no | `true`. Assert that the Cask contains no activatable artifacts. + +## Optional Stanzas + +| name | multiple occurrences allowed? | value | +| ---------------------- |------------------------------ | ----------- | +| `uninstall` | yes | procedures to uninstall a Cask. Optional unless the `pkg` stanza is used. (see also [Uninstall Stanza Details](#uninstall-stanza-details)) +| `zap` | yes | additional procedures for a more complete uninstall, including user files and shared resources (see also [Zap Stanza Details](#zap-stanza-details)) +| `appcast` | no | a URL providing an appcast feed to find updates for this Cask (see also [Appcast Stanza Details](#appcast-stanza-details)) +| `depends_on` | yes | a list of dependencies and requirements for this Cask (see also [Depends_on Stanza Details](#depends_on-stanza-details)) +| `conflicts_with` | yes | a list of conflicts with this Cask (*not yet functional* see also [Conflicts_with Stanza Details](#conflicts_with-stanza-details)) +| `caveats` | yes | a string or Ruby block providing the user with Cask-specific information at install time (see also [Caveats Stanza Details](#caveats-stanza-details)) +| `preflight` | yes | a Ruby block containing preflight install operations (needed only in very rare cases) +| `postflight` | yes | a Ruby block containing postflight install operations (see also [Postflight Stanza Details](#flight-stanzas-details)) +| `uninstall_preflight` | yes | a Ruby block containing preflight uninstall operations (needed only in very rare cases) +| `uninstall_postflight` | yes | a Ruby block containing postflight uninstall operations +| `accessibility_access` | no | `true` if the application should be granted accessibility access +| `container :nested =>` | no | relative path to an inner container that must be extracted before moving on with the installation; this allows us to support dmg inside tar, zip inside dmg, etc. +| `container :type =>` | no | a symbol to override container-type autodetect. May be one of: `:air`, `:bz2`, `:cab`, `:dmg`, `:generic_unar`, `:gzip`, `:otf`, `:pkg`, `:rar`, `:seven_zip`, `:sit`, `:tar`, `:ttf`, `:xar`, `:zip`, `:naked`. (example [parse.rb](https://github.com/caskroom/homebrew-cask/blob/ffdc9a1aa459d80a084ee0d24176409388efe71f/Casks/parse.rb#L12)) +| `gpg` | no | *stub: not yet functional.* (see also [GPG Stanza Details](#gpg-stanza-details)) +| `auto_updates` | no | `true`. Assert the Cask artifacts auto-update. (Use if `Check for Updates…` or similar is present in app menu) \ No newline at end of file diff --git a/doc/cask_language_reference/readme.md b/doc/cask_language_reference/readme.md new file mode 100644 index 0000000000..bc542a3018 --- /dev/null +++ b/doc/cask_language_reference/readme.md @@ -0,0 +1,116 @@ +# Synopsis + +## Casks Are Ruby Blocks + +Each Cask is a Ruby block, beginning with a special header line. The Cask definition itself is always enclosed in a `do … end` block. Example: + +```ruby +cask 'alfred' do + version '2.7.1_387' + sha256 'a3738d0513d736918a6d71535ef3d85dd184af267c05698e49ac4c6b48f38e17' + + url "https://cachefly.alfredapp.com/Alfred_#{version}.zip" + name 'Alfred' + homepage 'https://www.alfredapp.com/' + license :freemium + + app 'Alfred 2.app' + app 'Alfred 2.app/Contents/Preferences/Alfred Preferences.app' + + postflight do + suppress_move_to_applications :key => 'suppressMoveToApplications' + end +end +``` + +## The Cask Language Is Declarative + +Each Cask contains a series of stanzas (or “fields”) which *declare* how the software is to be obtained and installed. In a declarative language, the author does not need to worry about **order**. As long as all the needed fields are present, Homebrew-Cask will figure out what needs to be done at install time. + +To make maintenance easier, the most-frequently-updated stanzas are usually placed at the top. But that’s a convention, not a rule. + +Exception: `do` blocks such as `postflight` may enclose a block of pure Ruby code. Lines within that block follow a procedural (order-dependent) paradigm. + +## Conditional Statements + +### Efficiency + +Conditional statements are permitted, but only if they are very efficient. +Tests on the following values are known to be acceptable: + +| value | examples +| ----------------------------|-------------------------------------- +| `MacOS.release` | [macports.rb](https://github.com/caskroom/homebrew-cask/blob/9eae0af0daf9b55f81a3af010cca3b0b1272e2db/Casks/macports.rb#L4#L20), [coconutbattery.rb](https://github.com/caskroom/homebrew-cask/blob/2c801af44be29fff7f3cb2996455fce5dd95d1cc/Casks/coconutbattery.rb#L3#L17) +| `Hardware::CPU.is_32_bit?` | [vuescan.rb](https://github.com/caskroom/homebrew-cask/blob/655bfe48b41ae94cb81b1003182b8de5fa2995ef/Casks/vuescan.rb#L5#L9) +| `Hardware::CPU.is_64_bit?` | none, see [Always Fall Through to the Newest Case](#always-fall-through-to-the-newest-case) + +### Version Comparisons + +Tests against `MacOS.release` may use either symbolic names or version +strings with numeric comparison operators: + +```ruby +if MacOS.release <= :mavericks # symbolic name +``` + +```ruby +if MacOS.release <= '10.9' # version string +``` + +The available symbols for OS X versions are: `:cheetah`, `:puma`, `:jaguar`, `:panther`, `:tiger`, `:leopard`, `:snow_leopard`, `:lion`, `:mountain_lion`, `:mavericks`, `:yosemite`, and `:el_capitan`. The corresponding numeric version strings should given as major releases containing a single dot. + +### Always Fall Through to the Newest Case + +Conditionals should be constructed so that the default is the newest OS version or hardware type. When using an `if` statement, test for older versions, and then let the `else` statement hold the latest and greatest. This makes it more likely that the Cask will work without alteration when a new OS is released. Example (from [coconutbattery.rb](https://github.com/caskroom/homebrew-cask/blob/2c801af44be29fff7f3cb2996455fce5dd95d1cc/Casks/coconutbattery.rb)): + +```ruby +if MacOS.release <= :tiger + # ... +elsif MacOS.release <= :snow_leopard + # ... +else + # ... +end +``` + +## Arbitrary Ruby Methods + +In the exceptional case that the Cask DSL is insufficient, it is possible to define arbitrary Ruby variables and methods inside the Cask by creating a `Utils` namespace. Example: + +```ruby +cask 'myapp' do + module Utils + def self.arbitrary_method + ... + end + end + + name 'MyApp' + version '1.0' + sha256 'a32565cdb1673f4071593d4cc9e1c26bc884218b62fef8abc450daa47ba8fa92' + license :unknown + + url "https://#{Utils.arbitrary_method}" + homepage 'http://www.example.com/' + ... +end +``` + +This should be used sparingly: any method which is needed by two or more Casks should instead be rolled into the core. Care must also be taken that such methods be very efficient. + +Variables and methods should not be defined outside the `Utils` namespace, as they may collide with Homebrew-Cask internals. + +## Header Line Details + +The first non-comment line in a Cask follows the form: + +```ruby +cask '' do +``` + +`` should match the Cask filename, without the `.rb` extension, +enclosed in single quotes. + +The header line is not entirely strict Ruby: no comma is required after the Cask token. + +There are currently some arbitrary limitations on Cask tokens which are in the process of being removed. The Travis bot will catch any errors during the transition. \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/app.md b/doc/cask_language_reference/stanzas/app.md new file mode 100644 index 0000000000..fae216600f --- /dev/null +++ b/doc/cask_language_reference/stanzas/app.md @@ -0,0 +1,43 @@ +# app + +In the simple case of a string argument to `app`, a symlink is created in the target `~/Applications` directory using the same basename as the source file. For example: + +```ruby +app 'Alfred 2.app' +``` + +causes the creation of this symlink: + +```bash +~/Applications/Alfred 2.app +``` + +which points to a source file such as: + +```bash +/opt/homebrew-cask/Caskroom/alfred/2.8.2_431/Alfred 2.app +``` + +## Renaming the Target + +You can rename the target link which appears in your `~/Applications` directory by adding a `:target` key to `app`. Example (from [scala-ide.rb](https://github.com/caskroom/homebrew-cask/blob/84e8df88836a2c11657e09264bd01b96783bb0d1/Casks/scala-ide.rb#L21)): + +```ruby +app 'eclipse/Eclipse.app', :target => 'Scala IDE.app' +``` + +## :target May Contain an Absolute Path + +If `:target` has a leading slash, it is interpreted as an absolute path. The containing directory for the absolute path will be created if it does not already exist. Example (from [manopen.rb](https://github.com/caskroom/homebrew-cask/blob/84e8df88836a2c11657e09264bd01b96783bb0d1/Casks/manopen.rb#L12)): + +```ruby +artifact 'openman.1', :target => '/usr/local/share/man/man1/openman.1' +``` + +## :target Works on Most Artifact Types + +The `:target` key works similarly for most Cask artifacts, such as `app`, `binary`, `colorpicker`, `font`, `input_method`, `prefpane`, `qlplugin`, `service`, `suite`, and `artifact`. + +## :target Should Only Be Used in Select Cases + +Don’t use `:target` for aesthetic reasons, like removing version numbers (`app "Slack #{version}.app", :target => 'Slack.app'`). With `app`, use it when it makes sense functionally and document your reason cleary in the Cask: was it [for clarity](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/imagemin.rb#L11); [for consistency](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/devonthink-pro-office.rb#L14); [to prevent conflicts](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/flash-player-debugger.rb#L13)? With `binary` you can take some extra liberties to be consistent with other command-line tools, like [changing case](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/diffmerge.rb#L11) or [removing an extension](https://github.com/caskroom/homebrew-cask/blob/6e4eb6ba58ca0d9e6d42a1d78856cc8a35cf5fce/Casks/filebot.rb#L12). \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/appcast.md b/doc/cask_language_reference/stanzas/appcast.md new file mode 100644 index 0000000000..f445512734 --- /dev/null +++ b/doc/cask_language_reference/stanzas/appcast.md @@ -0,0 +1,19 @@ +# appcast + +The value of the `appcast` stanza is a string, holding the URL for an appcast which provides information on future updates. + +## Required Appcast Parameters + +| key | value | +| ------------- | ----------- | +| `:checkpoint` | a string holding a custom checksum of the most recent appcast which matches the current Cask versioning. Use `curl --compressed "{{appcast_url}}" | sed 's|[^<]*||g' | shasum --algorithm 256` to calculate it. + +Example: [`atom`](https://github.com/caskroom/homebrew-cask/blob/8f2da08f007d099e603d1d6c64c72b815f7af0b0/Casks/atom.rb#L7#L8) + +There are a few different ways the `appcast` can be determined: + + * If the app is distributed via GitHub releases, the `appcast` will be of the form `https://github.com/{{user}}/{{project}}/releases.atom`. (Example Cask: [`electron`](https://github.com/caskroom/homebrew-cask/blob/b543c9215c0af31a7e2f526429eb3011a5beb597/Casks/electron.rb#L6#L7)) + + * The popular update framework [Sparkle](http://sparkle-project.org) generally uses the `SUFeedURL` property in `Contents/Info.plist` inside `.app` bundles. You can use the script [`find_sparkle_appcast`](https://github.com/caskroom/homebrew-cask/blob/master/developer/bin/find_sparkle_appcast) to add this automatically. (Example Cask: [`glyphs`](https://github.com/caskroom/homebrew-cask/blob/b543c9215c0af31a7e2f526429eb3011a5beb597/Casks/glyphs.rb#L6#L7)) + +* An appcast can be any URL hosted by the app’s developer that changes every time a new release is out (e.g. a changelog HTML page). (Example Cask: [`shortcat`](https://github.com/caskroom/homebrew-cask/blob/b6e5b1ed2fc45f176258b4ca590a488b780555bc/Casks/shortcat.rb#L6#L7)) \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/caveats.md b/doc/cask_language_reference/stanzas/caveats.md new file mode 100644 index 0000000000..10c49f572f --- /dev/null +++ b/doc/cask_language_reference/stanzas/caveats.md @@ -0,0 +1,48 @@ +# caveats + +## caveats as a String + +When `caveats` is a string, it is evaluated at compile time. The following methods are available for interpolation if `caveats` is placed in its customary position at the end of the Cask: + +| method | description | +| ------------------ | ----------- | +| `token` | the Cask token +| `version` | the Cask version +| `homepage` | the Cask homepage +| `caskroom_path` | the containing directory for all staged Casks, typically `/opt/homebrew-cask/Caskroom` (only available with block form) +| `staged_path` | the staged location for this Cask, including version number, *eg* `/opt/homebrew-cask/Caskroom/adium/1.5.10` (only available with block form) + +Example: + +```ruby +caveats "Using #{token} is hazardous to your health." +``` + +## caveats as a Block + +When `caveats` is a Ruby block, evaluation is deferred until install time. Within a block you may refer to the `@cask` instance variable, and invoke any method available on `@cask`. + +## caveats Mini-DSL + +There is a mini-DSL available within `caveats` blocks. + +The following methods may be called to generate standard warning messages: + +| method | description | +| --------------------------------- | ----------- | +| `path_environment_variable(path)` | users should make sure `path` is in their `$PATH` environment variable +| `zsh_path_helper(path)` | zsh users must take additional steps to make sure `path` is in their `$PATH` environment variable +| `depends_on_java(version)` | users should make sure they have the specified version of java installed. `version` can be exact (e.g. `6`), a minimum (e.g. `7+`), or omitted (when any version works). +| `logout` | users should log out and log back in to complete installation +| `reboot` | users should reboot to complete installation +| `files_in_usr_local` | the Cask installs files to `/usr/local`, which may confuse Homebrew +| `discontinued` | all software development has been officially discontinued upstream +| `free_license(web_page)` | users may get an official license to use the software at `web_page` + +Example: + +```ruby +caveats do + path_environment_variable '/usr/texbin' +end +``` \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/conflicts_with.md b/doc/cask_language_reference/stanzas/conflicts_with.md new file mode 100644 index 0000000000..e924d76177 --- /dev/null +++ b/doc/cask_language_reference/stanzas/conflicts_with.md @@ -0,0 +1,14 @@ +# conflicts_with + +`conflicts_with` is used to declare conflicts that keep a Cask from installing or working correctly. + +Several keys are accepted by `conflicts_with`, but none of them are yet enforced by the backend implementation. It is fine to proactively add `conflicts_with` stanzas to Casks in anticipation of future backend support; they are currently just a type of structured comment. + +| key | description | +| ---------- | ----------- | +| `:formula` | *stub - not yet functional* +| `:cask` | *stub - not yet functional* +| `:macos` | *stub - not yet functional* +| `:arch` | *stub - not yet functional* +| `:x11` | *stub - not yet functional* +| `:java` | *stub - not yet functional* \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/depends_on.md b/doc/cask_language_reference/stanzas/depends_on.md new file mode 100644 index 0000000000..c9d36bd5aa --- /dev/null +++ b/doc/cask_language_reference/stanzas/depends_on.md @@ -0,0 +1,108 @@ +# depends_on + +`depends_on` is used to declare dependencies and requirements for a Cask. +`depends_on` is not consulted until `install` is attempted. + +## depends_on :cask + +The value should be another Cask token, needed by the current Cask. + +Example use: [`SSHFS`](https://github.com/caskroom/homebrew-cask/blob/feba4ec740920b73ac8bcee206bf65c945a1dc2e/Casks/sshfs.rb) depends on OSXFUSE: + +```ruby +depends_on :cask => 'osxfuse' +``` + +## depends_on :formula + +The value should name a Homebrew Formula needed by the Cask. + +Example use: some distributions are contained in archive formats such as `7z` which are not supported by stock Apple tools. For these cases, a more capable archive reader may be pulled in at install time by declaring a dependency on the Homebrew Formula `unar`: + +```ruby +depends_on :formula => 'unar' +``` + +## depends_on :macos + +### Requiring an Exact OS X Release + +The value for `depends_on :macos` may be a symbol, string, or an array, listing the exact compatible OS X releases. + +The available values for OS X releases are: + +| symbol | corresponding string +| -------------------|---------------------- +| `:cheetah` | `'10.0'` +| `:puma` | `'10.1'` +| `:jaguar` | `'10.2'` +| `:panther` | `'10.3'` +| `:tiger` | `'10.4'` +| `:leopard` | `'10.5'` +| `:snow_leopard` | `'10.6'` +| `:lion` | `'10.7'` +| `:mountain_lion` | `'10.8'` +| `:mavericks` | `'10.9'` +| `:yosemite` | `'10.10'` +| `:el_capitan` | `'10.11'` + +Only major releases are covered (version numbers containing a single dot). The symbol form is preferred for readability. The following are all valid ways to enumerate the exact OS X release requirements for a Cask: + +```ruby +depends_on :macos => :yosemite +depends_on :macos => [:mavericks, :yosemite] +depends_on :macos => '10.9' +depends_on :macos => ['10.9', '10.10'] +``` + +### Setting a Minimum OS X Release + +`depends_on :macos` can also accept a string starting with a comparison operator such as `>=`, followed by an OS X release in the form above. The following are both valid expressions meaning “at least OS X 10.9”: + +```ruby +depends_on :macos => '>= :mavericks' +depends_on :macos => '>= 10.9' +``` + +A comparison expression cannot be combined with any other form of `depends_on :macos`. + +## depends_on :arch + +The value for `depends_on :arch` may be a symbol or an array of symbols, listing the hardware compatibility requirements for a Cask. The requirement is satisfied at install time if any one of multiple `:arch` value matches the user’s hardware. + +The available symbols for hardware are: + +| symbol | meaning | +| ---------- | -------------- | +| `:i386` | 32-bit Intel | +| `:x86_64` | 64-bit Intel | +| `:ppc_7400`| 32-bit PowerPC | +| `:ppc_64` | 64-bit PowerPC | +| `:intel` | Any Intel | +| `:ppc` | Any PowerPC | + +The following are all valid expressions: + +```ruby +depends_on :arch => :x86_64 +depends_on :arch => [:x86_64] # same meaning as above +depends_on :arch => :intel +depends_on :arch => [:i386, :x86_64] # same meaning as above +``` + +Since PowerPC hardware is no longer common, the expression most frequently needed will be: + +```ruby +depends_on :arch => :x86_64 +``` + +## All depends_on Keys + +| key | description | +| ---------- | ----------- | +| `:formula` | a Homebrew Formula +| `:cask` | a Cask token +| `:macos` | a symbol, string, array, or comparison expression defining OS X release requirements +| `:arch` | a symbol or array defining hardware requirements +| `:x11` | a Boolean indicating a dependency on X11 +| `:java` | *stub - not yet functional* \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/flight.md b/doc/cask_language_reference/stanzas/flight.md new file mode 100644 index 0000000000..ad956dd208 --- /dev/null +++ b/doc/cask_language_reference/stanzas/flight.md @@ -0,0 +1,24 @@ +# \*flight + +## Evaluation of Blocks is Always Deferred + +The Ruby blocks defined by `preflight`, `postflight`, `uninstall_preflight`, and `uninstall_postflight` are not evaluated until install time or uninstall time. Within a block, you may refer to the `@cask` instance variable, and invoke any method available on `@cask`. + +## \*flight Mini-DSL + +There is a mini-DSL available within these blocks. + +The following methods may be called to perform standard tasks: + +| method | availability | description | +| ----------------------------------------- | ------------------------------------------------ | ----------- | +| `plist_set(key, value)` | `preflight`, `postflight`, `uninstall_preflight` | set a value in the `Info.plist` file for the app bundle. Example: [`rubymine.rb`](https://github.com/caskroom/homebrew-cask/blob/c5dbc58b7c1b6290b611677882b205d702b29190/Casks/rubymine.rb#L12) +| `set_ownership(paths)` | `preflight`, `postflight`, `uninstall_preflight` | set user and group ownership of `paths`. Example: [`unifi-controller.rb`](https://github.com/caskroom/homebrew-cask/blob/8a452a41707af6a661049da6254571090fac5418/Casks/unifi-controller.rb#L13) +| `set_permissions(paths, permissions_str)` | `preflight`, `postflight`, `uninstall_preflight` | set permissions in `paths` to `permissions_str`. Example: [`docker-machine.rb`](https://github.com/caskroom/homebrew-cask/blob/8a452a41707af6a661049da6254571090fac5418/Casks/docker-machine.rb#L16) +| `suppress_move_to_applications` | `postflight` | suppress a dialog asking the user to move the app to the `/Applications` folder. Example: [`github.rb`](https://github.com/caskroom/homebrew-cask/blob/c5dbc58b7c1b6290b611677882b205d702b29190/Casks/github.rb#L13) + +`plist_set` currently has the limitation that it only operates on the bundle indicated by the first `app` stanza (and the Cask must contain an `app` stanza). + +`set_ownership(paths)` defaults user ownership to the current user and group ownership to `staff`. These can be changed by passing in extra options: `set_ownership(paths, user: 'user', group: 'group')`. + +`suppress_move_to_applications` optionally accepts a `:key` parameter for apps which use a nonstandard `defaults` key. Example: [`alfred.rb`](https://github.com/caskroom/homebrew-cask/blob/c5dbc58b7c1b6290b611677882b205d702b29190/Casks/alfred.rb#L13). \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/gpg.md b/doc/cask_language_reference/stanzas/gpg.md new file mode 100644 index 0000000000..cb07a0faa4 --- /dev/null +++ b/doc/cask_language_reference/stanzas/gpg.md @@ -0,0 +1,11 @@ +# gpg Stanza Details + +**This is a stub for upcoming functionality, and is not fully documented**. + +The `gpg` stanza contains signature information for GPG-signed distributions. The form is: + +```ruby +gpg , => +``` + +where `` is one of `:key_id` or `:key_url`, and `` points to the detached signature of the distribution. Commonly, the signature follows the `url` value. Example: [libreoffice.rb](https://github.com/caskroom/homebrew-cask/blob/ae2b41394f19c864c3ff9dee0818620715fcc07e/Casks/libreoffice.rb#L13#L14). \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/installer.md b/doc/cask_language_reference/stanzas/installer.md new file mode 100644 index 0000000000..8dcff3aecd --- /dev/null +++ b/doc/cask_language_reference/stanzas/installer.md @@ -0,0 +1,31 @@ +# installer + +The `installer` stanza takes a series of key-value pairs, the first key of which must be `:manual` or `:script`. + +### installer :manual + +`installer :manual` takes a single string value, describing a GUI installer which must be run by the user at a later time. The path may be absolute, or relative to the Cask. Example (from [little-snitch.rb](https://github.com/caskroom/homebrew-cask/blob/fb2ac85d9fe4bf5095a63b01d58e69ca64a6c728/Casks/little-snitch.rb)): + +```ruby +installer :manual => 'Little Snitch Installer.app' +``` + +## installer :script + +`installer :script` introduces a series of key-value pairs describing a command which will automate completion of the install. The form is similar to `uninstall :script`: + +| key | value +| ----------------|------------------------------ +| `:script` | path to an install script to be run via `sudo`. (Required first key.) +| `:args` | array of arguments to the install script +| `:input` | array of lines of input to be sent to `stdin` of the script +| `:must_succeed` | set to `false` if the script is allowed to fail +| `:sudo` | set to `false` if the script does not need `sudo` + +The path may be absolute, or relative to the Cask. Example (from [adobe-air.rb](https://github.com/caskroom/homebrew-cask/blob/240320bef456fe74621d89fd160c4a6b5a7f56cc/Casks/adobe-air.rb)): + +```ruby +installer :script => 'Adobe AIR Installer.app/Contents/MacOS/Adobe AIR Installer', + :args => %w[-silent], + :sudo => true +``` \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/license.md b/doc/cask_language_reference/stanzas/license.md new file mode 100644 index 0000000000..ee6cd2aecd --- /dev/null +++ b/doc/cask_language_reference/stanzas/license.md @@ -0,0 +1,47 @@ +# license + +The `license` stanza is not free-form. A single value must be chosen from a list of valid symbols. + +The values for `license` are categories, rather than fully-specified licenses. For example, `:gpl` is a category; we do not distinguish between versions of the GPL. Similarly, `:cc` and `:bsd` comprise many variants. They must always pertain to the license of the software itself, not the vendor’s business model (a free app to access a paid service is still `:gratis`, not `:freemium`). + +The `license` stanza is intended as an aid to search/filtering of Casks. For full and complete information, the user must always rely on the vendor’s homepage. + +Note that `brew cask search` and `brew cask list` are not yet capable of using the information stored in the `license` stanza. + +## Generic Category Licenses + +Cask authors should use the most specific license category which is also correct. Generic categories are provided for difficult cases. `:unknown` is also perfectly fine if you are unsure. + +Example: [Chromium](http://www.chromium.org/chromium-os/licenses) includes code with multiple licenses, all of which are open source. Chromium licensing is described by the generic category [`:oss`](https://github.com/caskroom/homebrew-cask/blob/54a79f7dcceea9a922a5b608ac99466b9d10a191/Casks/chromium.rb#L7). + +| symbol | meaning | +| ----------- | ----------- | +| `:oss` | open-source software +| `:closed` | closed-source software +| `:unknown` | license unknown +| `:other` | license is known, but fits no category + +## Valid Licenses + +| symbol | generic category | meaning | URL | +| ---------------- | ---------------- | ------------------------------------------------------------------ | ----------- | +| `:gratis` | `:closed` | free-to-use, closed source | +| `:commercial` | `:closed` | not free to use | +| `:freemium` | `:closed` | free-to-use, payment required for full or additional functionality | +| `:affero` | `:oss` | Affero General Public License | +| `:apache` | `:oss` | Apache Public License | +| `:arphic` | `:oss` | Arphic Public License | +| `:artistic` | `:oss` | Artistic License | +| `:bsd` | `:oss` | BSD License | +| `:cc` | `:oss` | Creative Commons License | +| `:eclipse` | `:oss` | Eclipse Public License | +| `:gpl` | `:oss` | GNU Public License | +| `:isc` | `:oss` | Internet Systems Consortium License | +| `:lppl` | `:oss` | LaTeX Project Public License | +| `:ncsa` | `:oss` | University of Illinois/NCSA Open Source License | +| `:mit` | `:oss` | MIT License | +| `:mpl` | `:oss` | Mozilla Public License | +| `:ofl` | `:oss` | SIL Open Font License | +| `:public_domain` | `:oss` | not copyrighted | +| `:ubuntu_font` | `:oss` | Ubuntu Font License | +| `:x11` | `:oss` | X Consortium License | \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/name.md b/doc/cask_language_reference/stanzas/name.md new file mode 100644 index 0000000000..115001ffbd --- /dev/null +++ b/doc/cask_language_reference/stanzas/name.md @@ -0,0 +1,9 @@ +# name + +`name` accepts a UTF-8 string defining the full name of the software, and is used to help with searchability and disambiguation. It can be repeated multiple times if there are useful alternative names. + +Its first instance should use the latin alphabet, include the software vendor’s name, and be as verbose as possible while still making sense. + +A good example is [`pycharm-ce`](https://github.com/caskroom/homebrew-cask/blob/fc05c0353aebb28e40db72faba04b82ca832d11a/Casks/pycharm-ce.rb#L6#L7). `Jetbrains PyCharm Community Edition` makes sense even though it is likely never referenced as such anywhere, but `Jetbrains PyCharm Community Edition CE` doesn’t, hence why it has a second line. Another example are casks whose original names do not use the latin alphabet, like [`cave-story`](https://github.com/caskroom/homebrew-cask/blob/0fe48607f5656e4f1de58c6884945378b7e6f960/Casks/cave-story.rb#L7#L9). + +Note that `brew cask search` and `brew cask list` are not yet capable of using the information stored in the `name` stanza. \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/pkg.md b/doc/cask_language_reference/stanzas/pkg.md new file mode 100644 index 0000000000..bbffd537f1 --- /dev/null +++ b/doc/cask_language_reference/stanzas/pkg.md @@ -0,0 +1,17 @@ +# pkg + +The first argument to the `pkg` stanza should be a relative path to the `.pkg` file to be installed. For example: + +```ruby +pkg 'Unity.pkg' +``` + +Subsequent arguments to `pkg` are key/value pairs which modify the install process. Currently supported keys are: + +* `:allow_untrusted` — pass `-allowUntrusted` to `/usr/sbin/installer` + +Example (from [alinof-timer.rb](https://github.com/caskroom/homebrew-cask/blob/9a617c077dc238aac28dc9ad325f8924b19d6306/Casks/alinof-timer.rb)): + +```ruby +pkg 'AlinofTimer.pkg', :allow_untrusted => true +``` \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/sha256.md b/doc/cask_language_reference/stanzas/sha256.md new file mode 100644 index 0000000000..96d0115149 --- /dev/null +++ b/doc/cask_language_reference/stanzas/sha256.md @@ -0,0 +1,17 @@ +# sha256 + +## Calculating the SHA256 + +The `sha256` value is usually calculated by the command: + +```bash +$ shasum -a 256 +``` + +## Special Value `:no_check` + +The special value `sha256 :no_check` is used to turn off SHA checking whenever checksumming is impractical due to the upstream configuration. + +`version :latest` requires `sha256 :no_check`, and this pairing is common. However, `sha256 :no_check` does not require `version :latest`. + +We use a checksum whenever possible. \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/suite.md b/doc/cask_language_reference/stanzas/suite.md new file mode 100644 index 0000000000..9ef250d7e4 --- /dev/null +++ b/doc/cask_language_reference/stanzas/suite.md @@ -0,0 +1,11 @@ +# suite + +Some distributions provide a suite of multiple applications, or an application with required data, to be installed together in a subdirectory of `~/Applications`. + +For these Casks, use the `suite` stanza to define the directory containing the application suite. Example (from [sketchup.rb](https://github.com/caskroom/homebrew-cask/blob/b2c8d178ae8c668b233d390688812980cb3d4a29/Casks/sketchup.rb)): + +```ruby +suite 'SketchUp 2016' +``` + +The value of `suite` is never an `.app` bundle, but a plain directory. \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/uninstall.md b/doc/cask_language_reference/stanzas/uninstall.md new file mode 100644 index 0000000000..b1ef828e62 --- /dev/null +++ b/doc/cask_language_reference/stanzas/uninstall.md @@ -0,0 +1,199 @@ +# uninstall + +IF YOU CANNOT DESIGN A WORKING `UNINSTALL` STANZA, PLEASE SUBMIT YOUR CASK ANYWAY. The maintainers will help you write an `uninstall` stanza, just ask! + +## uninstall :pkgutil Is The Easiest and Most Useful + +`:pkgutil` is the easiest and most useful `uninstall` directive. See [Uninstall Key :pkgutil](#uninstall-key-pkgutil). + +## uninstall Is Required for Casks That Install a pkg or installer :manual + +For most Casks, uninstall actions are determined automatically, and an explicit `uninstall` stanza is not needed. However, a Cask which uses the `pkg` or `installer :pkg` stanzas will **not** know how to uninstall correctly unless an `uninstall` stanza is given. + +So, while the Cask language does not enforce the requirement, it is much better for end-users if every `pkg` and `installer :manual` has a corresponding `uninstall`. + +The `uninstall` stanza is available for non-`pkg` Casks, and is useful for a few corner cases. However, the documentation below concerns the typical case of using `uninstall` to define procedures for a `pkg`. + +## There Are Multiple Uninstall Techniques + +Since `pkg` installers can do arbitrary things, different techniques are needed to uninstall in each case. You may need to specify one, or several, of the following key/value pairs as arguments to `uninstall`. + +## Summary of Keys + +* `:early_script` (string or hash) - like `:script`, but runs early (for special cases, best avoided) +* `:launchctl` (string or array) - ids of `launchctl` jobs to remove +* `:quit` (string or array) - bundle ids of running applications to quit +* `:signal` (array of arrays) - signal numbers and bundle ids of running applications to send a Unix signal to (used when `:quit` does not work) +* `:login_item` (string or array) - names of login items to remove +* `:kext` (string or array) - bundle ids of kexts to unload from the system +* `:pkgutil` (string, regexp or array of strings and regexps) - strings or regexps matching bundle ids of packages to uninstall using `pkgutil` +* `:script` (string or hash) - relative path to an uninstall script to be run via sudo; use hash if args are needed + - `:executable` - relative path to an uninstall script to be run via sudo (required for hash form) + - `:args` - array of arguments to the uninstall script + - `:input` - array of lines of input to be sent to `stdin` of the script + - `:must_succeed` - set to `false` if the script is allowed to fail + - `:sudo` - set to `false` if the script does not need `sudo` +* `:delete` (string or array) - single-quoted, absolute paths of files or directory trees to remove. `:delete` should only be used as a last resort. `:pkgutil` is strongly preferred. +* `:rmdir` (string or array) - single-quoted, absolute paths of directories to remove if empty +* `:trash` (string or array) - currently a synonym for `:delete`. In the future this will cause files to be moved to the Trash. + +Each `uninstall` technique is applied according to the order above. The order in which `uninstall` keys appear in the Cask file is ignored. + +For assistance filling in the right values for `uninstall` keys, there are several helper scripts found under `developer/bin` in the Homebrew-Cask repository. Each of these scripts responds to the `-help` option with additional documentation. + +The easiest way to work out an `uninstall` stanza is on a system where the `pkg` is currently installed and operational. To operate on an uninstalled `pkg` file, see [Working With a pkg File Manually](#working-with-a-pkg-file-manually), below. + +## uninstall Key :pkgutil + +This is the most useful uninstall key. `:pkgutil` is often sufficient to completely uninstall a `pkg`, and is strongly preferred over `:delete`. + +IDs for the most recently-installed packages can be listed using the command: + +```bash +$ ./developer/bin/list_recent_pkg_ids +``` + +`:pkgutil` also accepts a regular expression match against multiple package IDs. The regular expressions are somewhat nonstandard. To test a `:pkgutil` regular expression against currently-installed packages, use the command: + +```bash +$ ./developer/bin/list_pkg_ids_by_regexp +``` + +## List Files Associated With a pkg Id + +Once you know the ID for an installed package, (above), you can list all files on your system associated with that package ID using the OS X command: + +```bash +$ pkgutil --files +``` + +Listing the associated files can help you assess whether the package included any `launchctl` jobs or kernel extensions (kexts). + +## uninstall Key :launchctl + +IDs for currently loaded `launchctl` jobs can be listed using the command: + +```bash +$ ./developer/bin/list_loaded_launchjob_ids +``` + +IDs for all installed `launchctl` jobs can be listed using the command: + +```bash +$ ./developer/bin/list_installed_launchjob_ids +``` + +## uninstall Key :quit + +Bundle IDs for currently running Applications can be listed using the command: + +```bash +$ ./developer/bin/list_running_app_ids +``` + +Bundle IDs inside an Application bundle on disk can be listed using the command: + +```bash +$ ./developer/bin/list_ids_in_app +``` + +## uninstall Key :signal + +`:signal` should only be needed in the rare case that a process does not respond to `:quit`. + +Bundle IDs for `:signal` targets may be obtained as for `:quit`. The value for `:signal` is an array-of-arrays, with each cell containing two elements: the desired Unix signal followed by the corresponding bundle ID. + +The Unix signal may be given in numeric or string form (see the `kill` man page for more details). + +The elements of the `:signal` array are applied in order, only if there is an existing process associated the bundle ID, and stopping when that process terminates. A bundle ID may be repeated to send more than one signal to the same process. + +It is better to use the least-severe signals which are sufficient to stop a process. The `KILL` signal in particular can have unwanted side-effects. + +An example, with commonly-used signals in ascending order of severity: + +```ruby + 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'], + ] +``` + +Note that when multiple running processes match the given Bundle ID, all matching processes will be signaled. + +Unlike `:quit` directives, Unix signals originate from the current user, not from the superuser. This is construed as a safety feature, since the superuser is capable of bringing down the system via signals. However, this inconsistency may also be considered a bug, and should be addressed in some fashion in a future version. + +## uninstall key :login_item + +Login items associated with an Application bundle on disk can be listed using the command: + +```bash +$ ./developer/bin/list_login_items_for_app +``` + +Note that you will likely need to have opened the app at least once for any login items to be present. + +## uninstall Key :kext + +IDs for currently loaded kernel extensions can be listed using the command: + +```bash +$ ./developer/bin/list_loaded_kext_ids +``` + +IDs inside a kext bundle you have located on disk can be listed using the command: + +```bash +$ ./developer/bin/list_id_in_kext +``` + +## uninstall Key :delete + +`:delete` should only be used as a last resort, if other `uninstall` methods are insufficient. + +Arguments to `uninstall :delete` should be static, single-quoted, absolute paths. + +* Only single quotes should be used. +* Double-quotes should not be used. `ENV['HOME']` and other variables + should not be interpolated in the value. +* Basic tilde expansion is performed on paths, i.e., leading `~` is expanded to the home directory. +* Only absolute paths should be given. +* No glob expansion is performed (*eg* `*` characters are literal), though glob expansion is a desired future feature. + +To remove user-specific files, use the `zap` stanza. + +## uninstall Key :trash + +*stub* - currently a synonym for `:delete`. In the future this will cause files to be moved to the Trash. It is best not to use this stub until it gains the proper functionality. + +## Working With a pkg File Manually + +Advanced users may wish to work with a `pkg` file manually, without having the package installed. + +A list of files which may be installed from a `pkg` can be extracted using the command: + +```bash +$ ./developer/bin/list_payload_in_pkg +``` + +Candidate application names helpful for determining the name of a Cask may be extracted from a `pkg` file using the command: + +```bash +$ ./developer/bin/list_apps_in_pkg +``` + +Candidate package IDs which may be useful in a `:pkgutil` key may be extracted from a `pkg` file using the command: + +```bash +$ ./developer/bin/list_ids_in_pkg +``` + +A fully manual method for finding bundle ids in a package file follows: + +1. Unpack `/path/to/my.pkg` (replace with your package name) with `pkgutil --expand /path/to/my.pkg /tmp/expanded.unpkg`. +2. The unpacked package is a folder. Bundle ids are contained within files named `PackageInfo`. These files can be found with the command `find /tmp/expanded.unpkg -name PackageInfo`. +3. `PackageInfo` files are XML files, and bundle ids are found within the `identifier` attributes of `` tags that look like ``, where extraneous attributes have been snipped out and replaced with ellipses. +4. Kexts inside packages are also described in `PackageInfo` files. If any kernel extensions are present, the command `find /tmp/expanded.unpkg -name PackageInfo -print0 | xargs -0 grep -i kext` should return a `` tag with a `path` attribute that contains a `.kext` extension, for example ``. +5. Once bundle ids have been identified, the unpacked package directory can be deleted. \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/url.md b/doc/cask_language_reference/stanzas/url.md new file mode 100644 index 0000000000..d8a1ec7d93 --- /dev/null +++ b/doc/cask_language_reference/stanzas/url.md @@ -0,0 +1,89 @@ +# url + +## HTTPS URLs are Preferred + +If available, an HTTPS URL is preferred. A plain HTTP URL should only be used in the absence of a secure alternative. + +## Additional HTTP/S URL Parameters + +When a plain URL string is insufficient to fetch a file, additional information may be provided to the `curl`-based downloader, in the form of key/value pairs appended to `url`: + +| key | value | +| ------------------ | ----------- | +| `:using` | the symbol `:post` is the only legal value +| `:cookies` | a hash of cookies to be set in the download request +| `:referer` | a string holding the URL to set as referrer in the download request +| `:user_agent` | a string holding the user agent to set for the download request. Can also be set to the symbol `:fake`, which will use a generic Browser-like user agent string. We prefer `:fake` when the server does not require a specific user agent. +| `:data` | a hash of parameters to be set in the POST request + +Example of using `:cookies`: [java.rb](https://github.com/caskroom/homebrew-cask/blob/b78fb320fc303fc503386aa6fac47fdd105ecbfb/Casks/java.rb#L5#L8) + +Example of using `:referer`: [rrootage.rb](https://github.com/caskroom/homebrew-cask/blob/992d34fec0a12193207a91d57b92bfcfb25174ea/Casks/rrootage.rb#L5) + +## When URL and Homepage Hostnames Differ, Add a Comment + +When the hostnames of `url` and `homepage` differ, the discrepancy should be documented with a comment of the form: + +``` +# URL_HOSTNAME is the official download host per the vendor homepage +``` + +Examples can be seen in [visit.rb](https://github.com/caskroom/homebrew-cask/blob/cafcd7cf7922022ea607c5811c63d45863c7ed36/Casks/visit.rb#L5) and [vistrails.rb](https://github.com/caskroom/homebrew-cask/blob/cafcd7cf7922022ea607c5811c63d45863c7ed36/Casks/vistrails.rb#L5). + +These comments must be added so a user auditing the cask knows the URL is the one provided by the vendor, even though it may look unofficial or suspicious. It is our responsibility as Homebrew-Cask maintainers to verify both the `url` and `homepage` information when first added (or subsequently modified, apart from versioning). The exception to this rule is a `homepage` of `github.io` with a `url` of `github.com`, since we know this pair of hostnames is connected. + +## Difficulty Finding a URL + +Web browsers may obscure the direct `url` download location for a variety of reasons. Homebrew-Cask supplies a script which can read extended file attributes to extract the actual source URL for most files downloaded by a browser on OS X. The script usually emits multiple candidate URLs; you may have to test each of them: + +```bash +$ $(brew --repository)/Library/Taps/caskroom/homebrew-cask/developer/bin/list_url_attributes_on_file +``` + +## Subversion URLs + +In rare cases, a distribution may not be available over ordinary HTTP/S. Subversion URLs are also supported, and can be specified by appending the following key/value pairs to `url`: + +| key | value | +| ------------------ | ----------- | +| `:using` | the symbol `:svn` is the only legal value +| `:revision` | a string identifying the subversion revision to download +| `:trust_cert` | set to `true` to automatically trust the certificate presented by the server (avoiding an interactive prompt) + +## SourceForge/OSDN URLs + +SourceForge and OSDN (formerly SourceForge.JP) projects are common ways to distribute binaries, but they provide many different styles of URLs to get to the goods. + +We prefer URLs of this format: + +``` +http://downloads.sourceforge.net/sourceforge/$PROJECTNAME/$FILENAME.$EXT +``` + +Or, if it’s from [OSDN](https://osdn.jp/): + +``` +http://$STRING.osdn.jp/$PROJECTNAME/$RELEASEID/$FILENAME.$EXT +``` + +`$STRING` is typically of the form `dl` or `$USER.dl`. + +If these formats are not available, and the application is Mac-exclusive (otherwise a command-line download defaults to the Windows version) we prefer the use of this format: + +``` +http://sourceforge.net/projects/$PROJECTNAME/files/latest/download +``` + +## Personal Hosting Such as Dropbox + +URLs from dropbox.com or cl.ly/cloudapp.com are not readily distinguishable as being controlled by the original software vendor. These URLs should be used only when given as such on the official project website. + +Also make sure to give the URL for the binary download itself, rather than a preview page. (See .) + +## Some Providers Block Command-line Downloads + +Some hosting providers actively block command-line HTTP clients (example: FossHub). Such URLs cannot be used in Casks. + +## Vendor URLs Are Preferred + +When possible, it is best to use a download URL from the original developer or vendor, rather than an aggregator such as `macupdate.com`. \ No newline at end of file diff --git a/doc/cask_language_reference/stanzas/version.md b/doc/cask_language_reference/stanzas/version.md new file mode 100644 index 0000000000..74a31faf10 --- /dev/null +++ b/doc/cask_language_reference/stanzas/version.md @@ -0,0 +1,53 @@ +# version + +`version`, while related to the app’s own versioning, doesn’t have to follow it exactly. It is common to change it slightly so it can be [interpolated](https://en.wikipedia.org/wiki/String_interpolation#Ruby) in other stanzas, usually in `url` to create a Cask that only needs `version` and `sha256` changes when updated. This can be taken further, when needed, with [ruby String methods](http://ruby-doc.org/core/String.html). + +For example: + +Instead of + +```ruby +version '1.2.3' +url 'http://example.com/file-version-123.dmg' +``` + +We can use + +```ruby +version '1.2.3' +url "http://example.com/file-version-#{version.delete('.')}.dmg" +``` + +We can also leverage the power of regular expressions. So instead of + +```ruby +version '1.2.3build4' +url 'http://example.com/1.2.3/file-version-1.2.3build4.dmg' +``` + +We can use + +```ruby +version '1.2.3build4' +url "http://example.com/#{version.sub(%r{build\d+}, '')}/file-version-#{version}.dmg" +``` + +## version methods + +The examples above can become hard to read, however. Since many of these changes are common, we provide a number of helpers to clearly interpret otherwise obtuse cases: + +| Method | Input | Output | +|--------------------------|--------------------|--------------------| +| `major` | `1.2.3-a45,ccdd88` | `1` | +| `minor` | `1.2.3-a45,ccdd88` | `2` | +| `patch` | `1.2.3-a45,ccdd88` | `3` | +| `major_minor` | `1.2.3-a45,ccdd88` | `1.2` | +| `major_minor_patch` | `1.2.3-a45,ccdd88` | `1.2.3` | +| `before_comma` | `1.2.3-a45,ccdd88` | `1.2.3-a45` | +| `after_comma` | `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` | + +Similar to `dots_to_hyphens`, we provide all logical permutations of `{dots,hyphens,underscores,slashes}_to_{dots,hyphens,underscores,slashes}`. The same applies to `no_dots` in the form of `no_{dots,hyphens,underscores,slashes}`, with an extra `no_dividers` that applies all of those at once. + +Finally, there are `before_colon` and `after_colon` that act like their `comma` counterparts. These four are extra special to allow for otherwise complex cases, and should be used sparingly. There should be no more than one of `,` and `:` per `version`. Use `,` first, and `:` only if absolutely necessary. diff --git a/doc/cask_language_reference/stanzas/zap.md b/doc/cask_language_reference/stanzas/zap.md new file mode 100644 index 0000000000..d7abd6fe75 --- /dev/null +++ b/doc/cask_language_reference/stanzas/zap.md @@ -0,0 +1,24 @@ +# zap + +## zap Stanza Purpose + +The `zap` stanza describes a more complete uninstallation of files associated with a Cask. The `zap` procedures will never be performed by default, but only if the user invokes the `zap` verb: + +```bash +$ brew cask zap td-toolbelt # also removes org.ruby-lang.installer +``` + +`zap` stanzas may remove: + +* Preference files and caches stored within the user’s `~/Library` directory. +* Shared resources such as application updaters. Since shared resources may be removed, other applications may be affected by `brew cask zap`. Understanding that is the responsibility of the end user. + +`zap` stanzas should not remove: + +* Files created by the user directly. + +## zap Stanza Syntax + +The form of `zap` stanza follows the [`uninstall` stanza](#uninstall-stanza-details). All of the same directives are available. Unlike with `uninstall`, however, `:delete` is not discouraged in `zap`. + +Example: [injection.rb](https://github.com/caskroom/homebrew-cask/blob/3a56867b39be1095f1247e4bad3f77eb4eb52ede/Casks/injection.rb#L16) \ No newline at end of file diff --git a/doc/cask_token_reference.md b/doc/cask_language_reference/token_reference.md similarity index 97% rename from doc/cask_token_reference.md rename to doc/cask_language_reference/token_reference.md index af51097398..014001e076 100644 --- a/doc/cask_token_reference.md +++ b/doc/cask_language_reference/token_reference.md @@ -23,7 +23,7 @@ The token itself should be: * Suitable for use as a filename * Mnemonic -Details of software names and brands will inevitably be lost in the conversion to a minimal token. To capture the vendor’s full name for a distribution, use the [`name`](CASK_LANGUAGE_REFERENCE.md#name-stanza-details) within a Cask. `name` accepts an unrestricted UTF-8 string. +Details of software names and brands will inevitably be lost in the conversion to a minimal token. To capture the vendor’s full name for a distribution, use the [`name`](https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/name.md) within a Cask. `name` accepts an unrestricted UTF-8 string. ## Finding the Simplified Name of the Vendor’s Distribution diff --git a/doc/development/adding_a_cask.md b/doc/development/adding_a_cask.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/doc/hacking.md b/doc/development/hacking.md similarity index 99% rename from doc/hacking.md rename to doc/development/hacking.md index ed7d887206..47b4496591 100644 --- a/doc/hacking.md +++ b/doc/development/hacking.md @@ -39,7 +39,7 @@ However, very little backend code is shared between the two projects. The Homebr Homebrew Formulae deal with many different build processes, and often include arbitrary Ruby code. -Casks, by contrast, only need to support the few installation methods used by apps, pkg installers, and so on, making them suitable for a [declarative DSL](https://github.com/caskroom/homebrew-cask/blob/master/doc/CASK_LANGUAGE_REFERENCE.md). +Casks, by contrast, only need to support the few installation methods used by apps, pkg installers, and so on, making them suitable for a [declarative DSL](https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/). We encourage Cask authors to use the DSL as much as possible, since that makes things easier for everyone: from maintainers who review pull requests, to first-time contributors, to people who are unfamiliar with Ruby but would like to help. diff --git a/doc/maintaining.md b/doc/development/maintaining.md similarity index 100% rename from doc/maintaining.md rename to doc/development/maintaining.md diff --git a/doc/src/brew-cask.1.md b/doc/man_page/brew-cask.1.md similarity index 100% rename from doc/src/brew-cask.1.md rename to doc/man_page/brew-cask.1.md diff --git a/doc/readme.md b/doc/readme.md new file mode 100644 index 0000000000..6e1c3cd608 --- /dev/null +++ b/doc/readme.md @@ -0,0 +1,12 @@ +# Cask Language Reference + ++ [Synopsis](cask_language_reference/readme.md) ++ [Token reference](cask_language_reference/token_reference.md) ++ [Stanza list](cask_language_reference/all_stanzas.md) ++ [Stanza documentation](cask_language_reference/stanzas/) + +# Contributing + ++ [Contributing to the core](development/hacking.md) ++ [Adding a new cask](development/adding_a_cask.md) ++ [Meta information on the project’s structure](development/maintaining.md)