Merge pull request #20421 from Homebrew/cask-rename-stanza
cask/dsl/rename: add new `rename` dsl
This commit is contained in:
commit
7dd47ca89a
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
require "cask/denylist"
|
require "cask/denylist"
|
||||||
require "cask/download"
|
require "cask/download"
|
||||||
|
require "cask/installer"
|
||||||
require "digest"
|
require "digest"
|
||||||
require "livecheck/livecheck"
|
require "livecheck/livecheck"
|
||||||
require "source_location"
|
require "source_location"
|
||||||
@ -631,6 +632,11 @@ module Cask
|
|||||||
.extract_nestedly(to: @tmpdir, verbose: false)
|
.extract_nestedly(to: @tmpdir, verbose: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Process rename operations after extraction
|
||||||
|
# Create a temporary installer to process renames in the audit directory
|
||||||
|
temp_installer = Installer.new(@cask)
|
||||||
|
temp_installer.process_rename_operations(target_dir: @tmpdir)
|
||||||
|
|
||||||
# Set the flag to indicate that extraction has occurred.
|
# Set the flag to indicate that extraction has occurred.
|
||||||
@artifacts_extracted = T.let(true, T.nilable(TrueClass))
|
@artifacts_extracted = T.let(true, T.nilable(TrueClass))
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ require "cask/dsl/container"
|
|||||||
require "cask/dsl/depends_on"
|
require "cask/dsl/depends_on"
|
||||||
require "cask/dsl/postflight"
|
require "cask/dsl/postflight"
|
||||||
require "cask/dsl/preflight"
|
require "cask/dsl/preflight"
|
||||||
|
require "cask/dsl/rename"
|
||||||
require "cask/dsl/uninstall_postflight"
|
require "cask/dsl/uninstall_postflight"
|
||||||
require "cask/dsl/uninstall_preflight"
|
require "cask/dsl/uninstall_preflight"
|
||||||
require "cask/dsl/version"
|
require "cask/dsl/version"
|
||||||
@ -81,6 +82,7 @@ module Cask
|
|||||||
:language,
|
:language,
|
||||||
:name,
|
:name,
|
||||||
:os,
|
:os,
|
||||||
|
:rename,
|
||||||
:sha256,
|
:sha256,
|
||||||
:staged_path,
|
:staged_path,
|
||||||
:url,
|
:url,
|
||||||
@ -162,6 +164,7 @@ module Cask
|
|||||||
@on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion))
|
@on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion))
|
||||||
@os = T.let(nil, T.nilable(String))
|
@os = T.let(nil, T.nilable(String))
|
||||||
@os_set_in_block = T.let(false, T::Boolean)
|
@os_set_in_block = T.let(false, T::Boolean)
|
||||||
|
@rename = T.let([], T::Array[DSL::Rename])
|
||||||
@sha256 = T.let(nil, T.nilable(T.any(Checksum, Symbol)))
|
@sha256 = T.let(nil, T.nilable(T.any(Checksum, Symbol)))
|
||||||
@sha256_set_in_block = T.let(false, T::Boolean)
|
@sha256_set_in_block = T.let(false, T::Boolean)
|
||||||
@staged_path = T.let(nil, T.nilable(Pathname))
|
@staged_path = T.let(nil, T.nilable(Pathname))
|
||||||
@ -343,6 +346,28 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Renames files after extraction.
|
||||||
|
#
|
||||||
|
# This is useful when the downloaded file has unpredictable names
|
||||||
|
# that need to be normalized for proper artifact installation.
|
||||||
|
#
|
||||||
|
# ### Example
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# rename "RØDECaster App*.pkg", "RØDECaster App.pkg"
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# @api public
|
||||||
|
sig {
|
||||||
|
params(from: String,
|
||||||
|
to: String).returns(T::Array[DSL::Rename])
|
||||||
|
}
|
||||||
|
def rename(from = T.unsafe(nil), to = T.unsafe(nil))
|
||||||
|
return @rename if from.nil?
|
||||||
|
|
||||||
|
@rename << DSL::Rename.new(T.must(from), T.must(to))
|
||||||
|
end
|
||||||
|
|
||||||
# Sets the cask's version.
|
# Sets the cask's version.
|
||||||
#
|
#
|
||||||
# ### Example
|
# ### Example
|
||||||
|
52
Library/Homebrew/cask/dsl/rename.rb
Normal file
52
Library/Homebrew/cask/dsl/rename.rb
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# typed: strict
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Cask
|
||||||
|
class DSL
|
||||||
|
# Class corresponding to the `rename` stanza.
|
||||||
|
class Rename
|
||||||
|
sig { returns(String) }
|
||||||
|
attr_reader :from, :to
|
||||||
|
|
||||||
|
sig { params(from: String, to: String).void }
|
||||||
|
def initialize(from, to)
|
||||||
|
@from = from
|
||||||
|
@to = to
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { params(staged_path: Pathname).void }
|
||||||
|
def perform_rename(staged_path)
|
||||||
|
return unless staged_path.exist?
|
||||||
|
|
||||||
|
# Find files matching the glob pattern
|
||||||
|
matching_files = if @from.include?("*")
|
||||||
|
staged_path.glob(@from)
|
||||||
|
else
|
||||||
|
[staged_path.join(@from)].select(&:exist?)
|
||||||
|
end
|
||||||
|
|
||||||
|
return if matching_files.empty?
|
||||||
|
|
||||||
|
# Rename the first matching file to the target path
|
||||||
|
source_file = matching_files.first
|
||||||
|
return if source_file.nil?
|
||||||
|
|
||||||
|
target_file = staged_path.join(@to)
|
||||||
|
|
||||||
|
# Ensure target directory exists
|
||||||
|
target_file.dirname.mkpath
|
||||||
|
|
||||||
|
# Perform the rename
|
||||||
|
source_file.rename(target_file.to_s) if source_file.exist?
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Hash[Symbol, String]) }
|
||||||
|
def pairs
|
||||||
|
{ from:, to: }
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(String) }
|
||||||
|
def to_s = pairs.inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -125,6 +125,7 @@ module Cask
|
|||||||
Caskroom.ensure_caskroom_exists
|
Caskroom.ensure_caskroom_exists
|
||||||
|
|
||||||
extract_primary_container
|
extract_primary_container
|
||||||
|
process_rename_operations
|
||||||
save_caskfile
|
save_caskfile
|
||||||
rescue => e
|
rescue => e
|
||||||
purge_versioned_files
|
purge_versioned_files
|
||||||
@ -292,6 +293,19 @@ on_request: true)
|
|||||||
Quarantine.propagate(from: primary_container.path, to:)
|
Quarantine.propagate(from: primary_container.path, to:)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(target_dir: T.nilable(Pathname)).void }
|
||||||
|
def process_rename_operations(target_dir: nil)
|
||||||
|
return if @cask.rename.empty?
|
||||||
|
|
||||||
|
working_dir = target_dir || @cask.staged_path
|
||||||
|
odebug "Processing rename operations in #{working_dir}"
|
||||||
|
|
||||||
|
@cask.rename.each do |rename_operation|
|
||||||
|
odebug "Renaming #{rename_operation.from} to #{rename_operation.to}"
|
||||||
|
rename_operation.perform_rename(working_dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
sig { params(predecessor: T.nilable(Cask)).void }
|
sig { params(predecessor: T.nilable(Cask)).void }
|
||||||
def install_artifacts(predecessor: nil)
|
def install_artifacts(predecessor: nil)
|
||||||
already_installed_artifacts = []
|
already_installed_artifacts = []
|
||||||
|
@ -34,6 +34,9 @@ module RuboCop
|
|||||||
:depends_on,
|
:depends_on,
|
||||||
:container,
|
:container,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
:rename,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
:suite,
|
:suite,
|
||||||
:app,
|
:app,
|
||||||
|
3
Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi
generated
3
Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi
generated
@ -168,6 +168,9 @@ class Cask::Cask
|
|||||||
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
def qlplugin(*args, &block); end
|
def qlplugin(*args, &block); end
|
||||||
|
|
||||||
|
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
|
def rename(*args, &block); end
|
||||||
|
|
||||||
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||||
def screen_saver(*args, &block); end
|
def screen_saver(*args, &block); end
|
||||||
|
|
||||||
|
114
Library/Homebrew/test/cask/dsl/rename_spec.rb
Normal file
114
Library/Homebrew/test/cask/dsl/rename_spec.rb
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe Cask::DSL::Rename do
|
||||||
|
subject(:rename) { described_class.new(from, to) }
|
||||||
|
|
||||||
|
let(:from) { "Source File*.pkg" }
|
||||||
|
let(:to) { "Target File.pkg" }
|
||||||
|
|
||||||
|
describe "#initialize" do
|
||||||
|
it "sets the from and to attributes" do
|
||||||
|
expect(rename.from).to eq("Source File*.pkg")
|
||||||
|
expect(rename.to).to eq("Target File.pkg")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#pairs" do
|
||||||
|
it "returns the attributes as a hash" do
|
||||||
|
expect(rename.pairs).to eq(from: "Source File*.pkg", to: "Target File.pkg")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#to_s" do
|
||||||
|
it "returns the stringified attributes" do
|
||||||
|
expect(rename.to_s).to eq(rename.pairs.inspect)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#perform_rename" do
|
||||||
|
let(:tmpdir) { mktmpdir }
|
||||||
|
let(:staged_path) { Pathname(tmpdir) }
|
||||||
|
|
||||||
|
context "when staged_path does not exist" do
|
||||||
|
let(:staged_path) { Pathname("/nonexistent/path") }
|
||||||
|
|
||||||
|
it "does nothing" do
|
||||||
|
expect { rename.perform_rename(staged_path) }.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when using glob patterns" do
|
||||||
|
let(:from) { "Test App*.pkg" }
|
||||||
|
let(:to) { "Test App.pkg" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
(staged_path / "Test App v1.2.3.pkg").write("test content")
|
||||||
|
(staged_path / "Test App v2.0.0.pkg").write("other content")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "renames the first matching file" do
|
||||||
|
rename.perform_rename(staged_path)
|
||||||
|
|
||||||
|
expect(staged_path / "Test App.pkg").to exist
|
||||||
|
expect((staged_path / "Test App.pkg").read).to eq("test content")
|
||||||
|
expect(staged_path / "Test App v1.2.3.pkg").not_to exist
|
||||||
|
expect(staged_path / "Test App v2.0.0.pkg").to exist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when using exact filenames" do
|
||||||
|
let(:from) { "Exact File.dmg" }
|
||||||
|
let(:to) { "New Name.dmg" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
(staged_path / "Exact File.dmg").write("dmg content")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "renames the exact file" do
|
||||||
|
rename.perform_rename(staged_path)
|
||||||
|
|
||||||
|
expect(staged_path / "New Name.dmg").to exist
|
||||||
|
expect((staged_path / "New Name.dmg").read).to eq("dmg content")
|
||||||
|
expect(staged_path / "Exact File.dmg").not_to exist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when target is in a subdirectory" do
|
||||||
|
let(:from) { "source.txt" }
|
||||||
|
let(:to) { "subdir/target.txt" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
(staged_path / "source.txt").write("content")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "creates the subdirectory and renames the file" do
|
||||||
|
rename.perform_rename(staged_path)
|
||||||
|
|
||||||
|
expect(staged_path / "subdir" / "target.txt").to exist
|
||||||
|
expect((staged_path / "subdir" / "target.txt").read).to eq("content")
|
||||||
|
expect(staged_path / "source.txt").not_to exist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when no files match the pattern" do
|
||||||
|
let(:from) { "nonexistent*.pkg" }
|
||||||
|
let(:to) { "target.pkg" }
|
||||||
|
|
||||||
|
it "does nothing" do
|
||||||
|
rename.perform_rename(staged_path)
|
||||||
|
|
||||||
|
expect(staged_path / "target.pkg").not_to exist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when source file doesn't exist after glob" do
|
||||||
|
let(:from) { "missing.txt" }
|
||||||
|
let(:to) { "target.txt" }
|
||||||
|
|
||||||
|
it "does nothing" do
|
||||||
|
expect { rename.perform_rename(staged_path) }.not_to raise_error
|
||||||
|
expect(staged_path / "target.txt").not_to exist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -598,4 +598,29 @@ RSpec.describe Cask::DSL, :cask, :no_api do
|
|||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "rename stanza" do
|
||||||
|
it "allows setting single rename operation" do
|
||||||
|
cask = Cask::Cask.new("rename-cask") do
|
||||||
|
rename "Source*.pkg", "Target.pkg"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(cask.rename.length).to eq(1)
|
||||||
|
expect(cask.rename.first.from).to eq("Source*.pkg")
|
||||||
|
expect(cask.rename.first.to).to eq("Target.pkg")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "allows setting multiple rename operations" do
|
||||||
|
cask = Cask::Cask.new("multi-rename-cask") do
|
||||||
|
rename "App*.pkg", "App.pkg"
|
||||||
|
rename "Doc*.dmg", "Doc.dmg"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(cask.rename.length).to eq(2)
|
||||||
|
expect(cask.rename.first.from).to eq("App*.pkg")
|
||||||
|
expect(cask.rename.first.to).to eq("App.pkg")
|
||||||
|
expect(cask.rename.last.from).to eq("Doc*.dmg")
|
||||||
|
expect(cask.rename.last.to).to eq("Doc.dmg")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -423,4 +423,94 @@ RSpec.describe Cask::Installer, :cask do
|
|||||||
end.to raise_error(Cask::CaskCannotBeInstalledError, /#{dep_name} formula was forbidden/)
|
end.to raise_error(Cask::CaskCannotBeInstalledError, /#{dep_name} formula was forbidden/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "rename operations" do
|
||||||
|
let(:tmpdir) { mktmpdir }
|
||||||
|
let(:staged_path) { Pathname(tmpdir) }
|
||||||
|
|
||||||
|
after do
|
||||||
|
FileUtils.rm_rf(tmpdir) if tmpdir && File.exist?(tmpdir)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "processes rename operations after extraction" do
|
||||||
|
# Create test files
|
||||||
|
(staged_path / "Original App.app").mkpath
|
||||||
|
(staged_path / "Original App.app" / "Contents").mkpath
|
||||||
|
|
||||||
|
cask = Cask::Cask.new("rename-test-cask") do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
||||||
|
rename "Original App.app", "Renamed App.app"
|
||||||
|
app "Renamed App.app"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mock the staged_path to point to our test directory
|
||||||
|
allow(cask).to receive(:staged_path).and_return(staged_path)
|
||||||
|
|
||||||
|
installer = described_class.new(cask)
|
||||||
|
installer.send(:process_rename_operations)
|
||||||
|
|
||||||
|
expect(staged_path / "Renamed App.app").to be_a_directory
|
||||||
|
expect(staged_path / "Original App.app").not_to exist
|
||||||
|
end
|
||||||
|
|
||||||
|
it "handles multiple rename operations in order" do
|
||||||
|
# Create test file
|
||||||
|
(staged_path / "Original.app").mkpath
|
||||||
|
|
||||||
|
cask = Cask::Cask.new("multi-rename-test-cask") do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
||||||
|
rename "Original.app", "First Rename.app"
|
||||||
|
rename "First Rename.app", "Final Name.app"
|
||||||
|
app "Final Name.app"
|
||||||
|
end
|
||||||
|
|
||||||
|
allow(cask).to receive(:staged_path).and_return(staged_path)
|
||||||
|
|
||||||
|
installer = described_class.new(cask)
|
||||||
|
installer.send(:process_rename_operations)
|
||||||
|
|
||||||
|
expect(staged_path / "Final Name.app").to be_a_directory
|
||||||
|
expect(staged_path / "Original.app").not_to exist
|
||||||
|
expect(staged_path / "First Rename.app").not_to exist
|
||||||
|
end
|
||||||
|
|
||||||
|
it "handles glob patterns in rename operations" do
|
||||||
|
# Create test file with version
|
||||||
|
(staged_path / "Test App v1.2.3.pkg").write("test content")
|
||||||
|
|
||||||
|
cask = Cask::Cask.new("glob-rename-test-cask") do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
||||||
|
rename "Test App*.pkg", "Test App.pkg"
|
||||||
|
pkg "Test App.pkg"
|
||||||
|
end
|
||||||
|
|
||||||
|
allow(cask).to receive(:staged_path).and_return(staged_path)
|
||||||
|
|
||||||
|
installer = described_class.new(cask)
|
||||||
|
installer.send(:process_rename_operations)
|
||||||
|
|
||||||
|
expect(staged_path / "Test App.pkg").to be_a_file
|
||||||
|
expect((staged_path / "Test App.pkg").read).to eq("test content")
|
||||||
|
expect(staged_path / "Test App v1.2.3.pkg").not_to exist
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does nothing when no files match rename pattern" do
|
||||||
|
# Create a different file
|
||||||
|
(staged_path / "Different.app").mkpath
|
||||||
|
|
||||||
|
cask = Cask::Cask.new("no-match-rename-test-cask") do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
||||||
|
rename "NonExistent*.app", "Target.app"
|
||||||
|
app "Different.app"
|
||||||
|
end
|
||||||
|
|
||||||
|
allow(cask).to receive(:staged_path).and_return(staged_path)
|
||||||
|
|
||||||
|
installer = described_class.new(cask)
|
||||||
|
|
||||||
|
expect { installer.send(:process_rename_operations) }.not_to raise_error
|
||||||
|
expect(staged_path / "Different.app").to be_a_directory
|
||||||
|
expect(staged_path / "Target.app").not_to exist
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -66,6 +66,8 @@ Having a common order for stanzas makes casks easier to update and parse. Below
|
|||||||
depends_on
|
depends_on
|
||||||
container
|
container
|
||||||
|
|
||||||
|
rename
|
||||||
|
|
||||||
suite
|
suite
|
||||||
app
|
app
|
||||||
pkg
|
pkg
|
||||||
@ -176,6 +178,7 @@ Each cask must declare one or more [artifacts](https://rubydoc.brew.sh/Cask/Arti
|
|||||||
| `container type:` | no | 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/Homebrew/homebrew-cask/blob/aa461148bbb5119af26b82cccf5003e2b4e50d95/Casks/p/parse.rb#L10)) |
|
| `container type:` | no | 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/Homebrew/homebrew-cask/blob/aa461148bbb5119af26b82cccf5003e2b4e50d95/Casks/p/parse.rb#L10)) |
|
||||||
| `auto_updates` | no | `true`. Asserts that the cask artifacts auto-update. Use if `Check for Updates…` or similar is present in an app menu, but not if it only opens a webpage and does not do the download and installation for you. |
|
| `auto_updates` | no | `true`. Asserts that the cask artifacts auto-update. Use if `Check for Updates…` or similar is present in an app menu, but not if it only opens a webpage and does not do the download and installation for you. |
|
||||||
| [`no_autobump!`](#stanza-no_autobump) | no | Allowed symbol or a string. Excludes cask from autobumping if set. |
|
| [`no_autobump!`](#stanza-no_autobump) | no | Allowed symbol or a string. Excludes cask from autobumping if set. |
|
||||||
|
| [`rename`](#stanza-rename) | yes | A pair of strings. |
|
||||||
|
|
||||||
## Stanza descriptions
|
## Stanza descriptions
|
||||||
|
|
||||||
@ -252,6 +255,18 @@ binary "#{appdir}/Atom.app/Contents/Resources/app/atom.sh", target: "atom"
|
|||||||
|
|
||||||
Behaviour and usage of `target:` is [the same as with `app`](#renaming-the-target). However, for `binary` the select cases don’t apply as rigidly. It’s fine to take extra liberties with `target:` to be consistent with other command-line tools, like [changing case](https://github.com/Homebrew/homebrew-cask/blob/aa461148bbb5119af26b82cccf5003e2b4e50d95/Casks/g/godot.rb#L19), [removing an extension](https://github.com/Homebrew/homebrew-cask/blob/aa461148bbb5119af26b82cccf5003e2b4e50d95/Casks/f/filebot.rb#L19), or [cleaning up the name](https://github.com/Homebrew/homebrew-cask/blob/aa461148bbb5119af26b82cccf5003e2b4e50d95/Casks/f/fig.rb#L21).
|
Behaviour and usage of `target:` is [the same as with `app`](#renaming-the-target). However, for `binary` the select cases don’t apply as rigidly. It’s fine to take extra liberties with `target:` to be consistent with other command-line tools, like [changing case](https://github.com/Homebrew/homebrew-cask/blob/aa461148bbb5119af26b82cccf5003e2b4e50d95/Casks/g/godot.rb#L19), [removing an extension](https://github.com/Homebrew/homebrew-cask/blob/aa461148bbb5119af26b82cccf5003e2b4e50d95/Casks/f/filebot.rb#L19), or [cleaning up the name](https://github.com/Homebrew/homebrew-cask/blob/aa461148bbb5119af26b82cccf5003e2b4e50d95/Casks/f/fig.rb#L21).
|
||||||
|
|
||||||
|
### Stanza: `rename`
|
||||||
|
|
||||||
|
The `rename` stanza provides a convenience method to rename files to provide more practical access to them.
|
||||||
|
This stanza should be used sparingly, and is reserved for scenarios where a the path of a file/directory is impossible to pre-determine.
|
||||||
|
|
||||||
|
The example below can be used when the `pkg` path has a value such as timestamp that can't be detected without extracting the archive it is distributed within.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# Upstream provides a `pkg` - "foobar-<timestamp>.pkg"
|
||||||
|
rename "foobar-*.pkg", "foobar.pkg"
|
||||||
|
```
|
||||||
|
|
||||||
### Stanza: `caveats`
|
### Stanza: `caveats`
|
||||||
|
|
||||||
Sometimes there are particularities with the installation of a piece of software that cannot or should not be handled programmatically by Homebrew Cask. In those instances, `caveats` is the way to inform the user. Information in `caveats` is displayed when a cask is invoked with either `install` or `info`.
|
Sometimes there are particularities with the installation of a piece of software that cannot or should not be handled programmatically by Homebrew Cask. In those instances, `caveats` is the way to inform the user. Information in `caveats` is displayed when a cask is invoked with either `install` or `info`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user