Merge pull request #4656 from amyspark/com-apple-quarantine
Enable quarantining of Homebrew-Cask's downloads
This commit is contained in:
commit
47d3bbee1c
@ -65,11 +65,8 @@ module Hbc
|
|||||||
ohai "Backing #{self.class.english_name} '#{target.basename}' up to '#{source}'."
|
ohai "Backing #{self.class.english_name} '#{target.basename}' up to '#{source}'."
|
||||||
source.dirname.mkpath
|
source.dirname.mkpath
|
||||||
|
|
||||||
if target.parent.writable?
|
# We need to preserve extended attributes between copies.
|
||||||
FileUtils.cp_r(target, source)
|
command.run!("/bin/cp", args: ["-pR", target, source], sudo: !target.parent.writable?)
|
||||||
else
|
|
||||||
command.run!("/bin/cp", args: ["-r", target, source], sudo: true)
|
|
||||||
end
|
|
||||||
|
|
||||||
delete(target, force: force, command: command, **options)
|
delete(target, force: force, command: command, **options)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,15 +2,16 @@ require "hbc/download"
|
|||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
class Auditor
|
class Auditor
|
||||||
def self.audit(cask, audit_download: false, check_token_conflicts: false, commit_range: nil)
|
def self.audit(cask, audit_download: false, check_token_conflicts: false, quarantine: true, commit_range: nil)
|
||||||
new(cask, audit_download, check_token_conflicts, commit_range).audit
|
new(cask, audit_download, check_token_conflicts, quarantine, commit_range).audit
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :cask, :commit_range
|
attr_reader :cask, :commit_range
|
||||||
|
|
||||||
def initialize(cask, audit_download, check_token_conflicts, commit_range)
|
def initialize(cask, audit_download, check_token_conflicts, quarantine, commit_range)
|
||||||
@cask = cask
|
@cask = cask
|
||||||
@audit_download = audit_download
|
@audit_download = audit_download
|
||||||
|
@quarantine = quarantine
|
||||||
@commit_range = commit_range
|
@commit_range = commit_range
|
||||||
@check_token_conflicts = check_token_conflicts
|
@check_token_conflicts = check_token_conflicts
|
||||||
end
|
end
|
||||||
@ -19,6 +20,10 @@ module Hbc
|
|||||||
@audit_download
|
@audit_download
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def quarantine?
|
||||||
|
@quarantine
|
||||||
|
end
|
||||||
|
|
||||||
def check_token_conflicts?
|
def check_token_conflicts?
|
||||||
@check_token_conflicts
|
@check_token_conflicts
|
||||||
end
|
end
|
||||||
@ -52,7 +57,7 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def audit_cask_instance(cask)
|
def audit_cask_instance(cask)
|
||||||
download = audit_download? && Download.new(cask)
|
download = audit_download? && Download.new(cask, quarantine: quarantine?)
|
||||||
audit = Audit.new(cask, download: download,
|
audit = Audit.new(cask, download: download,
|
||||||
check_token_conflicts: check_token_conflicts?,
|
check_token_conflicts: check_token_conflicts?,
|
||||||
commit_range: commit_range)
|
commit_range: commit_range)
|
||||||
|
|||||||
@ -12,6 +12,7 @@ module Hbc
|
|||||||
option "--verbose", :verbose, false
|
option "--verbose", :verbose, false
|
||||||
option "--outdated", :outdated_only, false
|
option "--outdated", :outdated_only, false
|
||||||
option "--require-sha", :require_sha, false
|
option "--require-sha", :require_sha, false
|
||||||
|
option "--[no-]quarantine", :quarantine, true
|
||||||
|
|
||||||
def self.command_name
|
def self.command_name
|
||||||
@command_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase
|
@command_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase
|
||||||
|
|||||||
@ -18,7 +18,9 @@ module Hbc
|
|||||||
|
|
||||||
def audit(cask)
|
def audit(cask)
|
||||||
odebug "Auditing Cask #{cask}"
|
odebug "Auditing Cask #{cask}"
|
||||||
Auditor.audit(cask, audit_download: download?, check_token_conflicts: token_conflicts?)
|
Auditor.audit(cask, audit_download: download?,
|
||||||
|
check_token_conflicts: token_conflicts?,
|
||||||
|
quarantine: quarantine?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -14,7 +14,7 @@ module Hbc
|
|||||||
casks.each do |cask|
|
casks.each do |cask|
|
||||||
Installer.print_caveats(cask)
|
Installer.print_caveats(cask)
|
||||||
ohai "Downloading external files for Cask #{cask}"
|
ohai "Downloading external files for Cask #{cask}"
|
||||||
downloaded_path = Download.new(cask, force: force?).perform
|
downloaded_path = Download.new(cask, force: force?, quarantine: quarantine?).perform
|
||||||
Verify.all(cask, downloaded_path)
|
Verify.all(cask, downloaded_path)
|
||||||
ohai "Success! Downloaded to -> #{downloaded_path}"
|
ohai "Success! Downloaded to -> #{downloaded_path}"
|
||||||
end
|
end
|
||||||
|
|||||||
@ -17,7 +17,8 @@ module Hbc
|
|||||||
verbose: verbose?,
|
verbose: verbose?,
|
||||||
force: force?,
|
force: force?,
|
||||||
skip_cask_deps: skip_cask_deps?,
|
skip_cask_deps: skip_cask_deps?,
|
||||||
require_sha: require_sha?).install
|
require_sha: require_sha?,
|
||||||
|
quarantine: quarantine?).install
|
||||||
rescue CaskAlreadyInstalledError => e
|
rescue CaskAlreadyInstalledError => e
|
||||||
opoo e.message
|
opoo e.message
|
||||||
end
|
end
|
||||||
|
|||||||
@ -7,7 +7,8 @@ module Hbc
|
|||||||
verbose: verbose?,
|
verbose: verbose?,
|
||||||
force: force?,
|
force: force?,
|
||||||
skip_cask_deps: skip_cask_deps?,
|
skip_cask_deps: skip_cask_deps?,
|
||||||
require_sha: require_sha?).reinstall
|
require_sha: require_sha?,
|
||||||
|
quarantine: quarantine?).reinstall
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,11 @@ module Hbc
|
|||||||
|
|
||||||
old_cask = CaskLoader.load(old_cask.installed_caskfile)
|
old_cask = CaskLoader.load(old_cask.installed_caskfile)
|
||||||
|
|
||||||
old_cask_installer = Installer.new(old_cask, binaries: binaries?, verbose: verbose?, force: force?, upgrade: true)
|
old_cask_installer =
|
||||||
|
Installer.new(old_cask, binaries: binaries?,
|
||||||
|
verbose: verbose?,
|
||||||
|
force: force?,
|
||||||
|
upgrade: true)
|
||||||
|
|
||||||
new_cask = CaskLoader.load(old_cask.to_s)
|
new_cask = CaskLoader.load(old_cask.to_s)
|
||||||
|
|
||||||
@ -46,7 +50,8 @@ module Hbc
|
|||||||
force: force?,
|
force: force?,
|
||||||
skip_cask_deps: skip_cask_deps?,
|
skip_cask_deps: skip_cask_deps?,
|
||||||
require_sha: require_sha?,
|
require_sha: require_sha?,
|
||||||
upgrade: true)
|
upgrade: true,
|
||||||
|
quarantine: quarantine?)
|
||||||
|
|
||||||
started_upgrade = false
|
started_upgrade = false
|
||||||
new_artifacts_installed = false
|
new_artifacts_installed = false
|
||||||
|
|||||||
@ -1,18 +1,21 @@
|
|||||||
require "fileutils"
|
require "fileutils"
|
||||||
|
require "hbc/quarantine"
|
||||||
require "hbc/verify"
|
require "hbc/verify"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
class Download
|
class Download
|
||||||
attr_reader :cask
|
attr_reader :cask
|
||||||
|
|
||||||
def initialize(cask, force: false)
|
def initialize(cask, force: false, quarantine: true)
|
||||||
@cask = cask
|
@cask = cask
|
||||||
@force = force
|
@force = force
|
||||||
|
@quarantine = quarantine
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform
|
def perform
|
||||||
clear_cache
|
clear_cache
|
||||||
fetch
|
fetch
|
||||||
|
quarantine
|
||||||
downloaded_path
|
downloaded_path
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -38,5 +41,13 @@ module Hbc
|
|||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
raise CaskError, "Download failed on Cask '#{cask}' with message: #{e}"
|
raise CaskError, "Download failed on Cask '#{cask}' with message: #{e}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def quarantine
|
||||||
|
return unless @quarantine
|
||||||
|
return unless Quarantine.available?
|
||||||
|
return if Quarantine.detect(@downloaded_path)
|
||||||
|
|
||||||
|
Quarantine.cask(cask: @cask, download_path: @downloaded_path)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -32,13 +32,13 @@ module Hbc
|
|||||||
|
|
||||||
class CaskUnavailableError < AbstractCaskErrorWithToken
|
class CaskUnavailableError < AbstractCaskErrorWithToken
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' is unavailable" << (reason.empty? ? "." : ": #{reason}")
|
"Cask '#{token}' is unavailable#{reason.empty? ? "." : ": #{reason}"}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskUnreadableError < CaskUnavailableError
|
class CaskUnreadableError < CaskUnavailableError
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' is unreadable" << (reason.empty? ? "." : ": #{reason}")
|
"Cask '#{token}' is unreadable#{reason.empty? ? "." : ": #{reason}"}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ module Hbc
|
|||||||
|
|
||||||
class CaskCyclicDependencyError < AbstractCaskErrorWithToken
|
class CaskCyclicDependencyError < AbstractCaskErrorWithToken
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' includes cyclic dependencies on other Casks" << (reason.empty? ? "." : ": #{reason}")
|
"Cask '#{token}' includes cyclic dependencies on other Casks#{reason.empty? ? "." : ": #{reason}"}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ module Hbc
|
|||||||
|
|
||||||
class CaskInvalidError < AbstractCaskErrorWithToken
|
class CaskInvalidError < AbstractCaskErrorWithToken
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' definition is invalid" << (reason.empty? ? "." : ": #{reason}")
|
"Cask '#{token}' definition is invalid#{reason.empty? ? "." : ": #{reason}"}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -149,4 +149,39 @@ module Hbc
|
|||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class CaskQuarantineError < CaskError
|
||||||
|
attr_reader :path, :reason
|
||||||
|
|
||||||
|
def initialize(path, reason)
|
||||||
|
@path = path
|
||||||
|
@reason = reason
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
s = "Failed to quarantine #{path}."
|
||||||
|
|
||||||
|
unless reason.empty?
|
||||||
|
s << " Here's the reason:\n"
|
||||||
|
s << Formatter.error(reason)
|
||||||
|
s << "\n" unless reason.end_with?("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class CaskQuarantinePropagationError < CaskQuarantineError
|
||||||
|
def to_s
|
||||||
|
s = "Failed to quarantine one or more files within #{path}."
|
||||||
|
|
||||||
|
unless reason.empty?
|
||||||
|
s << " Here's the reason:\n"
|
||||||
|
s << Formatter.error(reason)
|
||||||
|
s << "\n" unless reason.end_with?("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
s
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -7,6 +7,7 @@ require "hbc/cask_dependencies"
|
|||||||
require "hbc/download"
|
require "hbc/download"
|
||||||
require "hbc/staged"
|
require "hbc/staged"
|
||||||
require "hbc/verify"
|
require "hbc/verify"
|
||||||
|
require "hbc/quarantine"
|
||||||
|
|
||||||
require "cgi"
|
require "cgi"
|
||||||
|
|
||||||
@ -23,7 +24,10 @@ module Hbc
|
|||||||
|
|
||||||
PERSISTENT_METADATA_SUBDIRS = ["gpg"].freeze
|
PERSISTENT_METADATA_SUBDIRS = ["gpg"].freeze
|
||||||
|
|
||||||
def initialize(cask, command: SystemCommand, force: false, skip_cask_deps: false, binaries: true, verbose: false, require_sha: false, upgrade: false, installed_as_dependency: false)
|
def initialize(cask, command: SystemCommand, force: false,
|
||||||
|
skip_cask_deps: false, binaries: true, verbose: false,
|
||||||
|
require_sha: false, upgrade: false,
|
||||||
|
installed_as_dependency: false, quarantine: true)
|
||||||
@cask = cask
|
@cask = cask
|
||||||
@command = command
|
@command = command
|
||||||
@force = force
|
@force = force
|
||||||
@ -34,9 +38,12 @@ module Hbc
|
|||||||
@reinstall = false
|
@reinstall = false
|
||||||
@upgrade = upgrade
|
@upgrade = upgrade
|
||||||
@installed_as_dependency = installed_as_dependency
|
@installed_as_dependency = installed_as_dependency
|
||||||
|
@quarantine = quarantine
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_predicate :binaries?, :force?, :skip_cask_deps?, :require_sha?, :upgrade?, :verbose?, :installed_as_dependency?
|
attr_predicate :binaries?, :force?, :skip_cask_deps?, :require_sha?,
|
||||||
|
:upgrade?, :verbose?, :installed_as_dependency?,
|
||||||
|
:quarantine?
|
||||||
|
|
||||||
def self.print_caveats(cask)
|
def self.print_caveats(cask)
|
||||||
odebug "Printing caveats"
|
odebug "Printing caveats"
|
||||||
@ -86,6 +93,7 @@ module Hbc
|
|||||||
uninstall_existing_cask if @reinstall
|
uninstall_existing_cask if @reinstall
|
||||||
|
|
||||||
oh1 "Installing Cask #{Formatter.identifier(@cask)}"
|
oh1 "Installing Cask #{Formatter.identifier(@cask)}"
|
||||||
|
opoo "macOS's Gatekeeper has been disabled for this Cask" unless quarantine?
|
||||||
stage
|
stage
|
||||||
install_artifacts
|
install_artifacts
|
||||||
enable_accessibility_access
|
enable_accessibility_access
|
||||||
@ -137,7 +145,7 @@ module Hbc
|
|||||||
|
|
||||||
def download
|
def download
|
||||||
odebug "Downloading"
|
odebug "Downloading"
|
||||||
@downloaded_path = Download.new(@cask, force: false).perform
|
@downloaded_path = Download.new(@cask, force: false, quarantine: quarantine?).perform
|
||||||
odebug "Downloaded to -> #{@downloaded_path}"
|
odebug "Downloaded to -> #{@downloaded_path}"
|
||||||
@downloaded_path
|
@downloaded_path
|
||||||
end
|
end
|
||||||
@ -176,6 +184,11 @@ module Hbc
|
|||||||
else
|
else
|
||||||
primary_container.extract_nestedly(to: @cask.staged_path, basename: basename, verbose: verbose?)
|
primary_container.extract_nestedly(to: @cask.staged_path, basename: basename, verbose: verbose?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return unless quarantine?
|
||||||
|
return unless Quarantine.available?
|
||||||
|
|
||||||
|
Quarantine.propagate(from: @downloaded_path, to: @cask.staged_path, command: @command)
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_artifacts
|
def install_artifacts
|
||||||
|
|||||||
80
Library/Homebrew/cask/lib/hbc/quarantine.rb
Normal file
80
Library/Homebrew/cask/lib/hbc/quarantine.rb
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
require "development_tools"
|
||||||
|
module Hbc
|
||||||
|
module Quarantine
|
||||||
|
module_function
|
||||||
|
|
||||||
|
QUARANTINE_ATTRIBUTE = "com.apple.quarantine".freeze
|
||||||
|
|
||||||
|
QUARANTINE_SCRIPT = (HOMEBREW_LIBRARY_PATH/"cask/lib/hbc/utils/quarantine.swift").freeze
|
||||||
|
|
||||||
|
# @private
|
||||||
|
def swift
|
||||||
|
@swift ||= DevelopmentTools.locate("swift")
|
||||||
|
end
|
||||||
|
|
||||||
|
def available?
|
||||||
|
status = !swift.nil?
|
||||||
|
odebug "Quarantine is #{status ? "available" : "not available"}."
|
||||||
|
status
|
||||||
|
end
|
||||||
|
|
||||||
|
def detect(file)
|
||||||
|
return if file.nil?
|
||||||
|
|
||||||
|
odebug "Verifying Gatekeeper status of #{file}"
|
||||||
|
|
||||||
|
quarantine_status = !status(file).empty?
|
||||||
|
|
||||||
|
odebug "#{file} is #{quarantine_status ? "quarantined" : "not quarantined"}"
|
||||||
|
|
||||||
|
quarantine_status
|
||||||
|
end
|
||||||
|
|
||||||
|
def status(file, command: SystemCommand)
|
||||||
|
command.run("/usr/bin/xattr",
|
||||||
|
args: ["-p", QUARANTINE_ATTRIBUTE, file],
|
||||||
|
print_stderr: false).stdout.rstrip
|
||||||
|
end
|
||||||
|
|
||||||
|
def cask(cask: nil, download_path: nil, command: SystemCommand)
|
||||||
|
return if cask.nil? || download_path.nil?
|
||||||
|
|
||||||
|
odebug "Quarantining #{download_path}"
|
||||||
|
|
||||||
|
quarantiner = command.run(swift,
|
||||||
|
args: [
|
||||||
|
QUARANTINE_SCRIPT,
|
||||||
|
download_path,
|
||||||
|
cask.url.to_s,
|
||||||
|
cask.homepage.to_s,
|
||||||
|
])
|
||||||
|
|
||||||
|
return if quarantiner.success?
|
||||||
|
|
||||||
|
case quarantiner.exit_status
|
||||||
|
when 2
|
||||||
|
raise CaskQuarantineError.new(download_path, "Insufficient parameters")
|
||||||
|
else
|
||||||
|
raise CaskQuarantineError.new(download_path, quarantiner.stderr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def propagate(from: nil, to: nil, command: SystemCommand)
|
||||||
|
return if from.nil? || to.nil?
|
||||||
|
|
||||||
|
raise CaskError, "#{from} was not quarantined properly." unless detect(from)
|
||||||
|
|
||||||
|
odebug "Propagating quarantine from #{from} to #{to}"
|
||||||
|
|
||||||
|
quarantine_status = status(from, command: command)
|
||||||
|
|
||||||
|
quarantiner = command.run("/usr/bin/xattr",
|
||||||
|
args: ["-w", "-r", QUARANTINE_ATTRIBUTE, quarantine_status, to],
|
||||||
|
print_stderr: false)
|
||||||
|
|
||||||
|
return if quarantiner.success?
|
||||||
|
|
||||||
|
raise CaskQuarantinePropagationError.new(to, quarantiner.stderr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
42
Library/Homebrew/cask/lib/hbc/utils/quarantine.swift
Normal file
42
Library/Homebrew/cask/lib/hbc/utils/quarantine.swift
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/swift
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct swifterr: TextOutputStream {
|
||||||
|
public static var stream = swifterr()
|
||||||
|
mutating func write(_ string: String) { fputs(string, stderr) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CommandLine.arguments.count < 4) {
|
||||||
|
exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataLocationUrl: NSURL = NSURL.init(fileURLWithPath: CommandLine.arguments[1])
|
||||||
|
|
||||||
|
var errorBag: NSError?
|
||||||
|
|
||||||
|
let quarantineProperties: [String: Any] = [
|
||||||
|
kLSQuarantineAgentNameKey as String: "Homebrew-Cask",
|
||||||
|
kLSQuarantineTypeKey as String: kLSQuarantineTypeWebDownload,
|
||||||
|
kLSQuarantineDataURLKey as String: CommandLine.arguments[2],
|
||||||
|
kLSQuarantineOriginURLKey as String: CommandLine.arguments[3]
|
||||||
|
]
|
||||||
|
|
||||||
|
if (dataLocationUrl.checkResourceIsReachableAndReturnError(&errorBag)) {
|
||||||
|
do {
|
||||||
|
try dataLocationUrl.setResourceValue(
|
||||||
|
quarantineProperties as NSDictionary,
|
||||||
|
forKey: URLResourceKey.quarantinePropertiesKey
|
||||||
|
)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
print(error.localizedDescription, to: &swifterr.stream)
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print(errorBag!.localizedDescription, to: &swifterr.stream)
|
||||||
|
exit(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0)
|
||||||
@ -19,7 +19,7 @@ names, and other aspects of this manual are still subject to change.
|
|||||||
|
|
||||||
## FREQUENTLY USED COMMANDS
|
## FREQUENTLY USED COMMANDS
|
||||||
|
|
||||||
* `install` [--force] [--skip-cask-deps] [--require-sha] [--language=<iso-language>[,<iso-language> ... ]] <token> [ <token> ... ]:
|
* `install` [--force] [--skip-cask-deps] [--require-sha] [--no-quarantine] [--language=<iso-language>[,<iso-language> ... ]] <token> [ <token> ... ]:
|
||||||
Install Cask identified by <token>.
|
Install Cask identified by <token>.
|
||||||
|
|
||||||
* `uninstall` [--force] <token> [ <token> ... ]:
|
* `uninstall` [--force] <token> [ <token> ... ]:
|
||||||
@ -56,10 +56,11 @@ names, and other aspects of this manual are still subject to change.
|
|||||||
* `edit` <token>:
|
* `edit` <token>:
|
||||||
Open the given Cask definition file for editing.
|
Open the given Cask definition file for editing.
|
||||||
|
|
||||||
* `fetch` [--force] <token> [ <token> ... ]:
|
* `fetch` [--force] [--no-quarantine] <token> [ <token> ... ]:
|
||||||
Download remote application files for the given Cask to the local
|
Download remote application files for the given Cask to the local
|
||||||
cache. With `--force`, force re-download even if the files are already
|
cache. With `--force`, force re-download even if the files are already
|
||||||
cached.
|
cached. `--no-quarantine` will prevent Gatekeeper from
|
||||||
|
enforcing its security restrictions on the Cask.
|
||||||
|
|
||||||
* `home` or `homepage` [ <token> ... ]:
|
* `home` or `homepage` [ <token> ... ]:
|
||||||
Display the homepage associated with a given Cask in a browser.
|
Display the homepage associated with a given Cask in a browser.
|
||||||
@ -69,11 +70,12 @@ names, and other aspects of this manual are still subject to change.
|
|||||||
* `info` or `abv` <token> [ <token> ... ]:
|
* `info` or `abv` <token> [ <token> ... ]:
|
||||||
Display information about the given Cask.
|
Display information about the given Cask.
|
||||||
|
|
||||||
* `install` [--force] [--skip-cask-deps] [--require-sha] <token> [ <token> ... ]:
|
* `install` [--force] [--skip-cask-deps] [--require-sha] [--no-quarantine] <token> [ <token> ... ]:
|
||||||
Install the given Cask. With `--force`, re-install even if the Cask
|
Install the given Cask. With `--force`, re-install even if the Cask
|
||||||
appears to be already present. With `--skip-cask-deps`, skip any Cask
|
appears to be already present. With `--skip-cask-deps`, skip any Cask
|
||||||
dependencies. `--require-sha` will abort installation if the Cask does not
|
dependencies. `--require-sha` will abort installation if the Cask does not
|
||||||
have a checksum defined.
|
have a checksum defined. `--no-quarantine` will prevent Gatekeeper from
|
||||||
|
enforcing its security restrictions on the Cask.
|
||||||
|
|
||||||
<token> is usually the ID of a Cask,
|
<token> is usually the ID of a Cask,
|
||||||
but see [OTHER WAYS TO SPECIFY A CASK][] for variations.
|
but see [OTHER WAYS TO SPECIFY A CASK][] for variations.
|
||||||
@ -97,7 +99,7 @@ names, and other aspects of this manual are still subject to change.
|
|||||||
`--verbose` forces the display of the outdated and latest version.<br>
|
`--verbose` forces the display of the outdated and latest version.<br>
|
||||||
`--quiet` suppresses the display of versions.
|
`--quiet` suppresses the display of versions.
|
||||||
|
|
||||||
* `reinstall` <token> [ <token> ... ]:
|
* `reinstall` [--no-quarantine] <token> [ <token> ... ]:
|
||||||
Reinstall the given Cask.
|
Reinstall the given Cask.
|
||||||
|
|
||||||
* `search` or `-S` [<text> | /<regexp>/]:
|
* `search` or `-S` [<text> | /<regexp>/]:
|
||||||
@ -162,6 +164,10 @@ in a future version.
|
|||||||
* `--require-sha`:
|
* `--require-sha`:
|
||||||
Abort Cask installation if the Cask does not have a checksum defined.
|
Abort Cask installation if the Cask does not have a checksum defined.
|
||||||
|
|
||||||
|
* `--no-quarantine`:
|
||||||
|
Prevent Gatekeeper from enforcing its security restrictions on the Cask.
|
||||||
|
This will let you run it straightaway.
|
||||||
|
|
||||||
* `--verbose`:
|
* `--verbose`:
|
||||||
Give additional feedback during installation.
|
Give additional feedback during installation.
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ describe Hbc::CLI::Audit, :cask do
|
|||||||
expect(Hbc::CaskLoader).to receive(:load).with(cask_token).and_return(cask)
|
expect(Hbc::CaskLoader).to receive(:load).with(cask_token).and_return(cask)
|
||||||
|
|
||||||
expect(Hbc::Auditor).to receive(:audit)
|
expect(Hbc::Auditor).to receive(:audit)
|
||||||
.with(cask, audit_download: false, check_token_conflicts: false)
|
.with(cask, audit_download: false, check_token_conflicts: false, quarantine: true)
|
||||||
.and_return(true)
|
.and_return(true)
|
||||||
|
|
||||||
described_class.run(cask_token)
|
described_class.run(cask_token)
|
||||||
@ -30,7 +30,7 @@ describe Hbc::CLI::Audit, :cask do
|
|||||||
it "does not download the Cask per default" do
|
it "does not download the Cask per default" do
|
||||||
allow(Hbc::CaskLoader).to receive(:load).and_return(cask)
|
allow(Hbc::CaskLoader).to receive(:load).and_return(cask)
|
||||||
expect(Hbc::Auditor).to receive(:audit)
|
expect(Hbc::Auditor).to receive(:audit)
|
||||||
.with(cask, audit_download: false, check_token_conflicts: false)
|
.with(cask, audit_download: false, check_token_conflicts: false, quarantine: true)
|
||||||
.and_return(true)
|
.and_return(true)
|
||||||
|
|
||||||
described_class.run("casktoken")
|
described_class.run("casktoken")
|
||||||
@ -39,7 +39,7 @@ describe Hbc::CLI::Audit, :cask do
|
|||||||
it "download a Cask if --download flag is set" do
|
it "download a Cask if --download flag is set" do
|
||||||
allow(Hbc::CaskLoader).to receive(:load).and_return(cask)
|
allow(Hbc::CaskLoader).to receive(:load).and_return(cask)
|
||||||
expect(Hbc::Auditor).to receive(:audit)
|
expect(Hbc::Auditor).to receive(:audit)
|
||||||
.with(cask, audit_download: true, check_token_conflicts: false)
|
.with(cask, audit_download: true, check_token_conflicts: false, quarantine: true)
|
||||||
.and_return(true)
|
.and_return(true)
|
||||||
|
|
||||||
described_class.run("casktoken", "--download")
|
described_class.run("casktoken", "--download")
|
||||||
@ -50,7 +50,7 @@ describe Hbc::CLI::Audit, :cask do
|
|||||||
it "does not check for token conflicts per default" do
|
it "does not check for token conflicts per default" do
|
||||||
allow(Hbc::CaskLoader).to receive(:load).and_return(cask)
|
allow(Hbc::CaskLoader).to receive(:load).and_return(cask)
|
||||||
expect(Hbc::Auditor).to receive(:audit)
|
expect(Hbc::Auditor).to receive(:audit)
|
||||||
.with(cask, audit_download: false, check_token_conflicts: false)
|
.with(cask, audit_download: false, check_token_conflicts: false, quarantine: true)
|
||||||
.and_return(true)
|
.and_return(true)
|
||||||
|
|
||||||
described_class.run("casktoken")
|
described_class.run("casktoken")
|
||||||
@ -59,7 +59,7 @@ describe Hbc::CLI::Audit, :cask do
|
|||||||
it "checks for token conflicts if --token-conflicts flag is set" do
|
it "checks for token conflicts if --token-conflicts flag is set" do
|
||||||
allow(Hbc::CaskLoader).to receive(:load).and_return(cask)
|
allow(Hbc::CaskLoader).to receive(:load).and_return(cask)
|
||||||
expect(Hbc::Auditor).to receive(:audit)
|
expect(Hbc::Auditor).to receive(:audit)
|
||||||
.with(cask, audit_download: false, check_token_conflicts: true)
|
.with(cask, audit_download: false, check_token_conflicts: true, quarantine: true)
|
||||||
.and_return(true)
|
.and_return(true)
|
||||||
|
|
||||||
described_class.run("casktoken", "--token-conflicts")
|
described_class.run("casktoken", "--token-conflicts")
|
||||||
|
|||||||
@ -51,7 +51,7 @@ describe Hbc::CLI::Info, :cask do
|
|||||||
Not installed
|
Not installed
|
||||||
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/local-transmission.rb
|
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/local-transmission.rb
|
||||||
==> Name
|
==> Name
|
||||||
None
|
Transmission
|
||||||
==> Artifacts
|
==> Artifacts
|
||||||
Transmission.app (App)
|
Transmission.app (App)
|
||||||
EOS
|
EOS
|
||||||
|
|||||||
213
Library/Homebrew/test/cask/cli/quarantine_spec.rb
Normal file
213
Library/Homebrew/test/cask/cli/quarantine_spec.rb
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
describe Hbc::Quarantine, :cask do
|
||||||
|
matcher :be_quarantined do
|
||||||
|
match do |path|
|
||||||
|
expect(
|
||||||
|
described_class.detect(path),
|
||||||
|
).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "by default" do
|
||||||
|
it "quarantines a nice fresh Cask" do
|
||||||
|
Hbc::CLI::Install.run("local-transmission")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("local-transmission")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::Config.global.appdir.join("Transmission.app"),
|
||||||
|
).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines Cask fetches" do
|
||||||
|
Hbc::CLI::Fetch.run("local-transmission")
|
||||||
|
local_transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
|
||||||
|
cached_location = Hbc::Download.new(local_transmission, force: false, quarantine: false).perform
|
||||||
|
|
||||||
|
expect(cached_location).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines Cask audits" do
|
||||||
|
Hbc::CLI::Audit.run("local-transmission", "--download")
|
||||||
|
|
||||||
|
local_transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
|
||||||
|
cached_location = Hbc::Download.new(local_transmission, force: false, quarantine: false).perform
|
||||||
|
|
||||||
|
expect(cached_location).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines dmg-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-dmg")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-dmg")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines tar-gz-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-tar-gz")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-tar-gz")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines xar-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-xar")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-xar")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines pure bzip2-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-bzip2")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-bzip2")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines pure gzip-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-gzip")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-gzip")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines the pkg in naked-pkg-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-pkg")
|
||||||
|
|
||||||
|
naked_pkg = Hbc::CaskLoader.load(cask_path("container-pkg"))
|
||||||
|
|
||||||
|
expect(naked_pkg).to be_installed
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::Caskroom.path.join("container-pkg", naked_pkg.version, "container.pkg"),
|
||||||
|
).to be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "quarantines a nested container" do
|
||||||
|
Hbc::CLI::Install.run("nested-app")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("nested-app")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("MyNestedApp.app")).to be_quarantined
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when disabled" do
|
||||||
|
it "does not quarantine even a nice, fresh Cask" do
|
||||||
|
Hbc::CLI::Install.run("local-transmission", "--no-quarantine")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("local-transmission")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("Transmission.app")).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine Cask fetches" do
|
||||||
|
Hbc::CLI::Fetch.run("local-transmission", "--no-quarantine")
|
||||||
|
local_transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
|
||||||
|
cached_location = Hbc::Download.new(local_transmission, force: false, quarantine: false).perform
|
||||||
|
|
||||||
|
expect(cached_location).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine dmg-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-dmg", "--no-quarantine")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-dmg")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine tar-gz-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-tar-gz", "--no-quarantine")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-tar-gz")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine xar-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-xar", "--no-quarantine")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-xar")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine pure bzip2-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-bzip2", "--no-quarantine")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-bzip2")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine pure gzip-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-gzip", "--no-quarantine")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("container-gzip")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("container")).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine the pkg in naked-pkg-based Casks" do
|
||||||
|
Hbc::CLI::Install.run("container-pkg", "--no-quarantine")
|
||||||
|
|
||||||
|
naked_pkg = Hbc::CaskLoader.load(cask_path("container-pkg"))
|
||||||
|
|
||||||
|
expect(naked_pkg).to be_installed
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::Caskroom.path.join("container-pkg", naked_pkg.version, "container.pkg"),
|
||||||
|
).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine a nested container" do
|
||||||
|
Hbc::CLI::Install.run("nested-app", "--no-quarantine")
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Hbc::CaskLoader.load(cask_path("nested-app")),
|
||||||
|
).to be_installed
|
||||||
|
|
||||||
|
expect(Hbc::Config.global.appdir.join("MyNestedApp.app")).to_not be_quarantined
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not quarantine Cask audits" do
|
||||||
|
Hbc::CLI::Audit.run("local-transmission", "--download", "--no-quarantine")
|
||||||
|
|
||||||
|
local_transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
|
||||||
|
cached_location = Hbc::Download.new(local_transmission, force: false, quarantine: false).perform
|
||||||
|
|
||||||
|
expect(cached_location).to_not be_quarantined
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,4 +1,5 @@
|
|||||||
cask 'local-transmission' do
|
cask 'local-transmission' do
|
||||||
|
name 'Transmission'
|
||||||
version '2.61'
|
version '2.61'
|
||||||
sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68'
|
sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68'
|
||||||
|
|
||||||
|
|||||||
@ -90,7 +90,7 @@ module UnpackStrategy
|
|||||||
args: ["--bom", bomfile.path, "--", path, unpack_dir],
|
args: ["--bom", bomfile.path, "--", path, unpack_dir],
|
||||||
verbose: verbose
|
verbose: verbose
|
||||||
|
|
||||||
FileUtils.chmod "u+w", Pathname.glob(unpack_dir/"**/*").reject(&:symlink?)
|
FileUtils.chmod "u+w", Pathname.glob(unpack_dir/"**/*", File::FNM_DOTMATCH).reject(&:symlink?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -18,7 +18,7 @@ Homebrew\-Cask works robustly enough that we welcome new users, but the project
|
|||||||
.SH "FREQUENTLY USED COMMANDS"
|
.SH "FREQUENTLY USED COMMANDS"
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fBinstall\fR [\-\-force] [\-\-skip\-cask\-deps] [\-\-require\-sha] [\-\-language=\fIiso\-language\fR[,\fIiso\-language\fR \.\.\. ]] \fItoken\fR [ \fItoken\fR \.\.\. ]
|
\fBinstall\fR [\-\-force] [\-\-skip\-cask\-deps] [\-\-require\-sha] [\-\-no\-quarantine] [\-\-language=\fIiso\-language\fR[,\fIiso\-language\fR \.\.\. ]] \fItoken\fR [ \fItoken\fR \.\.\. ]
|
||||||
Install Cask identified by \fItoken\fR\.
|
Install Cask identified by \fItoken\fR\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
@ -59,8 +59,8 @@ Check for configuration issues\. Can be useful to upload as a gist for developer
|
|||||||
Open the given Cask definition file for editing\.
|
Open the given Cask definition file for editing\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fBfetch\fR [\-\-force] \fItoken\fR [ \fItoken\fR \.\.\. ]
|
\fBfetch\fR [\-\-force] [\-\-no\-quarantine] \fItoken\fR [ \fItoken\fR \.\.\. ]
|
||||||
Download remote application files for the given Cask to the local cache\. With \fB\-\-force\fR, force re\-download even if the files are already cached\.
|
Download remote application files for the given Cask to the local cache\. With \fB\-\-force\fR, force re\-download even if the files are already cached\. \fB\-\-no\-quarantine\fR will prevent Gatekeeper from enforcing its security restrictions on the Cask\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fBhome\fR or \fBhomepage\fR [ \fItoken\fR \.\.\. ]
|
\fBhome\fR or \fBhomepage\fR [ \fItoken\fR \.\.\. ]
|
||||||
@ -74,8 +74,8 @@ With no arguments, display the project page \fIhttps://caskroom\.github\.io/\fR\
|
|||||||
Display information about the given Cask\.
|
Display information about the given Cask\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fBinstall\fR [\-\-force] [\-\-skip\-cask\-deps] [\-\-require\-sha] \fItoken\fR [ \fItoken\fR \.\.\. ]
|
\fBinstall\fR [\-\-force] [\-\-skip\-cask\-deps] [\-\-require\-sha] [\-\-no\-quarantine] \fItoken\fR [ \fItoken\fR \.\.\. ]
|
||||||
Install the given Cask\. With \fB\-\-force\fR, re\-install even if the Cask appears to be already present\. With \fB\-\-skip\-cask\-deps\fR, skip any Cask dependencies\. \fB\-\-require\-sha\fR will abort installation if the Cask does not have a checksum defined\.
|
Install the given Cask\. With \fB\-\-force\fR, re\-install even if the Cask appears to be already present\. With \fB\-\-skip\-cask\-deps\fR, skip any Cask dependencies\. \fB\-\-require\-sha\fR will abort installation if the Cask does not have a checksum defined\. \fB\-\-no\-quarantine\fR will prevent Gatekeeper from enforcing its security restrictions on the Cask\.
|
||||||
.
|
.
|
||||||
.IP
|
.IP
|
||||||
\fItoken\fR is usually the ID of a Cask, but see \fIOTHER WAYS TO SPECIFY A CASK\fR for variations\.
|
\fItoken\fR is usually the ID of a Cask, but see \fIOTHER WAYS TO SPECIFY A CASK\fR for variations\.
|
||||||
@ -98,7 +98,7 @@ Without token arguments, display all the installed Casks that have newer version
|
|||||||
\fB\-\-quiet\fR suppresses the display of versions\.
|
\fB\-\-quiet\fR suppresses the display of versions\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fBreinstall\fR \fItoken\fR [ \fItoken\fR \.\.\. ]
|
\fBreinstall\fR [\-\-no\-quarantine] \fItoken\fR [ \fItoken\fR \.\.\. ]
|
||||||
Reinstall the given Cask\.
|
Reinstall the given Cask\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
@ -158,6 +158,10 @@ Skip Cask dependencies when installing\.
|
|||||||
Abort Cask installation if the Cask does not have a checksum defined\.
|
Abort Cask installation if the Cask does not have a checksum defined\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-no\-quarantine\fR
|
||||||
|
Prevent Gatekeeper from enforcing its security restrictions on the Cask\. This will let you run it straightaway\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
\fB\-\-verbose\fR
|
\fB\-\-verbose\fR
|
||||||
Give additional feedback during installation\.
|
Give additional feedback during installation\.
|
||||||
.
|
.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user