Merge branch 'master' into exclude-executable-metafiles

Added tests in keg_test and pathname_test was
moved into keg_spec and pathname_spec.
This commit is contained in:
Naoto Kaneko 2017-02-27 14:23:53 +09:00
commit 928eaca267
214 changed files with 6751 additions and 5475 deletions

View File

@ -7,7 +7,7 @@
#: If `--dry-run` or `-n` is passed, show what would be removed, but do not #: If `--dry-run` or `-n` is passed, show what would be removed, but do not
#: actually remove anything. #: actually remove anything.
#: #:
#: If `-s` is passed, scrubs the cache, removing downloads for even the latest #: If `-s` is passed, scrub the cache, removing downloads for even the latest
#: versions of formulae. Note downloads for any installed formulae will still not be #: versions of formulae. Note downloads for any installed formulae will still not be
#: deleted. If you want to delete those too: `rm -rf $(brew --cache)` #: deleted. If you want to delete those too: `rm -rf $(brew --cache)`

View File

@ -1,11 +1,10 @@
#: * `desc` <formula>: #: * `desc` <formula>:
#: Display <formula>'s name and one-line description. #: Display <formula>'s name and one-line description.
#: #:
#: * `desc` [`-s`|`-n`|`-d`] <pattern>: #: * `desc` [`-s`|`-n`|`-d`] (<text>|`/`<text>`/`):
#: Search both name and description (`-s`), just the names (`-n`), or just the #: Search both name and description (`-s`), just the names (`-n`), or just the
#: descriptions (`-d`) for `<pattern>`. `<pattern>` is by default interpreted #: descriptions (`-d`) for <text>. If <text> is flanked by slashes, it is interpreted
#: as a literal string; if flanked by slashes, it is instead interpreted as a #: as a regular expression. Formula descriptions are cached; the cache is created on
#: regular expression. Formula descriptions are cached; the cache is created on
#: the first search, making that search slower than subsequent ones. #: the first search, making that search slower than subsequent ones.
require "descriptions" require "descriptions"

View File

@ -4,7 +4,7 @@
#: * `info` `--github` <formula>: #: * `info` `--github` <formula>:
#: Open a browser to the GitHub History page for formula <formula>. #: Open a browser to the GitHub History page for formula <formula>.
#: #:
#: To view formula history locally: `brew log -p <formula>`. #: To view formula history locally: `brew log -p <formula>`
#: #:
#: * `info` `--json=`<version> (`--all`|`--installed`|<formulae>): #: * `info` `--json=`<version> (`--all`|`--installed`|<formulae>):
#: Print a JSON representation of <formulae>. Currently the only accepted value #: Print a JSON representation of <formulae>. Currently the only accepted value
@ -13,7 +13,7 @@
#: Pass `--all` to get information on all formulae, or `--installed` to get #: Pass `--all` to get information on all formulae, or `--installed` to get
#: information on all installed formulae. #: information on all installed formulae.
#: #:
#: See the docs for examples of using the JSON: #: See the docs for examples of using the JSON output:
#: <http://docs.brew.sh/Querying-Brew.html> #: <http://docs.brew.sh/Querying-Brew.html>
require "blacklist" require "blacklist"

View File

@ -12,6 +12,7 @@ class Symbol
Formulary.factory(to_s, *args) Formulary.factory(to_s, *args)
end end
end end
class String class String
def f(*args) def f(*args)
Formulary.factory(self, *args) Formulary.factory(self, *args)

View File

@ -1,4 +1,4 @@
#: * `outdated` [`--quiet`|`--verbose`|`--json=v1`] [`--fetch-HEAD`]: #: * `outdated` [`--quiet`|`--verbose`|`--json=`<version>] [`--fetch-HEAD`]:
#: Show formulae that have an updated version available. #: Show formulae that have an updated version available.
#: #:
#: By default, version information is displayed in interactive shells, and #: By default, version information is displayed in interactive shells, and

View File

@ -4,7 +4,7 @@
#: #:
#: This can be useful for debugging issues across all formulae #: This can be useful for debugging issues across all formulae
#: when making significant changes to `formula.rb`, #: when making significant changes to `formula.rb`,
#: or to determine if any current formulae have Ruby issues #: or to determine if any current formulae have Ruby issues.
require "readall" require "readall"

View File

@ -2,7 +2,7 @@
#: Display all locally available formulae for brewing (including tapped ones). #: Display all locally available formulae for brewing (including tapped ones).
#: No online search is performed if called without arguments. #: No online search is performed if called without arguments.
#: #:
#: * `search` [`--desc`] <text>|`/`<text>`/`: #: * `search` [`--desc`] (<text>|`/`<text>`/`):
#: Perform a substring search of formula names for <text>. If <text> is #: Perform a substring search of formula names for <text>. If <text> is
#: surrounded with slashes, then it is interpreted as a regular expression. #: surrounded with slashes, then it is interpreted as a regular expression.
#: The search for <text> is extended online to some popular taps. #: The search for <text> is extended online to some popular taps.

View File

@ -12,7 +12,7 @@
#: #:
#: Pass `--installed` to get information on installed taps. #: Pass `--installed` to get information on installed taps.
#: #:
#: See the docs for examples of using the JSON: #: See the docs for examples of using the JSON output:
#: <http://docs.brew.sh/Querying-Brew.html> #: <http://docs.brew.sh/Querying-Brew.html>
require "tap" require "tap"

View File

@ -1,7 +1,7 @@
#: * `unlink` [`--dry-run`] <formula>: #: * `unlink` [`--dry-run`] <formula>:
#: Remove symlinks for <formula> from the Homebrew prefix. This can be useful #: Remove symlinks for <formula> from the Homebrew prefix. This can be useful
#: for temporarily disabling a formula: #: for temporarily disabling a formula:
#: `brew unlink foo && commands && brew link foo`. #: `brew unlink <formula> && <commands> && brew link <formula>`
#: #:
#: If `--dry-run` or `-n` is passed, Homebrew will list all files which would #: If `--dry-run` or `-n` is passed, Homebrew will list all files which would
#: be unlinked, but will not actually unlink or delete any files. #: be unlinked, but will not actually unlink or delete any files.

View File

@ -1,7 +1,7 @@
#: * `unpack` [`--git`|`--patch`] [`--destdir=`<path>] <formulae>: #: * `unpack` [`--git`|`--patch`] [`--destdir=`<path>] <formulae>:
#: Unpack the source files for <formulae> into subdirectories of the current #: Unpack the source files for <formulae> into subdirectories of the current
#: working directory. If `--destdir=`<path> is given, the subdirectories will #: working directory. If `--destdir=`<path> is given, the subdirectories will
#: be created in the directory named by `<path>` instead. #: be created in the directory named by <path> instead.
#: #:
#: If `--patch` is passed, patches for <formulae> will be applied to the #: If `--patch` is passed, patches for <formulae> will be applied to the
#: unpacked source. #: unpacked source.

View File

@ -12,8 +12,8 @@
#: `--include-build`. Similarly, pass `--include-optional` to include `:optional` #: `--include-build`. Similarly, pass `--include-optional` to include `:optional`
#: dependencies. To skip `:recommended` type dependencies, pass `--skip-recommended`. #: dependencies. To skip `:recommended` type dependencies, pass `--skip-recommended`.
#: #:
#: By default, `uses` shows usages of `formula` by stable builds. To find #: By default, `uses` shows usages of <formulae> by stable builds. To find
#: cases where `formula` is used by development or HEAD build, pass #: cases where <formulae> is used by development or HEAD build, pass
#: `--devel` or `--HEAD`. #: `--devel` or `--HEAD`.
require "formula" require "formula"

View File

@ -75,6 +75,17 @@ class CompilerFailure
create(gcc: "4.5"), create(gcc: "4.5"),
create(gcc: "4.6"), create(gcc: "4.6"),
], ],
cxx14: [
create(:clang) { build 600 },
create(:gcc_4_0),
create(:gcc_4_2),
create(gcc: "4.3"),
create(gcc: "4.4"),
create(gcc: "4.5"),
create(gcc: "4.6"),
create(gcc: "4.7"),
create(gcc: "4.8"),
],
openmp: [ openmp: [
create(:clang), create(:clang),
], ],

View File

@ -174,30 +174,64 @@ class FormulaAuditor
@specs = %w[stable devel head].map { |s| formula.send(s) }.compact @specs = %w[stable devel head].map { |s| formula.send(s) }.compact
end end
def url_status_code(url, range: false) def self.check_http_content(url, user_agents: [:default])
# The system Curl is too old and unreliable with HTTPS homepages on return unless url.start_with? "http"
# Yosemite and below.
return "200" unless DevelopmentTools.curl_handles_most_https_homepages?
extra_args = [ details = nil
"--connect-timeout", "15", user_agent = nil
"--output", "/dev/null", user_agents.each do |ua|
"--write-out", "%{http_code}" details = http_content_headers_and_checksum(url, user_agent: ua)
] user_agent = ua
extra_args << "--range" << "0-0" if range break if details[:status].to_s.start_with?("2")
extra_args << url end
status_code = nil return "The URL #{url} is not reachable" unless details[:status]
[:browser, :default].each do |user_agent| unless details[:status].start_with? "2"
return "The URL #{url} is not reachable (HTTP status code #{details[:status]})"
end
return unless url.start_with? "http:"
secure_url = url.sub "http", "https"
secure_details =
http_content_headers_and_checksum(secure_url, user_agent: user_agent)
if !details[:status].to_s.start_with?("2") ||
!secure_details[:status].to_s.start_with?("2")
return
end
etag_match = details[:etag] &&
details[:etag] == secure_details[:etag]
content_length_match =
details[:content_length] &&
details[:content_length] == secure_details[:content_length]
file_match = details[:file_hash] == secure_details[:file_hash]
return if !etag_match && !content_length_match && !file_match
"The URL #{url} could use HTTPS rather than HTTP"
end
def self.http_content_headers_and_checksum(url, user_agent: :default)
args = curl_args( args = curl_args(
extra_args: extra_args, extra_args: ["--connect-timeout", "15", "--include", url],
show_output: true, show_output: true,
user_agent: user_agent, user_agent: user_agent,
) )
status_code = Open3.popen3(*args) { |_, stdout, _, _| stdout.read } output = Open3.popen3(*args) { |_, stdout, _, _| stdout.read }
break if status_code.start_with? "20"
status_code = :unknown
while status_code == :unknown || status_code.to_s.start_with?("3")
headers, _, output = output.partition("\r\n\r\n")
status_code = headers[%r{HTTP\/.* (\d+)}, 1]
end end
status_code
{
status: status_code,
etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2],
content_length: headers[/Content-Length: (\d+)/, 1],
file_hash: Digest::SHA256.digest(output),
}
end end
def audit_style def audit_style
@ -295,6 +329,27 @@ class FormulaAuditor
problem "File should end with a newline" unless text.trailing_newline? problem "File should end with a newline" unless text.trailing_newline?
versioned_formulae = Dir[formula.path.to_s.gsub(/\.rb$/, "@*.rb")]
needs_versioned_alias = !versioned_formulae.empty? &&
formula.tap &&
formula.aliases.grep(/.@\d/).empty?
if needs_versioned_alias
_, last_alias_version = File.basename(versioned_formulae.sort.reverse.first)
.gsub(/\.rb$/, "")
.split("@")
major, minor, = formula.version.to_s.split(".")
alias_name = if last_alias_version.split(".").length == 1
"#{formula.name}@#{major}"
else
"#{formula.name}@#{major}.#{minor}"
end
problem <<-EOS.undent
Formula has other versions so create an alias:
cd #{formula.tap.alias_dir}
ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name}
EOS
end
return unless @strict return unless @strict
present = audit_components present = audit_components
@ -410,7 +465,8 @@ class FormulaAuditor
problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'." problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'."
end end
if @@aliases.include?(dep.name) if @@aliases.include?(dep.name) &&
(core_formula? || !dep_f.versioned_formula?)
problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'." problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'."
end end
@ -549,6 +605,11 @@ class FormulaAuditor
def audit_homepage def audit_homepage
homepage = formula.homepage homepage = formula.homepage
if homepage.nil? || homepage.empty?
problem "Formula should have a homepage."
return
end
unless homepage =~ %r{^https?://} unless homepage =~ %r{^https?://}
problem "The homepage should start with http or https (URL is #{homepage})." problem "The homepage should start with http or https (URL is #{homepage})."
end end
@ -619,9 +680,13 @@ class FormulaAuditor
return unless @online return unless @online
status_code = url_status_code(homepage) # The system Curl is too old and unreliable with HTTPS homepages on
return if status_code.start_with? "20" # Yosemite and below.
problem "The homepage #{homepage} is not reachable (HTTP status code #{status_code})" return unless DevelopmentTools.curl_handles_most_https_homepages?
if http_content_problem = FormulaAuditor.check_http_content(homepage,
user_agents: [:browser, :default])
problem http_content_problem
end
end end
def audit_bottle_spec def audit_bottle_spec
@ -671,11 +736,11 @@ class FormulaAuditor
%w[Stable Devel HEAD].each do |name| %w[Stable Devel HEAD].each do |name|
next unless spec = formula.send(name.downcase) next unless spec = formula.send(name.downcase)
ra = ResourceAuditor.new(spec, online: @online).audit ra = ResourceAuditor.new(spec, online: @online, strict: @strict).audit
problems.concat ra.problems.map { |problem| "#{name}: #{problem}" } problems.concat ra.problems.map { |problem| "#{name}: #{problem}" }
spec.resources.each_value do |resource| spec.resources.each_value do |resource|
ra = ResourceAuditor.new(resource, online: @online).audit ra = ResourceAuditor.new(resource, online: @online, strict: @strict).audit
problems.concat ra.problems.map { |problem| problems.concat ra.problems.map { |problem|
"#{name} resource #{resource.name.inspect}: #{problem}" "#{name} resource #{resource.name.inspect}: #{problem}"
} }
@ -702,6 +767,7 @@ class FormulaAuditor
unstable_whitelist = %w[ unstable_whitelist = %w[
aalib 1.4rc5 aalib 1.4rc5
angolmois 2.0.0alpha2
automysqlbackup 3.0-rc6 automysqlbackup 3.0-rc6
aview 1.3.0rc1 aview 1.3.0rc1
distcc 3.2rc1 distcc 3.2rc1
@ -709,6 +775,8 @@ class FormulaAuditor
ftgl 2.1.3-rc5 ftgl 2.1.3-rc5
hidapi 0.8.0-rc1 hidapi 0.8.0-rc1
libcaca 0.99b19 libcaca 0.99b19
nethack4 4.3.0-beta2
opensyobon 1.0rc2
premake 4.4-beta5 premake 4.4-beta5
pwnat 0.3-beta pwnat 0.3-beta
pxz 4.999.9 pxz 4.999.9
@ -861,7 +929,7 @@ class FormulaAuditor
end end
end end
if text =~ /xcodebuild[ (]["'*]/ && !text.include?("SYMROOT=") if text =~ /xcodebuild[ (]*["'*]*/ && !text.include?("SYMROOT=")
problem 'xcodebuild should be passed an explicit "SYMROOT"' problem 'xcodebuild should be passed an explicit "SYMROOT"'
end end
@ -1231,6 +1299,7 @@ class ResourceAuditor
@using = resource.using @using = resource.using
@specs = resource.specs @specs = resource.specs
@online = options[:online] @online = options[:online]
@strict = options[:strict]
@problems = [] @problems = []
end end
@ -1490,38 +1559,26 @@ class ResourceAuditor
return unless @online return unless @online
urls.each do |url| urls.each do |url|
check_insecure_mirror(url) if url.start_with? "http:" next if !@strict && mirrors.include?(url)
strategy = DownloadStrategyDetector.detect(url, using)
if strategy <= CurlDownloadStrategy && !url.start_with?("file")
if http_content_problem = FormulaAuditor.check_http_content(url)
problem http_content_problem
end
elsif strategy <= GitDownloadStrategy
unless Utils.git_remote_exists url
problem "The URL #{url} is not a valid git URL"
end
elsif strategy <= SubversionDownloadStrategy
unless Utils.svn_remote_exists url
problem "The URL #{url} is not a valid svn URL"
end
end end
end end
def check_insecure_mirror(url)
details = get_content_details(url)
secure_url = url.sub "http", "https"
secure_details = get_content_details(secure_url)
return if details[:status].nil? || secure_details[:status].nil? || !details[:status].start_with?("2") || !secure_details[:status].start_with?("2")
etag_match = details[:etag] && details[:etag] == secure_details[:etag]
content_length_match = details[:content_length] && details[:content_length] == secure_details[:content_length]
file_match = details[:file_hash] == secure_details[:file_hash]
return if !etag_match && !content_length_match && !file_match
problem "The URL #{url} could use HTTPS rather than HTTP"
end end
def problem(text) def problem(text)
@problems << text @problems << text
end end
def get_content_details(url)
out = {}
output, = curl_output "--connect-timeout", "15", "--include", url
split = output.partition("\r\n\r\n")
headers = split.first
out[:status] = headers[%r{HTTP\/.* (\d+)}, 1]
out[:etag] = headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2]
out[:content_length] = headers[/Content-Length: (\d+)/, 1]
out[:file_hash] = Digest::SHA256.digest split.last
out
end
end end

View File

@ -1,5 +1,5 @@
#: @hide_from_man_page #: @hide_from_man_page
#: * `boneyard-formula-pr` [`--dry-run`] [`--local`] [`--reason=<reason>`] <formula-name> : #: * `boneyard-formula-pr` [`--dry-run`] [`--local`] [`--reason=<reason>`] <formula> :
#: Creates a pull request to boneyard a formula. #: Creates a pull request to boneyard a formula.
#: #:
#: If `--dry-run` is passed, print what would be done rather than doing it. #: If `--dry-run` is passed, print what would be done rather than doing it.

View File

@ -1,6 +1,5 @@
#: * `bottle` [`--verbose`] [`--no-rebuild`] [`--keep-old`] [`--skip-relocation`] [`--root-url=<root_url>`] [`--force-core-tap`]: #: * `bottle` [`--verbose`] [`--no-rebuild`] [`--keep-old`] [`--skip-relocation`] [`--root-url=`<URL>] [`--force-core-tap`]:
#: * `bottle` `--merge` [`--no-commit`] [`--keep-old`] [`--write`]: #: * `bottle` `--merge` [`--no-commit`] [`--keep-old`] [`--write`]:
#:
#: Generate a bottle (binary package) from a formula installed with #: Generate a bottle (binary package) from a formula installed with
#: `--build-bottle`. #: `--build-bottle`.

View File

@ -1,8 +1,7 @@
#: * `bump-formula-pr` [`--devel`] [`--dry-run`] [`--audit`|`--strict`] [`--message=`<message>] `--url=`<url> `--sha256=`<sha-256> <formula>: #: * `bump-formula-pr` [`--devel`] [`--dry-run` [`--write`]] [`--audit`|`--strict`] [`--mirror=`<URL>] [`--version=`<version>] [`--message=`<message>] (`--url=`<URL> `--sha256=`<sha-256>|`--tag=`<tag> `--revision=`<revision>) <formula>:
#: * `bump-formula-pr` [`--devel`] [`--dry-run`] [`--audit`|`--strict`] [`--message=`<message>] `--tag=`<tag> `--revision=`<revision> <formula>: #: Creates a pull request to update the formula with a new URL or a new tag.
#: Creates a pull request to update the formula with a new url or a new tag.
#: #:
#: If a <url> is specified, the <sha-256> checksum of the new download must #: If a <URL> is specified, the <sha-256> checksum of the new download must
#: also be specified. A best effort to determine the <sha-256> and <formula> #: also be specified. A best effort to determine the <sha-256> and <formula>
#: name will be made if either or both values are not supplied by the user. #: name will be made if either or both values are not supplied by the user.
#: #:
@ -21,17 +20,17 @@
#: #:
#: If `--strict` is passed, run `brew audit --strict` before opening the PR. #: If `--strict` is passed, run `brew audit --strict` before opening the PR.
#: #:
#: If `--mirror=`<url> is passed, use the value as a mirror url. #: If `--mirror=`<URL> is passed, use the value as a mirror URL.
#: #:
#: If `--version=`<version> is passed, use the value to override the value #: If `--version=`<version> is passed, use the value to override the value
#: parsed from the url or tag. Note that `--version=0` can be used to delete #: parsed from the URL or tag. Note that `--version=0` can be used to delete
#: an existing `version` override from a formula if it has become redundant. #: an existing `version` override from a formula if it has become redundant.
#: #:
#: If `--message=`<message> is passed, append <message> to the default PR #: If `--message=`<message> is passed, append <message> to the default PR
#: message. #: message.
#: #:
#: Note that this command cannot be used to transition a formula from a #: Note that this command cannot be used to transition a formula from a
#: url-and-sha256 style specification into a tag-and-revision style #: URL-and-sha256 style specification into a tag-and-revision style
#: specification, nor vice versa. It must use whichever style specification #: specification, nor vice versa. It must use whichever style specification
#: the preexisting formula already uses. #: the preexisting formula already uses.

View File

@ -3,8 +3,7 @@
#: Homebrew will attempt to automatically derive the formula name #: Homebrew will attempt to automatically derive the formula name
#: and version, but if it fails, you'll have to make your own template. The `wget` #: and version, but if it fails, you'll have to make your own template. The `wget`
#: formula serves as a simple example. For the complete API have a look at #: formula serves as a simple example. For the complete API have a look at
#: #: <http://www.rubydoc.info/github/Homebrew/brew/master/Formula>.
#: <http://www.rubydoc.info/github/Homebrew/brew/master/Formula>
#: #:
#: If `--autotools` is passed, create a basic template for an Autotools-style build. #: If `--autotools` is passed, create a basic template for an Autotools-style build.
#: If `--cmake` is passed, create a basic template for a CMake-style build. #: If `--cmake` is passed, create a basic template for a CMake-style build.

View File

@ -1,5 +1,5 @@
#: * `formula` <formula>: #: * `formula` <formula>:
#: Display the path where <formula> is #: Display the path where <formula> is located.
require "formula" require "formula"

View File

@ -1,4 +1,4 @@
#: * `linkage` [`--test`] [`--reverse`] <formula-name>: #: * `linkage` [`--test`] [`--reverse`] <formula>:
#: Checks the library links of an installed formula. #: Checks the library links of an installed formula.
#: #:
#: Only works on installed formulae. An error is raised if it is run on #: Only works on installed formulae. An error is raised if it is run on

View File

@ -1,5 +1,5 @@
#: @hide_from_man_page #: @hide_from_man_page
#: * `mirror` [`--test`] <formula-name> [<formula-name> ...]: #: * `mirror` [`--test`] <formulae>:
#: Reuploads the stable URL for a formula to Bintray to use it as a mirror. #: Reuploads the stable URL for a formula to Bintray to use it as a mirror.
module Homebrew module Homebrew

View File

@ -1,33 +1,42 @@
#: `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] <patch-source> [<patch-source>] #: * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] <patch-source> [<patch-source>]:
#:
#: Gets a patch from a GitHub commit or pull request and applies it to Homebrew. #: Gets a patch from a GitHub commit or pull request and applies it to Homebrew.
#: Optionally, installs the formulae changed by the patch. #: Optionally, installs the formulae changed by the patch.
#: #:
#: Each <patch-source> may be one of: #: Each <patch-source> may be one of:
#: * The ID number of a PR (Pull Request) in the homebrew/core GitHub #:
#: ~ The ID number of a PR (pull request) in the homebrew/core GitHub
#: repository #: repository
#: * The URL of a PR on GitHub, using either the web page or API URL #:
#: ~ The URL of a PR on GitHub, using either the web page or API URL
#: formats. In this form, the PR may be on Homebrew/brew, #: formats. In this form, the PR may be on Homebrew/brew,
#: Homebrew/homebrew-core or any tap. #: Homebrew/homebrew-core or any tap.
#: * The URL of a commit on GitHub
#: * A "http://bot.brew.sh/job/..." string specifying a testing job ID
#: #:
#: If `--bottle` was passed, handle bottles, pulling the bottle-update #: ~ The URL of a commit on GitHub
#:
#: ~ A "http://bot.brew.sh/job/..." string specifying a testing job ID
#:
#: If `--bottle` is passed, handle bottles, pulling the bottle-update
#: commit and publishing files on Bintray. #: commit and publishing files on Bintray.
#: If `--bump` was passed, for one-formula PRs, automatically reword #:
#: If `--bump` is passed, for one-formula PRs, automatically reword
#: commit message to our preferred format. #: commit message to our preferred format.
#: If `--clean` was passed, do not rewrite or otherwise modify the #:
#: If `--clean` is passed, do not rewrite or otherwise modify the
#: commits found in the pulled PR. #: commits found in the pulled PR.
#: If `--ignore-whitespace` was passed, silently ignore whitespace #:
#: If `--ignore-whitespace` is passed, silently ignore whitespace
#: discrepancies when applying diffs. #: discrepancies when applying diffs.
#: If `--resolve` was passed, when a patch fails to apply, leave in #:
#: progress and allow user to #: If `--resolve` is passed, when a patch fails to apply, leave in
#: resolve, instead of aborting. #: progress and allow user to resolve, instead of aborting.
#: If `--branch-okay` was passed, do not warn if pulling to a branch #:
#: If `--branch-okay` is passed, do not warn if pulling to a branch
#: besides master (useful for testing). #: besides master (useful for testing).
#: If `--no-pbcopy` was passed, do not copy anything to the system #:
# clipboard. #: If `--no-pbcopy` is passed, do not copy anything to the system
#: If `--no-publish` was passed, do not publish bottles to Bintray. #: clipboard.
#:
#: If `--no-publish` is passed, do not publish bottles to Bintray.
require "net/http" require "net/http"
require "net/https" require "net/https"

View File

@ -1,7 +1,7 @@
#: * `release-notes` [<previous_tag>] [<end_ref>]: #: * `release-notes` [`--markdown`] [<previous_tag>] [<end_ref>]:
#: Output the merged pull requests on Homebrew/brew between two Git refs. #: Output the merged pull requests on Homebrew/brew between two Git refs.
#: If no `previous_tag` is provided it defaults to the newest tag. #: If no <previous_tag> is provided it defaults to the newest tag.
#: If no `end_ref` is provided it defaults to `origin/master`. #: If no <end_ref> is provided it defaults to `origin/master`.
#: #:
#: If `--markdown` is passed, output as a Markdown list. #: If `--markdown` is passed, output as a Markdown list.

View File

@ -1,4 +1,4 @@
#: * `tests` [`-v`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`<test_script:test_method>] [`--seed` <seed>] [`--trace`] [`--online`] [`--official-cmd-taps`]: #: * `tests` [`-v`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`<test_script>`:`<test_method>] [`--seed` <seed>] [`--trace`] [`--online`] [`--official-cmd-taps`]:
#: Run Homebrew's unit and integration tests. #: Run Homebrew's unit and integration tests.
require "fileutils" require "fileutils"
@ -82,6 +82,8 @@ module Homebrew
"--format", "ParallelTests::RSpec::RuntimeLogger", "--format", "ParallelTests::RSpec::RuntimeLogger",
"--out", "tmp/parallel_runtime_rspec.log" "--out", "tmp/parallel_runtime_rspec.log"
] ]
spec_args << "--tag" << "~needs_macos" unless OS.mac?
run_tests "parallel_rspec", spec_files, spec_args run_tests "parallel_rspec", spec_files, spec_args
if (fs_leak_log = HOMEBREW_LIBRARY_PATH/"tmp/fs_leak.log").file? if (fs_leak_log = HOMEBREW_LIBRARY_PATH/"tmp/fs_leak.log").file?

View File

@ -1,14 +1,14 @@
#: * `update-test` [`--commit=<commit>`] [`--before=<date>`] [`--keep-tmp`]: #: * `update-test` [`--commit=`<commit>] [`--before=`<date>] [`--keep-tmp`]:
#: Runs a test of `brew update` with a new repository clone. #: Runs a test of `brew update` with a new repository clone.
#: #:
#: If no arguments are passed, use `origin/master` as the start commit. #: If no arguments are passed, use `origin/master` as the start commit.
#: #:
#: If `--commit=<commit>` is passed, use `<commit>` as the start commit. #: If `--commit=`<commit> is passed, use <commit> as the start commit.
#: #:
#: If `--before=<date>` is passed, use the commit at `<date>` as the #: If `--before=`<date> is passed, use the commit at <date> as the
#: start commit. #: start commit.
#: #:
#: If `--to-tag` is passed, set HOMEBREW_UPDATE_TO_TAG to test updating #: If `--to-tag` is passed, set `HOMEBREW_UPDATE_TO_TAG` to test updating
#: between tags. #: between tags.
#: #:
#: If `--keep-tmp` is passed, retain the temporary directory containing #: If `--keep-tmp` is passed, retain the temporary directory containing

View File

@ -335,7 +335,7 @@ class Pathname
alias to_str to_s unless method_defined?(:to_str) alias to_str to_s unless method_defined?(:to_str)
def cd def cd
Dir.chdir(self) { yield } Dir.chdir(self) { yield self }
end end
def subdirs def subdirs

View File

@ -1026,7 +1026,9 @@ class Formula
@prefix_returns_versioned_prefix = false @prefix_returns_versioned_prefix = false
end end
# Tell the user about any caveats regarding this package. # Tell the user about any Homebrew-specific caveats or locations regarding
# this package. These should not contain setup instructions that would apply
# to installation through a different package manager on a different OS.
# @return [String] # @return [String]
# <pre>def caveats # <pre>def caveats
# <<-EOS.undent # <<-EOS.undent

View File

@ -151,6 +151,28 @@ class FormulaInstaller
recursive_deps = formula.recursive_dependencies recursive_deps = formula.recursive_dependencies
recursive_formulae = recursive_deps.map(&:to_formula) recursive_formulae = recursive_deps.map(&:to_formula)
recursive_dependencies = []
recursive_formulae.each do |dep|
dep_recursive_dependencies = dep.recursive_dependencies.map(&:to_s)
if dep_recursive_dependencies.include?(formula.name)
recursive_dependencies << "#{formula.full_name} depends on #{dep.full_name}"
recursive_dependencies << "#{dep.full_name} depends on #{formula.full_name}"
end
end
unless recursive_dependencies.empty?
raise CannotInstallFormulaError, <<-EOS.undent
#{formula.full_name} contains a recursive dependency on itself:
#{recursive_dependencies.join("\n ")}
EOS
end
if recursive_formulae.flat_map(&:recursive_dependencies).map(&:to_s).include?(formula.name)
raise CannotInstallFormulaError, <<-EOS.undent
#{formula.full_name} contains a recursive dependency on itself!
EOS
end
if ENV["HOMEBREW_CHECK_RECURSIVE_VERSION_DEPENDENCIES"] if ENV["HOMEBREW_CHECK_RECURSIVE_VERSION_DEPENDENCIES"]
version_hash = {} version_hash = {}
version_conflicts = Set.new version_conflicts = Set.new

View File

@ -86,11 +86,11 @@ names, and other aspects of this manual are still subject to change.
If <token> is given, summarize the staged files associated with the If <token> is given, summarize the staged files associated with the
given Cask. given Cask.
* `reinstall` <token> [ <token> ...] * `reinstall` <token> [ <token> ... ]:
Reinstall the given Cask. Reinstall the given Cask.
* `search` or `-S` [<text> | /<regexp>/]: * `search` or `-S` [<text> | /<regexp>/]:
Without argument, display all Casks available for install, otherwise Without an argument, display all Casks available for install; otherwise
perform a substring search of known Cask tokens for <text> or, if the perform a substring search of known Cask tokens for <text> or, if the
text is delimited by slashes (/<regexp>/), it is interpreted as a text is delimited by slashes (/<regexp>/), it is interpreted as a
Ruby regular expression. Ruby regular expression.
@ -111,7 +111,7 @@ names, and other aspects of this manual are still subject to change.
the Cask does not appear to be currently installed. the Cask does not appear to be currently installed.
Removes all staged versions of the Cask distribution found under Removes all staged versions of the Cask distribution found under
`<Caskroom_path>/<token>`. `<Caskroom_path>/`<token>.
If the Cask definition contains a `zap` stanza, performs additional If the Cask definition contains a `zap` stanza, performs additional
`zap` actions as defined there, such as removing local preference `zap` actions as defined there, such as removing local preference
@ -123,18 +123,18 @@ names, and other aspects of this manual are still subject to change.
## INTERNAL COMMANDS ## INTERNAL COMMANDS
* `_appcast_checkpoint` [--calculate] [ <token> ... | <URL> ... ]: * `_appcast_checkpoint` [--calculate] [ <token> ... | <URL> ... ]:
Given a `token`, returns the current appcast checkpoint, or calculates Given a <token>, returns the current appcast checkpoint, or calculates
the appcast checkpoint if the `--calculate` flag is specified. the appcast checkpoint if the `--calculate` flag is specified.
Given a `URL`, calculates the appcast checkpoint for it.
* `_stanza` <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <cask_token> ... ]: Given a <URL>, calculates the appcast checkpoint for it.
Given a `stanza_name` and a `cask_token`, returns the current stanza
for a given Cask. If no `cask_token` is given, then data for all * `_stanza` <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <token> ... ]:
Casks is returned. Given a <stanza_name> and a <token>, returns the current stanza for a
given Cask. If no <token> is given, then data for all Casks is returned.
## OPTIONS ## OPTIONS
To make these options persistent, see the ENVIRONMENT section, below. To make these options persistent, see the [ENVIRONMENT][] section, below.
Some of these (such as `--prefpanedir`) may be subject to removal Some of these (such as `--prefpanedir`) may be subject to removal
in a future version. in a future version.
@ -150,7 +150,7 @@ in a future version.
Abort Cask installation if the Cask does not have a checksum defined. Abort Cask installation if the Cask does not have a checksum defined.
* `--caskroom=<path>`: * `--caskroom=<path>`:
Location of the Caskroom, where all binaries are stored. The default value is: `$(brew --prefix)/Caskroom`. Set location of the Caskroom, where all binaries are stored. The default value is `$(brew --prefix)/Caskroom`.
* `--verbose`: * `--verbose`:
Give additional feedback during installation. Give additional feedback during installation.
@ -218,17 +218,17 @@ the Homebrew command:
Most Homebrew-Cask commands can accept a Cask token as an argument. As Most Homebrew-Cask commands can accept a Cask token as an argument. As
described above, the argument can take the form of: described above, the argument can take the form of:
* A token as returned by `brew cask search`, _eg_ `google-chrome` * A token as returned by `brew cask search`, e.g. `google-chrome`
Homebrew-Cask also accepts three other forms in place of plain tokens: Homebrew-Cask also accepts three other forms in place of plain tokens:
* A fully-qualified token which includes the Tap name, _eg_ * A fully-qualified token which includes the Tap name, e.g.
`caskroom/fonts/font-symbola` `caskroom/fonts/font-symbola`
* A fully-qualified pathname to a Cask file, _eg_ * A fully-qualified pathname to a Cask file, e.g.
`/usr/local/Library/Taps/caskroom/homebrew-cask/Casks/google-chrome.rb` `/usr/local/Library/Taps/caskroom/homebrew-cask/Casks/google-chrome.rb`
* A `curl`-retrievable URI to a Cask file, _eg_ * A `curl`-retrievable URI to a Cask file, e.g.
`https://raw.githubusercontent.com/caskroom/homebrew-cask/f25b6babcd398abf48e33af3d887b2d00de1d661/Casks/google-chrome.rb` `https://raw.githubusercontent.com/caskroom/homebrew-cask/f25b6babcd398abf48e33af3d887b2d00de1d661/Casks/google-chrome.rb`
## ENVIRONMENT ## ENVIRONMENT
@ -239,17 +239,18 @@ information.
Environment variables specific to Homebrew-Cask: Environment variables specific to Homebrew-Cask:
* HOMEBREW\_CASK\_OPTS: * `HOMEBREW_CASK_OPTS`:
This variable may contain any arguments normally used as options on This variable may contain any arguments normally used as options on
the command-line. This is particularly useful to make options persistent. the command-line. This is particularly useful to make options persistent.
For example, you might add to your .bash_profile or .zshenv something like: For example, you might add to your .bash_profile or .zshenv something like:
`export HOMEBREW_CASK_OPTS='--appdir=/Applications --caskroom=/etc/Caskroom'`.
export HOMEBREW_CASK_OPTS='--appdir=/Applications --caskroom=/etc/Caskroom'
## SEE ALSO ## SEE ALSO
The Homebrew-Cask home page: <http://caskroom.io>. The Homebrew-Cask home page: <http://caskroom.io>
The Homebrew-Cask GitHub page: <https://github.com/caskroom/homebrew-cask>. The Homebrew-Cask GitHub page: <https://github.com/caskroom/homebrew-cask>
`brew`(1), `curl`(1) `brew`(1), `curl`(1)
@ -261,7 +262,7 @@ Man page format based on `brew.1.md` from Homebrew.
## BUGS ## BUGS
We still have bugs — and we are busy fixing them! If you have a problem, dont We still have bugs - and we are busy fixing them! If you have a problem, don't
be shy about reporting it on our [GitHub issues page](https://github.com/caskroom/homebrew-cask/issues?state=open). be shy about reporting it on our [GitHub issues page](https://github.com/caskroom/homebrew-cask/issues?state=open).
When reporting bugs, remember that Homebrew-Cask is an independent project from When reporting bugs, remember that Homebrew-Cask is an independent project from

View File

@ -40,7 +40,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
* `list`: * `list`:
List all installed formulae. List all installed formulae.
* `search` <text>|`/`<text>`/`: * `search` (<text>|`/`<text>`/`):
Perform a substring search of formula names for <text>. If <text> is Perform a substring search of formula names for <text>. If <text> is
surrounded with slashes, then it is interpreted as a regular expression. surrounded with slashes, then it is interpreted as a regular expression.
The search for <text> is extended online to some popular taps. The search for <text> is extended online to some popular taps.
@ -214,7 +214,7 @@ can take several different forms:
to insecure HTTP. to insecure HTTP.
While ensuring your downloads are fully secure, this is likely While ensuring your downloads are fully secure, this is likely
to cause from-source Sourceforge, some GNU & GNOME based to cause from-source SourceForge, some GNU & GNOME based
formulae to fail to download. formulae to fail to download.
* `HOMEBREW_NO_GITHUB_API`: * `HOMEBREW_NO_GITHUB_API`:

View File

@ -8,16 +8,14 @@ class RubyRequirement < Requirement
super super
end end
satisfy build_env: false do satisfy(build_env: false) { new_enough_ruby }
which_all("ruby").detect do |ruby|
version = /\d\.\d/.match Utils.popen_read(ruby, "--version") env do
next unless version ENV.prepend_path "PATH", new_enough_ruby
Version.create(version.to_s) >= Version.create(@version)
end
end end
def message def message
s = "Ruby #{@version} is required to install this formula." s = "Ruby >= #{@version} is required to install this formula."
s += super s += super
s s
end end
@ -33,4 +31,28 @@ class RubyRequirement < Requirement
name name
end end
end end
private
def new_enough_ruby
rubies.detect { |ruby| new_enough?(ruby) }
end
def rubies
rubies = which_all("ruby")
ruby_formula = Formula["ruby"]
if ruby_formula && ruby_formula.installed?
rubies.unshift ruby_formula.bin/"ruby"
end
rubies.uniq
end
def new_enough?(ruby)
version = Utils.popen_read(ruby, "-e", "print RUBY_VERSION").strip
version =~ /^\d+\.\d+/ && Version.create(version) >= min_version
end
def min_version
@min_version ||= Version.create(@version)
end
end end

View File

@ -7,19 +7,35 @@ require "development_tools"
class SystemConfig class SystemConfig
class << self class << self
def gcc_4_2 def gcc_4_2
@gcc_4_2 ||= DevelopmentTools.gcc_4_2_build_version if DevelopmentTools.installed? @gcc_4_2 ||= if DevelopmentTools.installed?
DevelopmentTools.gcc_4_2_build_version
else
Version::NULL
end
end end
def gcc_4_0 def gcc_4_0
@gcc_4_0 ||= DevelopmentTools.gcc_4_0_build_version if DevelopmentTools.installed? @gcc_4_0 ||= if DevelopmentTools.installed?
DevelopmentTools.gcc_4_0_build_version
else
Version::NULL
end
end end
def clang def clang
@clang ||= DevelopmentTools.clang_version if DevelopmentTools.installed? @clang ||= if DevelopmentTools.installed?
DevelopmentTools.clang_version
else
Version::NULL
end
end end
def clang_build def clang_build
@clang_build ||= DevelopmentTools.clang_build_version if DevelopmentTools.installed? @clang_build ||= if DevelopmentTools.installed?
DevelopmentTools.clang_build_version
else
Version::NULL
end
end end
def head def head

View File

@ -1,7 +1,7 @@
require "extend/ARGV" require "extend/ARGV"
describe HomebrewArgvExtension do describe HomebrewArgvExtension do
subject { argv.extend(HomebrewArgvExtension) } subject { argv.extend(described_class) }
let(:argv) { ["mxcl"] } let(:argv) { ["mxcl"] }
describe "#formulae" do describe "#formulae" do

View File

@ -0,0 +1,189 @@
require "extend/ENV"
shared_examples EnvActivation do
subject { env.extend(described_class) }
let(:env) { {}.extend(EnvActivation) }
it "supports switching compilers" do
subject.clang
expect(subject["LD"]).to be nil
expect(subject["CC"]).to eq(subject["OBJC"])
end
describe "#with_build_environment" do
it "restores the environment" do
before = subject.dup
subject.with_build_environment do
subject["foo"] = "bar"
end
expect(subject["foo"]).to be nil
expect(subject).to eq(before)
end
it "ensures the environment is restored" do
before = subject.dup
expect {
subject.with_build_environment do
subject["foo"] = "bar"
raise StandardError
end
}.to raise_error(StandardError)
expect(subject["foo"]).to be nil
expect(subject).to eq(before)
end
it "returns the value of the block" do
expect(subject.with_build_environment { 1 }).to eq(1)
end
it "does not mutate the interface" do
expected = subject.methods
subject.with_build_environment do
expect(subject.methods).to eq(expected)
end
expect(subject.methods).to eq(expected)
end
end
describe "#append" do
it "appends to an existing key" do
subject["foo"] = "bar"
subject.append "foo", "1"
expect(subject["foo"]).to eq("bar 1")
end
it "appends to an existing empty key" do
subject["foo"] = ""
subject.append "foo", "1"
expect(subject["foo"]).to eq("1")
end
it "appends to a non-existant key" do
subject.append "foo", "1"
expect(subject["foo"]).to eq("1")
end
# NOTE: this may be a wrong behavior; we should probably reject objects that
# do not respond to #to_str. For now this documents existing behavior.
it "coerces a value to a string" do
subject.append "foo", 42
expect(subject["foo"]).to eq("42")
end
end
describe "#prepend" do
it "prepends to an existing key" do
subject["foo"] = "bar"
subject.prepend "foo", "1"
expect(subject["foo"]).to eq("1 bar")
end
it "prepends to an existing empty key" do
subject["foo"] = ""
subject.prepend "foo", "1"
expect(subject["foo"]).to eq("1")
end
it "prepends to a non-existant key" do
subject.prepend "foo", "1"
expect(subject["foo"]).to eq("1")
end
# NOTE: this may be a wrong behavior; we should probably reject objects that
# do not respond to #to_str. For now this documents existing behavior.
it "coerces a value to a string" do
subject.prepend "foo", 42
expect(subject["foo"]).to eq("42")
end
end
describe "#append_path" do
it "appends to a path" do
subject.append_path "FOO", "/usr/bin"
expect(subject["FOO"]).to eq("/usr/bin")
subject.append_path "FOO", "/bin"
expect(subject["FOO"]).to eq("/usr/bin#{File::PATH_SEPARATOR}/bin")
end
end
describe "#prepend_path" do
it "prepends to a path" do
subject.prepend_path "FOO", "/usr/bin"
expect(subject["FOO"]).to eq("/usr/bin")
subject.prepend_path "FOO", "/bin"
expect(subject["FOO"]).to eq("/bin#{File::PATH_SEPARATOR}/usr/bin")
end
end
describe "#compiler" do
it "allows switching compilers" do
[:clang, :gcc_4_2, :gcc_4_0].each do |compiler|
subject.public_send(compiler)
expect(subject.compiler).to eq(compiler)
end
end
end
example "deparallelize_block_form_restores_makeflags" do
subject["MAKEFLAGS"] = "-j4"
subject.deparallelize do
expect(subject["MAKEFLAGS"]).to be nil
end
expect(subject["MAKEFLAGS"]).to eq("-j4")
end
end
describe Stdenv do
include_examples EnvActivation
end
describe Superenv do
include_examples EnvActivation
it "initializes deps" do
expect(subject.deps).to eq([])
expect(subject.keg_only_deps).to eq([])
end
describe "#cxx11" do
it "raises an error when the compiler isn't supported" do
%w[gcc gcc-4.7].each do |compiler|
subject["HOMEBREW_CC"] = compiler
expect { subject.cxx11 }
.to raise_error(/The selected compiler doesn't support C\+\+11:/)
expect(subject["HOMEBREW_CCCFG"]).to be nil
end
end
it "supports gcc-5" do
subject["HOMEBREW_CC"] = "gcc-5"
subject.cxx11
expect(subject["HOMEBREW_CCCFG"]).to include("x")
end
example "supports gcc-6" do
subject["HOMEBREW_CC"] = "gcc-6"
subject.cxx11
expect(subject["HOMEBREW_CCCFG"]).to include("x")
end
it "supports clang" do
subject["HOMEBREW_CC"] = "clang"
subject.cxx11
expect(subject["HOMEBREW_CCCFG"]).to include("x")
expect(subject["HOMEBREW_CCCFG"]).to include("g")
end
end
end

View File

@ -1,202 +0,0 @@
require "testing_env"
require "extend/ENV"
require "testing_env"
class IntegrationCommandTestEnv < IntegrationCommandTestCase
def test_env
assert_match(/CMAKE_PREFIX_PATH="#{Regexp.escape(HOMEBREW_PREFIX)}[:"]/,
cmd("--env"))
end
def test_env_fish
assert_match(/set [-]gx CMAKE_PREFIX_PATH "#{Regexp.quote(HOMEBREW_PREFIX.to_s)}"/,
cmd("--env", "--shell=fish"))
end
def test_env_csh
assert_match(/setenv CMAKE_PREFIX_PATH #{Regexp.quote(HOMEBREW_PREFIX.to_s)};/,
cmd("--env", "--shell=tcsh"))
end
def test_env_bash
assert_match(/export CMAKE_PREFIX_PATH="#{Regexp.quote(HOMEBREW_PREFIX.to_s)}"/,
cmd("--env", "--shell=bash"))
end
def test_env_plain
assert_match(/CMAKE_PREFIX_PATH: #{Regexp.quote(HOMEBREW_PREFIX)}/,
cmd("--env", "--plain"))
end
end
module SharedEnvTests
def setup
super
@env = {}.extend(EnvActivation)
end
def test_switching_compilers
@env.clang
assert_nil @env["LD"]
assert_equal @env["OBJC"], @env["CC"]
end
def test_with_build_environment_restores_env
before = @env.dup
@env.with_build_environment do
@env["foo"] = "bar"
end
assert_nil @env["foo"]
assert_equal before, @env
end
def test_with_build_environment_ensures_env_restored
before = @env.dup
begin
@env.with_build_environment do
@env["foo"] = "bar"
raise Exception
end
rescue Exception
end
assert_nil @env["foo"]
assert_equal before, @env
end
def test_with_build_environment_returns_block_value
assert_equal 1, @env.with_build_environment { 1 }
end
def test_with_build_environment_does_not_mutate_interface
expected = @env.methods
@env.with_build_environment { assert_equal expected, @env.methods }
assert_equal expected, @env.methods
end
def test_append_existing_key
@env["foo"] = "bar"
@env.append "foo", "1"
assert_equal "bar 1", @env["foo"]
end
def test_append_existing_key_empty
@env["foo"] = ""
@env.append "foo", "1"
assert_equal "1", @env["foo"]
end
def test_append_missing_key
@env.append "foo", "1"
assert_equal "1", @env["foo"]
end
def test_prepend_existing_key
@env["foo"] = "bar"
@env.prepend "foo", "1"
assert_equal "1 bar", @env["foo"]
end
def test_prepend_existing_key_empty
@env["foo"] = ""
@env.prepend "foo", "1"
assert_equal "1", @env["foo"]
end
def test_prepend_missing_key
@env.prepend "foo", "1"
assert_equal "1", @env["foo"]
end
# NOTE: this may be a wrong behavior; we should probably reject objects that
# do not respond to #to_str. For now this documents existing behavior.
def test_append_coerces_value_to_string
@env.append "foo", 42
assert_equal "42", @env["foo"]
end
def test_prepend_coerces_value_to_string
@env.prepend "foo", 42
assert_equal "42", @env["foo"]
end
def test_append_path
@env.append_path "FOO", "/usr/bin"
assert_equal "/usr/bin", @env["FOO"]
@env.append_path "FOO", "/bin"
assert_equal "/usr/bin#{File::PATH_SEPARATOR}/bin", @env["FOO"]
end
def test_prepend_path
@env.prepend_path "FOO", "/usr/bin"
assert_equal "/usr/bin", @env["FOO"]
@env.prepend_path "FOO", "/bin"
assert_equal "/bin#{File::PATH_SEPARATOR}/usr/bin", @env["FOO"]
end
def test_switching_compilers_updates_compiler
[:clang, :gcc_4_2, :gcc_4_0].each do |compiler|
@env.send(compiler)
assert_equal compiler, @env.compiler
end
end
def test_deparallelize_block_form_restores_makeflags
@env["MAKEFLAGS"] = "-j4"
@env.deparallelize do
assert_nil @env["MAKEFLAGS"]
end
assert_equal "-j4", @env["MAKEFLAGS"]
end
end
class StdenvTests < Homebrew::TestCase
include SharedEnvTests
def setup
super
@env.extend(Stdenv)
end
end
class SuperenvTests < Homebrew::TestCase
include SharedEnvTests
def setup
super
@env.extend(Superenv)
end
def test_initializes_deps
assert_equal [], @env.deps
assert_equal [], @env.keg_only_deps
end
def test_unsupported_cxx11
%w[gcc gcc-4.7].each do |compiler|
@env["HOMEBREW_CC"] = compiler
assert_raises do
@env.cxx11
end
refute_match "x", @env["HOMEBREW_CCCFG"]
end
end
def test_supported_cxx11_gcc_5
@env["HOMEBREW_CC"] = "gcc-5"
@env.cxx11
assert_match "x", @env["HOMEBREW_CCCFG"]
end
def test_supported_cxx11_gcc_6
@env["HOMEBREW_CC"] = "gcc-6"
@env.cxx11
assert_match "x", @env["HOMEBREW_CCCFG"]
end
def test_supported_cxx11_clang
@env["HOMEBREW_CC"] = "clang"
@env.cxx11
assert_match "x", @env["HOMEBREW_CCCFG"]
assert_match "g", @env["HOMEBREW_CCCFG"]
end
end

View File

@ -419,9 +419,8 @@ class FormulaAuditorTests < Homebrew::TestCase
EOS EOS
fa.audit_homepage fa.audit_homepage
assert_equal ["The homepage should start with http or https " \ assert_equal ["The homepage should start with http or https (URL is #{fa.formula.homepage})."],
"(URL is #{fa.formula.homepage}).", "The homepage #{fa.formula.homepage} is not reachable " \ fa.problems
"(HTTP status code 000)"], fa.problems
formula_homepages = { formula_homepages = {
"bar" => "http://www.freedesktop.org/wiki/bar", "bar" => "http://www.freedesktop.org/wiki/bar",
@ -466,4 +465,49 @@ class FormulaAuditorTests < Homebrew::TestCase
end end
end end
end end
def test_audit_without_homepage
fa = formula_auditor "foo", <<-EOS.undent, online: true
class Foo < Formula
url "http://example.com/foo-1.0.tgz"
end
EOS
fa.audit_homepage
assert_match "Formula should have a homepage.", fa.problems.first
end
def test_audit_xcodebuild_suggests_symroot
fa = formula_auditor "foo", <<-EOS.undent
class Foo < Formula
url "http://example.com/foo-1.0.tgz"
homepage "http://example.com"
def install
xcodebuild "-project", "meow.xcodeproject"
end
end
EOS
fa.audit_text
assert_match 'xcodebuild should be passed an explicit "SYMROOT"', fa.problems.first
end
def test_audit_bare_xcodebuild_suggests_symroot_also
fa = formula_auditor "foo", <<-EOS.undent
class Foo < Formula
url "http://example.com/foo-1.0.tgz"
homepage "http://example.com"
def install
xcodebuild
end
end
EOS
fa.audit_text
assert_match 'xcodebuild should be passed an explicit "SYMROOT"', fa.problems.first
end
end end

View File

@ -1,21 +0,0 @@
require "testing_env"
class IntegrationCommandTestBottle < IntegrationCommandTestCase
def test_bottle
cmd("install", "--build-bottle", testball)
assert_match "Formula not from core or any taps",
cmd_fail("bottle", "--no-rebuild", testball)
setup_test_formula "testball"
# `brew bottle` should not fail with dead symlink
# https://github.com/Homebrew/legacy-homebrew/issues/49007
(HOMEBREW_CELLAR/"testball/0.1").cd do
FileUtils.ln_s "not-exist", "symlink"
end
assert_match(/testball-0\.1.*\.bottle\.tar\.gz/,
cmd("bottle", "--no-rebuild", "testball"))
ensure
FileUtils.rm_f Dir["testball-0.1*.bottle.tar.gz"]
end
end

View File

@ -0,0 +1,52 @@
require "build_options"
require "options"
RSpec::Matchers.alias_matcher :be_built_with, :be_with
RSpec::Matchers.alias_matcher :be_built_without, :be_without
describe BuildOptions do
subject { described_class.new(args, opts) }
let(:bad_build) { described_class.new(bad_args, opts) }
let(:args) { Options.create(%w[--with-foo --with-bar --without-qux]) }
let(:opts) { Options.create(%w[--with-foo --with-bar --without-baz --without-qux]) }
let(:bad_args) { Options.create(%w[--with-foo --with-bar --without-bas --without-qux --without-abc]) }
specify "#include?" do
expect(subject).to include("with-foo")
expect(subject).not_to include("with-qux")
expect(subject).not_to include("--with-foo")
end
specify "#with?" do
expect(subject).to be_built_with("foo")
expect(subject).to be_built_with("bar")
expect(subject).to be_built_with("baz")
end
specify "#without?" do
expect(subject).to be_built_without("qux")
expect(subject).to be_built_without("xyz")
end
specify "#used_options" do
expect(subject.used_options).to include("--with-foo")
expect(subject.used_options).to include("--with-bar")
end
specify "#unused_options" do
expect(subject.unused_options).to include("--without-baz")
end
specify "#invalid_options" do
expect(subject.invalid_options).to be_empty
expect(bad_build.invalid_options).to include("--without-bas")
expect(bad_build.invalid_options).to include("--without-abc")
expect(bad_build.invalid_options).not_to include("--with-foo")
expect(bad_build.invalid_options).not_to include("--with-baz")
end
specify "#invalid_option_names" do
expect(subject.invalid_option_names).to be_empty
expect(bad_build.invalid_option_names).to eq(%w[--without-abc --without-bas])
end
end

View File

@ -1,50 +0,0 @@
require "testing_env"
require "build_options"
require "options"
class BuildOptionsTests < Homebrew::TestCase
def setup
super
args = Options.create(%w[--with-foo --with-bar --without-qux])
opts = Options.create(%w[--with-foo --with-bar --without-baz --without-qux])
@build = BuildOptions.new(args, opts)
bad_args = Options.create(%w[--with-foo --with-bar --without-bas --without-qux --without-abc])
@bad_build = BuildOptions.new(bad_args, opts)
end
def test_include
assert_includes @build, "with-foo"
refute_includes @build, "with-qux"
refute_includes @build, "--with-foo"
end
def test_with_without
assert @build.with?("foo")
assert @build.with?("bar")
assert @build.with?("baz")
assert @build.without?("qux")
assert @build.without?("xyz")
end
def test_used_options
assert_includes @build.used_options, "--with-foo"
assert_includes @build.used_options, "--with-bar"
end
def test_unused_options
assert_includes @build.unused_options, "--without-baz"
end
def test_invalid_options
assert_empty @build.invalid_options
assert_includes @bad_build.invalid_options, "--without-bas"
assert_includes @bad_build.invalid_options, "--without-abc"
refute_includes @bad_build.invalid_options, "--with-foo"
refute_includes @bad_build.invalid_options, "--with-baz"
end
def test_invalid_option_names
assert_empty @build.invalid_option_names
assert_equal @bad_build.invalid_option_names, %w[--without-abc --without-bas]
end
end

View File

@ -1,22 +0,0 @@
require "testing_env"
class IntegrationCommandTestBundle < IntegrationCommandTestCase
def test_bundle
needs_test_cmd_taps
setup_remote_tap("homebrew/bundle")
HOMEBREW_REPOSITORY.cd do
shutup do
system "git", "init"
system "git", "commit", "--allow-empty", "-m", "This is a test commit"
end
end
mktmpdir do |path|
FileUtils.touch "#{path}/Brewfile"
Dir.chdir path do
assert_equal "The Brewfile's dependencies are satisfied.",
cmd("bundle", "check")
end
end
end
end

View File

@ -1,8 +0,0 @@
require "testing_env"
class IntegrationCommandTestCacheFormula < IntegrationCommandTestCase
def test_cache_formula
assert_match %r{#{HOMEBREW_CACHE}/testball-},
cmd("--cache", testball)
end
end

View File

@ -1,8 +0,0 @@
require "testing_env"
class IntegrationCommandTestCache < IntegrationCommandTestCase
def test_cache
assert_equal HOMEBREW_CACHE.to_s,
cmd("--cache")
end
end

View File

@ -1,10 +0,0 @@
require "testing_env"
class IntegrationCommandTestCask < IntegrationCommandTestCase
def test_cask
needs_test_cmd_taps
needs_macos
setup_remote_tap("caskroom/cask")
cmd("cask", "list", "--caskroom=#{HOMEBREW_PREFIX}/Caskroom")
end
end

View File

@ -1,8 +0,0 @@
require "testing_env"
class IntegrationCommandTestCat < IntegrationCommandTestCase
def test_cat
formula_file = setup_test_formula "testball"
assert_equal formula_file.read.chomp, cmd("cat", "testball")
end
end

View File

@ -0,0 +1,29 @@
require "formula"
require "caveats"
describe Caveats do
subject { described_class.new(f) }
let(:f) { formula { url "foo-1.0" } }
specify "#f" do
expect(subject.f).to eq(f)
end
describe "#empty?" do
it "returns true if the Formula has no caveats" do
expect(subject).to be_empty
end
it "returns false if the Formula has caveats" do
f = formula do
url "foo-1.0"
def caveats
"something"
end
end
expect(described_class.new(f)).not_to be_empty
end
end
end

View File

@ -1,30 +0,0 @@
require "testing_env"
require "formula"
require "caveats"
class CaveatsTests < Homebrew::TestCase
def setup
super
@f = formula { url "foo-1.0" }
@c = Caveats.new @f
end
def test_f
assert_equal @f, @c.f
end
def test_empty?
assert @c.empty?
f = formula do
url "foo-1.0"
def caveats
"something"
end
end
c = Caveats.new f
refute c.empty?
end
end

View File

@ -1,8 +0,0 @@
require "testing_env"
class IntegrationCommandTestCellarFormula < IntegrationCommandTestCase
def test_cellar_formula
assert_match "#{HOMEBREW_CELLAR}/testball",
cmd("--cellar", testball)
end
end

View File

@ -1,8 +0,0 @@
require "testing_env"
class IntegrationCommandTestCellar < IntegrationCommandTestCase
def test_cellar
assert_equal HOMEBREW_CELLAR.to_s,
cmd("--cellar")
end
end

View File

@ -5,13 +5,6 @@ require "fileutils"
require "pathname" require "pathname"
require "testing_env" require "testing_env"
class IntegrationCommandTestCleanup < IntegrationCommandTestCase
def test_cleanup
(HOMEBREW_CACHE/"test").write "test"
assert_match "#{HOMEBREW_CACHE}/test", cmd("cleanup", "--prune=all")
end
end
class CleanupTests < Homebrew::TestCase class CleanupTests < Homebrew::TestCase
def setup def setup
super super

View File

@ -0,0 +1,15 @@
describe "brew --cache", :integration_test do
it "print the location of Homebrew's cache when no argument is given" do
expect { brew "--cache" }
.to output("#{HOMEBREW_CACHE}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "prints all cache files for a given Formula" do
expect { brew "--cache", testball }
.to output(%r{#{HOMEBREW_CACHE}/testball-}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,15 @@
describe "brew --cellar", :integration_test do
it "print the location of Homebrew's Cellar when no argument is given" do
expect { brew "--cellar" }
.to output("#{HOMEBREW_CELLAR}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "returns the Cellar subdirectory for a given Formula" do
expect { brew "--cellar", testball }
.to output(%r{#{HOMEBREW_CELLAR}/testball}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,44 @@
describe "brew --env", :integration_test do
it "prints the Homebrew build environment variables" do
expect { brew "--env" }
.to output(/CMAKE_PREFIX_PATH="#{Regexp.escape(HOMEBREW_PREFIX)}[:"]/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
describe "--shell=bash" do
it "prints the Homebrew build environment variables in Bash syntax" do
expect { brew "--env", "--shell=bash" }
.to output(/export CMAKE_PREFIX_PATH="#{Regexp.quote(HOMEBREW_PREFIX.to_s)}"/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
describe "--shell=fish" do
it "prints the Homebrew build environment variables in Fish syntax" do
expect { brew "--env", "--shell=fish" }
.to output(/set [-]gx CMAKE_PREFIX_PATH "#{Regexp.quote(HOMEBREW_PREFIX.to_s)}"/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
describe "--shell=tcsh" do
it "prints the Homebrew build environment variables in Tcsh syntax" do
expect { brew "--env", "--shell=tcsh" }
.to output(/setenv CMAKE_PREFIX_PATH #{Regexp.quote(HOMEBREW_PREFIX.to_s)};/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
describe "--plain" do
it "prints the Homebrew build environment variables without quotes" do
expect { brew "--env", "--plain" }
.to output(/CMAKE_PREFIX_PATH: #{Regexp.quote(HOMEBREW_PREFIX)}/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
end

View File

@ -0,0 +1,15 @@
describe "brew --prefix", :integration_test do
it "prints the Homebrew prefix when no argument is given" do
expect { brew "--prefix" }
.to output("#{HOMEBREW_PREFIX}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "prints a given Formula's prefix" do
expect { brew "--prefix", testball }
.to output(%r{#{HOMEBREW_CELLAR}/testball}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,15 @@
describe "brew --repository", :integration_test do
it "prints the path of the Homebrew repository" do
expect { brew "--repository" }
.to output("#{HOMEBREW_REPOSITORY}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "prints the path of a given Tap" do
expect { brew "--repository", "foo/bar" }
.to output("#{HOMEBREW_LIBRARY}/Taps/foo/homebrew-bar\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,8 @@
describe "brew --version", :integration_test do
it "prints the Homebrew version" do
expect { brew "--version" }
.to output(/^Homebrew #{Regexp.escape(HOMEBREW_VERSION.to_s)}\n/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,24 @@
describe "brew bundle", :integration_test, :needs_test_cmd_taps do
describe "check" do
it "checks if a Brewfile's dependencies are satisfied" do
setup_remote_tap "homebrew/bundle"
HOMEBREW_REPOSITORY.cd do
shutup do
system "git", "init"
system "git", "commit", "--allow-empty", "-m", "This is a test commit"
end
end
Dir.mktmpdir do |path|
FileUtils.touch "#{path}/Brewfile"
Dir.chdir path do
expect { brew "bundle", "check" }
.to output("The Brewfile's dependencies are satisfied.\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
end
end
end

View File

@ -0,0 +1,8 @@
describe "brew cask", :integration_test, :needs_macos, :needs_official_cmd_taps do
describe "list" do
it "returns a list of installed Casks" do
setup_remote_tap("caskroom/cask")
expect { brew "cask", "list" }.to be_a_success
end
end
end

View File

@ -0,0 +1,11 @@
describe "brew cat", :integration_test do
it "prints the content of a given Formula" do
formula_file = setup_test_formula "testball"
content = formula_file.read
expect { brew "cat", "testball" }
.to output(content).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,12 @@
describe "brew cleanup", :integration_test do
describe "--prune=all" do
it "removes all files in Homebrew's cache" do
(HOMEBREW_CACHE/"test").write "test"
expect { brew "cleanup", "--prune=all" }
.to output(%r{#{Regexp.escape(HOMEBREW_CACHE)}/test}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
end

View File

@ -0,0 +1,13 @@
describe "brew command", :integration_test do
it "returns the file for a given command" do
expect { brew "command", "info" }
.to output(%r{#{Regexp.escape(HOMEBREW_LIBRARY_PATH)}/cmd/info.rb}).to_stdout
.and be_a_success
end
it "fails when the given command is unknown" do
expect { brew "command", "does-not-exist" }
.to output(/Unknown command/).to_stderr
.and be_a_failure
end
end

View File

@ -0,0 +1,7 @@
describe "brew commands", :integration_test do
it "prints a list of all available commands" do
expect { brew "commands" }
.to output(/Built-in commands/).to_stdout
.and be_a_success
end
end

View File

@ -0,0 +1,8 @@
describe "brew config", :integration_test do
it "prints information about the current Homebrew configuration" do
expect { brew "config" }
.to output(/HOMEBREW_VERSION: #{HOMEBREW_VERSION}/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,21 @@
describe "brew custom-external-command", :integration_test do
it "is supported" do
Dir.mktmpdir do |path|
path = Pathname.new(path)
cmd = "custom-external-command-#{rand}"
file = path/"brew-#{cmd}"
file.write <<-EOS.undent
#!/bin/sh
echo 'I am #{cmd}.'
EOS
FileUtils.chmod "+x", file
expect { brew cmd, "PATH" => "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}" }
.to output("I am #{cmd}.\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
end

View File

@ -0,0 +1,40 @@
describe "brew desc", :integration_test do
let(:desc_cache) { HOMEBREW_CACHE/"desc_cache.json" }
it "shows a given Formula's description" do
setup_test_formula "testball"
expect { brew "desc", "testball" }
.to output("testball: Some test\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "fails when both --search and --name are specified" do
expect { brew "desc", "--search", "--name" }
.to output(/Pick one, and only one/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
end
describe "--search" do
it "fails when no search term is given" do
expect { brew "desc", "--search" }
.to output(/You must provide a search term/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
end
end
describe "--description" do
it "creates a description cache" do
expect(desc_cache).not_to exist
shutup do
expect { brew "desc", "--description", "testball" }.to be_a_success
end
expect(desc_cache).to exist
end
end
end

View File

@ -0,0 +1,6 @@
describe "brew doctor", :integration_test do
specify "check_integration_test" do
expect { brew "doctor", "check_integration_test" }
.to output(/This is an integration test/).to_stderr
end
end

View File

@ -0,0 +1,13 @@
describe "brew fetch", :integration_test do
it "downloads the Formula's URL" do
setup_test_formula "testball"
expect(HOMEBREW_CACHE/"testball-0.1.tbz").not_to exist
shutup do
expect { brew "fetch", "testball" }.to be_a_success
end
expect(HOMEBREW_CACHE/"testball-0.1.tbz").to exist
end
end

View File

@ -0,0 +1,47 @@
describe "brew", :integration_test do
it "prints help when no argument is given" do
expect { brew }
.to output(/Example usage:\n/).to_stderr
.and be_a_failure
end
describe "help" do
it "prints help" do
expect { brew "help" }
.to output(/Example usage:\n/).to_stdout
.and be_a_success
end
it "prints help for a documented Ruby command" do
expect { brew "help", "cat" }
.to output(/^brew cat/).to_stdout
.and be_a_success
end
it "prints help for a documented shell command" do
expect { brew "help", "update" }
.to output(/^brew update/).to_stdout
.and be_a_success
end
it "prints help for a documented Ruby developer command" do
expect { brew "help", "update-test" }
.to output(/^brew update-test/).to_stdout
.and be_a_success
end
it "fails when given an unknown command" do
expect { brew "help", "command-that-does-not-exist" }
.to output(/Unknown command: command-that-does-not-exist/).to_stderr
.and be_a_failure
end
end
describe "cat" do
it "prints help when no argument is given" do
expect { brew "cat" }
.to output(/^brew cat/).to_stderr
.and be_a_failure
end
end
end

View File

@ -0,0 +1,17 @@
describe "brew home", :integration_test do
it "opens the Homebrew homepage when no argument is given" do
expect { brew "home", "HOMEBREW_BROWSER" => "echo" }
.to output("#{HOMEBREW_WWW}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "opens the homepage for a given Formula" do
setup_test_formula "testball"
expect { brew "home", "testball", "HOMEBREW_BROWSER" => "echo" }
.to output("#{Formula["testball"].homepage}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,30 @@
require "cmd/info"
describe "brew info", :integration_test do
it "prints information about a given Formula" do
setup_test_formula "testball"
expect { brew "info", "testball" }
.to output(/testball: stable 0.1/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
describe Homebrew do
let(:remote) { "https://github.com/Homebrew/homebrew-core" }
specify "::github_remote_path" do
expect(subject.github_remote_path(remote, "Formula/git.rb"))
.to eq("https://github.com/Homebrew/homebrew-core/blob/master/Formula/git.rb")
expect(subject.github_remote_path("#{remote}.git", "Formula/git.rb"))
.to eq("https://github.com/Homebrew/homebrew-core/blob/master/Formula/git.rb")
expect(subject.github_remote_path("git@github.com:user/repo", "foo.rb"))
.to eq("https://github.com/user/repo/blob/master/foo.rb")
expect(subject.github_remote_path("https://mywebsite.com", "foo/bar.rb"))
.to eq("https://mywebsite.com/foo/bar.rb")
end
end

View File

@ -0,0 +1,243 @@
describe "brew install", :integration_test do
it "installs Formulae" do
setup_test_formula "testball1"
expect { brew "install", "testball1", "--head" }
.to output(/Specify `\-\-HEAD`/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
expect { brew "install", "testball1", "--HEAD" }
.to output(/No head is defined/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
expect { brew "install", "testball1", "--devel" }
.to output(/No devel block/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
expect { brew "install", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/0\.1}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "install", "testball1" }
.to output(/testball1\-0\.1 already installed/).to_stderr
.and not_to_output.to_stdout
.and be_a_success
expect { brew "install", "macruby" }
.to output(/MacRuby is not packaged/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
expect { brew "install", "formula" }
.to output(/No available formula/).to_stderr
.and output(/Searching for similarly named formulae/).to_stdout
.and be_a_failure
expect { brew "install", "testball" }
.to output(/This similarly named formula was found/).to_stdout
.and output(/No available formula/).to_stderr
.and be_a_failure
setup_test_formula "testball2"
expect { brew "install", "testball" }
.to output(/These similarly named formulae were found/).to_stdout
.and output(/No available formula/).to_stderr
.and be_a_failure
install_and_rename_coretap_formula "testball1", "testball2"
expect { brew "install", "testball2" }
.to output(/testball1 already installed, it's just not migrated/).to_stderr
.and output(/You can migrate formula with `brew migrate testball2`/).to_stdout
.and be_a_success
end
specify "install failures" do
path = setup_test_formula "testball1", <<-EOS.undent
version "1.0"
EOS
expect { brew "install", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
FileUtils.rm path
setup_test_formula "testball1", <<-EOS.undent
version "2.0"
devel do
url "#{Formulary.factory("testball1").stable.url}"
sha256 "#{TESTBALL_SHA256}"
version "3.0"
end
EOS
expect { brew "install", "testball1" }
.to output(/first `brew unlink testball1`/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
expect { brew "unlink", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "install", "testball1", "--devel" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/3\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "unlink", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/3\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "install", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/2\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
shutup do
expect { brew "switch", "testball1", "3.0" }.to be_a_success
end
expect { brew "install", "testball1" }
.to output(/already installed, however linked version is/).to_stderr
.and output(/`brew switch testball1 2.0`/).to_stdout
.and be_a_success
expect { brew "unlink", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/3\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "install", "testball1" }
.to output(/just not linked/).to_stderr
.and not_to_output.to_stdout
.and be_a_success
end
it "can install keg-only Formulae" do
path_keg_only = setup_test_formula "testball1", <<-EOS.undent
version "1.0"
keg_only "test reason"
EOS
expect { brew "install", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
FileUtils.rm path_keg_only
setup_test_formula "testball1", <<-EOS.undent
version "2.0"
keg_only "test reason"
EOS
expect { brew "install", "testball1" }
.to output(/keg-only and another version is linked to opt/).to_stderr
.and output(/Use `brew install --force`/).to_stdout
.and be_a_success
expect { brew "install", "testball1", "--force" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/2\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "can install HEAD Formulae" do
repo_path = HOMEBREW_CACHE.join("repo")
repo_path.join("bin").mkpath
repo_path.cd do
shutup do
system "git", "init"
system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo"
FileUtils.touch "bin/something.bin"
FileUtils.touch "README"
system "git", "add", "--all"
system "git", "commit", "-m", "Initial repo commit"
end
end
setup_test_formula "testball1", <<-EOS.undent
version "1.0"
head "file://#{repo_path}", :using => :git
def install
prefix.install Dir["*"]
end
EOS
# Ignore dependencies, because we'll try to resolve requirements in build.rb
# and there will be the git requirement, but we cannot instantiate git
# formula since we only have testball1 formula.
expect { brew "install", "testball1", "--HEAD", "--ignore-dependencies" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD\-d5eb689}).to_stdout
.and output(/Cloning into/).to_stderr
.and be_a_success
expect { brew "install", "testball1", "--HEAD", "--ignore-dependencies" }
.to output(/testball1\-HEAD\-d5eb689 already installed/).to_stderr
.and not_to_output.to_stdout
.and be_a_success
expect { brew "unlink", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD\-d5eb689}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "install", "testball1" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "ignores invalid options" do
setup_test_formula "testball1"
expect { brew "install", "testball1", "--with-fo" }
.to output(/testball1: this formula has no \-\-with\-fo option so it will be ignored!/).to_stderr
.and output(/Downloading file/).to_stdout
.and be_a_success
end
it "succeeds when a non-fatal requirement isn't satisfied" do
setup_test_formula "testball1", <<-EOS.undent
class NonFatalRequirement < Requirement
satisfy { false }
end
depends_on NonFatalRequirement
EOS
# FIXME: This should output to STDERR.
expect { brew "install", "testball1" }
.to output(/NonFatalRequirement unsatisfied!/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "fails when a fatal requirement isn't satisfied" do
setup_test_formula "testball1", <<-EOS.undent
class FatalRequirement < Requirement
fatal true
satisfy { false }
end
depends_on FatalRequirement
EOS
# FIXME: This should output to STDERR.
expect { brew "install", "testball1" }
.to output(/FatalRequirement unsatisfied!/).to_stdout
.and output(/An unsatisfied requirement failed this build./).to_stderr
.and be_a_failure
end
end

View File

@ -0,0 +1,24 @@
describe "brew irb", :integration_test do
it "starts an interactive Homebrew shell session" do
setup_test_formula "testball"
irb_test = HOMEBREW_TEMP/"irb-test.rb"
irb_test.write <<-EOS.undent
"testball".f
:testball.f
exit
EOS
expect { brew "irb", irb_test }
.to output(/Interactive Homebrew Shell/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
specify "--examples" do
expect { brew "irb", "--examples" }
.to output(/'v8'\.f # => instance of the v8 formula/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,23 @@
describe "brew leaves", :integration_test do
it "prints all Formulae that are not dependencies of other Formulae" do
setup_test_formula "foo"
setup_test_formula "bar"
expect { brew "leaves" }
.to be_a_success
.and not_to_output.to_stdout
.and not_to_output.to_stderr
(HOMEBREW_CELLAR/"foo/0.1/somedir").mkpath
expect { brew "leaves" }
.to output("foo\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
(HOMEBREW_CELLAR/"bar/0.1/somedir").mkpath
expect { brew "leaves" }
.to output("bar\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,56 @@
describe "brew link", :integration_test do
it "fails when no argument is given" do
expect { brew "link" }
.to output(/This command requires a keg argument/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
end
it "does not fail if the given Formula is already linked" do
setup_test_formula "testball1"
shutup do
expect { brew "install", "testball1" }.to be_a_success
expect { brew "link", "testball1" }.to be_a_success
end
end
it "links a given Formula" do
setup_test_formula "testball1"
shutup do
expect { brew "install", "testball1" }.to be_a_success
expect { brew "unlink", "testball1" }.to be_a_success
end
expect { brew "link", "--dry-run", "testball1" }
.to output(/Would link/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "link", "--dry-run", "--overwrite", "testball1" }
.to output(/Would remove/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "link", "testball1" }
.to output(/Linking/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "refuses to link keg-only Formulae" do
setup_test_formula "testball1", <<-EOS.undent
keg_only "just because"
EOS
shutup do
expect { brew "install", "testball1" }.to be_a_success
end
expect { brew "link", "testball1" }
.to output(/testball1 is keg-only/).to_stderr
.and output(/Note that doing so can interfere with building software\./).to_stdout
.and be_a_success
end
end

View File

@ -0,0 +1,24 @@
describe "brew linkapps", :integration_test do
let(:home_dir) { @home_dir = Pathname.new(Dir.mktmpdir) }
let(:apps_dir) { home_dir/"Applications" }
after(:each) do
home_dir.rmtree unless @home_dir.nil?
end
it "symlinks applications" do
apps_dir.mkpath
setup_test_formula "testball"
source_app = HOMEBREW_CELLAR/"testball/0.1/TestBall.app"
source_app.mkpath
expect { brew "linkapps", "--local", "HOME" => home_dir }
.to output(/Linking: #{Regexp.escape(source_app)}/).to_stdout
.and output(/`brew linkapps` has been deprecated/).to_stderr
.and be_a_success
expect(apps_dir/"TestBall.app").to be_a_symlink
end
end

View File

@ -0,0 +1,14 @@
describe "brew list", :integration_test do
let(:formulae) { %w[bar foo qux] }
it "prints all installed Formulae" do
formulae.each do |f|
(HOMEBREW_CELLAR/f/"1.0/somedir").mkpath
end
expect { brew "list" }
.to output("#{formulae.join("\n")}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,41 @@
describe "brew log", :integration_test do
it "shows the Git log for the Homebrew repository when no argument is given" do
HOMEBREW_REPOSITORY.cd do
shutup do
system "git", "init"
system "git", "commit", "--allow-empty", "-m", "This is a test commit"
end
end
expect { brew "log" }
.to output(/This is a test commit/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "shows the Git log for a given Formula" do
setup_test_formula "testball"
core_tap = CoreTap.new
core_tap.path.cd do
shutup do
system "git", "init"
system "git", "add", "--all"
system "git", "commit", "-m", "This is a test commit for Testball"
end
end
core_tap_url = "file://#{core_tap.path}"
shallow_tap = Tap.fetch("homebrew", "shallow")
shutup do
system "git", "clone", "--depth=1", core_tap_url, shallow_tap.path
end
expect { brew "log", "#{shallow_tap}/testball" }
.to output(/This is a test commit for Testball/).to_stdout
.and output(/Warning: The git repository is a shallow clone/).to_stderr
.and be_a_success
expect(shallow_tap.path/".git/shallow").to exist, "A shallow clone should have been created."
end
end

View File

@ -0,0 +1,46 @@
describe "brew migrate", :integration_test do
before(:each) do
setup_test_formula "testball1"
setup_test_formula "testball2"
end
it "fails when no argument is given" do
expect { brew "migrate" }
.to output(/Invalid usage/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
end
it "fails when a given Formula doesn't exist" do
expect { brew "migrate", "testball" }
.to output(/No available formula with the name "testball"/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
end
it "fails if a given Formula doesn't replace another one" do
expect { brew "migrate", "testball1" }
.to output(/testball1 doesn't replace any formula/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
end
it "migrates a renamed Formula" do
install_and_rename_coretap_formula "testball1", "testball2"
expect { brew "migrate", "testball1" }
.to output(/Migrating testball1 to testball2/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "fails if a given Formula is not installed" do
install_and_rename_coretap_formula "testball1", "testball2"
(HOMEBREW_CELLAR/"testball1").rmtree
expect { brew "migrate", "testball1" }
.to output(/Error: No such keg/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
end
end

View File

@ -0,0 +1,41 @@
describe "brew missing", :integration_test do
before(:each) do
setup_test_formula "foo"
setup_test_formula "bar"
end
def make_prefix(name)
(HOMEBREW_CELLAR/name/"1.0").mkpath
end
it "prints missing dependencies" do
make_prefix "bar"
expect { brew "missing" }
.to output("foo\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "prints nothing if all dependencies are installed" do
make_prefix "foo"
make_prefix "bar"
expect { brew "missing" }
.to be_a_success
.and not_to_output.to_stdout
.and not_to_output.to_stderr
end
describe "--hide=" do
it "pretends that the specified Formulae are not installed" do
make_prefix "foo"
make_prefix "bar"
expect { brew "missing", "--hide=foo" }
.to output("bar: foo\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
end

View File

@ -0,0 +1,12 @@
describe "brew options", :integration_test do
it "prints a given Formula's options" do
setup_test_formula "testball", <<-EOS.undent
depends_on "bar" => :recommended
EOS
expect { brew "options", "testball" }
.to output("--with-foo\n\tBuild with foo\n--without-bar\n\tBuild without bar support\n\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,11 @@
describe "brew outdated", :integration_test do
it "prints outdated Formulae" do
setup_test_formula "testball"
(HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
expect { brew "outdated" }
.to output("testball\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,13 @@
describe "brew pin", :integration_test do
it "pins a Formula's version" do
setup_test_formula "testball"
(HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
shutup do
expect { brew "pin", "testball" }.to be_a_success
expect { brew "upgrade" }.to be_a_success
end
expect(HOMEBREW_CELLAR/"testball/0.1").not_to be_a_directory
end
end

View File

@ -0,0 +1,28 @@
describe "brew prune", :integration_test do
it "removes empty directories and broken symlinks" do
share = (HOMEBREW_PREFIX/"share")
(share/"pruneable/directory/here").mkpath
(share/"notpruneable/file").write "I'm here"
FileUtils.ln_s "/i/dont/exist/no/really/i/dont", share/"pruneable_symlink"
expect { brew "prune", "--dry-run" }
.to output(%r{Would remove \(empty directory\): .*/pruneable/directory/here}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "prune" }
.to output(/Pruned 1 symbolic links and 3 directories/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect(share/"pruneable").not_to be_a_directory
expect(share/"notpruneable").to be_a_directory
expect(share/"pruneable_symlink").not_to be_a_symlink
expect { brew "prune", "--verbose" }
.to output(/Nothing pruned/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,20 @@
describe "brew readall", :integration_test do
it "imports all Formulae for a given Tap" do
formula_file = setup_test_formula "testball"
alias_file = CoreTap.new.alias_dir/"foobar"
alias_file.parent.mkpath
FileUtils.ln_s formula_file, alias_file
expect { brew "readall", "--aliases", "--syntax" }
.to be_a_success
.and not_to_output.to_stdout
.and not_to_output.to_stderr
expect { brew "readall", "homebrew/core" }
.to be_a_success
.and not_to_output.to_stdout
.and not_to_output.to_stderr
end
end

View File

@ -0,0 +1,44 @@
require "extend/ENV"
describe "brew reinstall", :integration_test do
before(:each) do
setup_test_formula "testball"
shutup do
expect { brew "install", "testball", "--with-foo" }.to be_a_success
end
end
it "reinstalls a Formula" do
foo_dir = HOMEBREW_CELLAR/"testball/0.1/foo"
expect(foo_dir).to exist
foo_dir.rmtree
expect { brew "reinstall", "testball" }
.to output(/Reinstalling testball --with-foo/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect(foo_dir).to exist
end
it "reinstalls a Formula even when one of the options is invalid" do
expect { brew "reinstall", "testball", "--with-fo" }
.to output(/Reinstalling testball --with-foo/).to_stdout
.and output(/testball: this formula has no \-\-with-fo option so it will be ignored!/).to_stderr
.and be_a_success
end
it "refuses to reinstall a pinned Formula, but doesn't fail" do
(HOMEBREW_CELLAR/"testball/0.1").mkpath
HOMEBREW_PINNED_KEGS.mkpath
FileUtils.ln_s HOMEBREW_CELLAR/"testball/0.1", HOMEBREW_PINNED_KEGS/"testball"
expect { brew "reinstall", "testball" }
.to output(/testball is pinned. You must unpin it to reinstall./).to_stderr
.and not_to_output.to_stdout
.and be_a_success
HOMEBREW_PINNED_KEGS.rmtree
end
end

View File

@ -0,0 +1,57 @@
describe "brew search", :integration_test do
before(:each) do
setup_test_formula "testball"
end
it "lists all available Formulae when no argument is given" do
expect { brew "search" }
.to output(/testball/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "supports searching by name" do
expect { brew "search", "testball" }
.to output(/testball/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
it "supports searching a fully-qualified name " do
expect { brew "search", "homebrew/homebrew-core/testball" }
.to output(/testball/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
describe "--desc" do
let(:desc_cache) { HOMEBREW_CACHE/"desc_cache.json" }
it "supports searching in descriptions and creates a description cache" do
expect(desc_cache).not_to exist
expect { brew "search", "--desc", "Some test" }
.to output(/testball/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect(desc_cache).to exist
end
end
{
"macports" => "https://www.macports.org/ports.php?by=name&substr=testball",
"fink" => "http://pdb.finkproject.org/pdb/browse.php?summary=testball",
"debian" => "https://packages.debian.org/search?keywords=testball&searchon=names&suite=all&section=all",
"opensuse" => "https://software.opensuse.org/search?q=testball",
"fedora" => "https://admin.fedoraproject.org/pkgdb/packages/%2Atestball%2A/",
"ubuntu" => "http://packages.ubuntu.com/search?keywords=testball&searchon=names&suite=all&section=all",
}.each do |flag, url|
specify "--#{flag}" do
expect { brew "search", "--#{flag}", "testball", "HOMEBREW_BROWSER" => "echo" }
.to output("#{url}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end
end

View File

@ -0,0 +1,10 @@
describe "brew services", :integration_test, :needs_macos, :needs_official_cmd_taps do
it "allows controlling services" do
setup_remote_tap "homebrew/services"
expect { brew "services", "list" }
.to output("Warning: No services available to control with `brew services`\n").to_stderr
.and not_to_output.to_stdout
.and be_a_success
end
end

View File

@ -0,0 +1,8 @@
describe "brew sh", :integration_test do
it "runs a shell with the Homebrew environment" do
expect { brew "sh", "SHELL" => which("true") }
.to output(/Your shell has been configured/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,34 @@
describe "brew switch", :integration_test do
it "allows switching between Formula versions" do
expect { brew "switch" }
.to output(/Usage: brew switch <name> <version>/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
expect { brew "switch", "testball", "0.1" }
.to output(/testball not found/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
setup_test_formula "testball", <<-EOS.undent
keg_only "just because"
EOS
shutup do
expect { brew "install", "testball" }.to be_a_success
end
testball_rack = HOMEBREW_CELLAR/"testball"
FileUtils.cp_r testball_rack/"0.1", testball_rack/"0.2"
expect { brew "switch", "testball", "0.2" }
.to output(/link created/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "switch", "testball", "0.3" }
.to output("Versions available: 0.1, 0.2\n").to_stdout
.and output(/testball does not have a version "0.3"/).to_stderr
.and be_a_failure
end
end

View File

@ -0,0 +1,10 @@
describe "brew tap-new", :integration_test do
it "initializes a new Tap with a ReadMe file" do
expect { brew "tap-new", "homebrew/foo", "--verbose" }
.to be_a_success
.and not_to_output.to_stdout
.and not_to_output.to_stderr
expect(HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo/README.md").to exist
end
end

View File

@ -0,0 +1,12 @@
describe "brew uninstall", :integration_test do
it "uninstalls a given Formula" do
shutup do
expect { brew "install", testball }.to be_a_success
end
expect { brew "uninstall", "--force", testball }
.to output(/Uninstalling testball/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,14 @@
describe "brew unlink", :integration_test do
it "unlinks a Formula" do
setup_test_formula "testball"
shutup do
expect { brew "install", "testball" }.to be_a_success
end
expect { brew "unlink", "--dry-run", "testball" }
.to output(/Would remove/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,24 @@
describe "brew unlinkapps", :integration_test do
let(:home_dir) { @home_dir = Pathname.new(Dir.mktmpdir) }
let(:apps_dir) { home_dir/"Applications" }
after(:each) do
home_dir.rmtree unless @home_dir.nil?
end
it "unlinks symlinked applications" do
apps_dir.mkpath
setup_test_formula "testball"
source_app = HOMEBREW_CELLAR/"testball/0.1/TestBall.app"
source_app.mkpath
FileUtils.ln_s source_app, apps_dir/"TestBall.app"
expect { brew "unlinkapps", "--local", "HOME" => home_dir }
.to output(%r{Unlinking: #{Regexp.escape(apps_dir)}/TestBall.app}).to_stdout
.and output(/`brew unlinkapps` has been deprecated/).to_stderr
.and be_a_success
end
end

View File

@ -0,0 +1,16 @@
describe "brew unpack", :integration_test do
it "unpacks a given Formula's archive" do
setup_test_formula "testball"
Dir.mktmpdir do |path|
path = Pathname.new(path)
shutup do
expect { brew "unpack", "testball", "--destdir=#{path}" }
.to be_a_success
end
expect(path/"testball-0.1").to be_a_directory
end
end
end

View File

@ -0,0 +1,14 @@
describe "brew unpin", :integration_test do
it "unpins a Formula's version" do
setup_test_formula "testball"
(HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
shutup do
expect { brew "pin", "testball" }.to be_a_success
expect { brew "unpin", "testball" }.to be_a_success
expect { brew "upgrade" }.to be_a_success
end
expect(HOMEBREW_CELLAR/"testball/0.1").to be_a_directory
end
end

View File

@ -0,0 +1,127 @@
require "cmd/update-report"
require "formula_versions"
require "yaml"
describe Reporter do
def perform_update(fixture_name = "")
allow(Formulary).to receive(:factory).and_return(double(pkg_version: "1.0"))
allow(FormulaVersions).to receive(:new).and_return(double(formula_at_revision: "2.0"))
diff = YAML.load_file("#{TEST_FIXTURE_DIR}/updater_fixture.yaml")[fixture_name]
allow(subject).to receive(:diff).and_return(diff || "")
hub.add(subject) if subject.updated?
end
let(:reporter_class) do
Class.new(described_class) do
def initialize(tap)
@tap = tap
ENV["HOMEBREW_UPDATE_BEFORE#{repo_var}"] = "12345678"
ENV["HOMEBREW_UPDATE_AFTER#{repo_var}"] = "abcdef00"
super(tap)
end
end
end
subject { reporter_class.new(tap) }
let(:tap) { CoreTap.new }
let(:hub) { ReporterHub.new }
specify "without revision variable" do
ENV.delete_if { |k, _v| k.start_with? "HOMEBREW_UPDATE" }
expect {
described_class.new(tap)
}.to raise_error(Reporter::ReporterRevisionUnsetError)
end
specify "without any changes" do
perform_update
expect(hub).to be_empty
end
specify "without Formula changes" do
perform_update("update_git_diff_output_without_formulae_changes")
expect(hub.select_formula(:M)).to be_empty
expect(hub.select_formula(:A)).to be_empty
expect(hub.select_formula(:D)).to be_empty
end
specify "with Formula changes" do
perform_update("update_git_diff_output_with_formulae_changes")
expect(hub.select_formula(:M)).to eq(%w[xar yajl])
expect(hub.select_formula(:A)).to eq(%w[antiword bash-completion ddrescue dict lua])
end
specify "with removed Formulae" do
perform_update("update_git_diff_output_with_removed_formulae")
expect(hub.select_formula(:D)).to eq(%w[libgsasl])
end
specify "with changed file type" do
perform_update("update_git_diff_output_with_changed_filetype")
expect(hub.select_formula(:M)).to eq(%w[elixir])
expect(hub.select_formula(:A)).to eq(%w[libbson])
expect(hub.select_formula(:D)).to eq(%w[libgsasl])
end
specify "with renamed Formula" do
allow(tap).to receive(:formula_renames).and_return("cv" => "progress")
perform_update("update_git_diff_output_with_formula_rename")
expect(hub.select_formula(:A)).to be_empty
expect(hub.select_formula(:D)).to be_empty
expect(hub.select_formula(:R)).to eq([["cv", "progress"]])
end
context "when updating a Tap other than the core Tap" do
let(:tap) { Tap.new("foo", "bar") }
before(:each) do
(tap.path/"Formula").mkpath
end
after(:each) do
tap.path.parent.rmtree
end
specify "with restructured Tap" do
perform_update("update_git_diff_output_with_restructured_tap")
expect(hub.select_formula(:A)).to be_empty
expect(hub.select_formula(:D)).to be_empty
expect(hub.select_formula(:R)).to be_empty
end
specify "with renamed Formula and restructured Tap" do
allow(tap).to receive(:formula_renames).and_return("xchat" => "xchat2")
perform_update("update_git_diff_output_with_formula_rename_and_restructuring")
expect(hub.select_formula(:A)).to be_empty
expect(hub.select_formula(:D)).to be_empty
expect(hub.select_formula(:R)).to eq([%w[foo/bar/xchat foo/bar/xchat2]])
end
specify "with simulated 'homebrew/php' restructuring" do
perform_update("update_git_diff_simulate_homebrew_php_restructuring")
expect(hub.select_formula(:A)).to be_empty
expect(hub.select_formula(:D)).to be_empty
expect(hub.select_formula(:R)).to be_empty
end
specify "with Formula changes" do
perform_update("update_git_diff_output_with_tap_formulae_changes")
expect(hub.select_formula(:A)).to eq(%w[foo/bar/lua])
expect(hub.select_formula(:M)).to eq(%w[foo/bar/git])
expect(hub.select_formula(:D)).to be_empty
end
end
end

View File

@ -0,0 +1,12 @@
describe "brew upgrade", :integration_test do
it "upgrades a Formula to the latest version" do
setup_test_formula "testball"
(HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
shutup do
expect { brew "upgrade" }.to be_a_success
end
expect(HOMEBREW_CELLAR/"testball/0.1").to be_a_directory
end
end

View File

@ -0,0 +1,25 @@
describe "brew uses", :integration_test do
it "prints the Formulae a given Formula is used by" do
setup_test_formula "foo"
setup_test_formula "bar"
setup_test_formula "baz", <<-EOS.undent
url "https://example.com/baz-1.0"
depends_on "bar"
EOS
expect { brew "uses", "baz" }
.to be_a_success
.and not_to_output.to_stdout
.and not_to_output.to_stderr
expect { brew "uses", "bar" }
.to output("baz\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "uses", "--recursive", "foo" }
.to output(/(bar\nbaz|baz\nbar)/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
end

View File

@ -1,11 +0,0 @@
require "testing_env"
class IntegrationCommandTestCommand < IntegrationCommandTestCase
def test_command
assert_equal "#{HOMEBREW_LIBRARY_PATH}/cmd/info.rb",
cmd("command", "info")
assert_match "Unknown command",
cmd_fail("command", "I-don't-exist")
end
end

View File

@ -4,13 +4,6 @@ require "cmd/commands"
require "fileutils" require "fileutils"
require "testing_env" require "testing_env"
class IntegrationCommandTestCommands < IntegrationCommandTestCase
def test_commands
assert_match "Built-in commands",
cmd("commands")
end
end
class CommandsTests < Homebrew::TestCase class CommandsTests < Homebrew::TestCase
def setup def setup
super super

View File

@ -0,0 +1,122 @@
require "compilers"
require "software_spec"
describe CompilerSelector do
subject { described_class.new(software_spec, versions, compilers) }
let(:compilers) { [:clang, :gcc, :llvm, :gnu] }
let(:software_spec) { SoftwareSpec.new }
let(:cc) { :clang }
let(:versions) do
double(
gcc_4_0_build_version: Version::NULL,
gcc_build_version: Version.create("5666"),
llvm_build_version: Version::NULL,
clang_build_version: Version.create("425"),
)
end
before(:each) do
allow(versions).to receive(:non_apple_gcc_version) do |name|
case name
when "gcc-4.8" then Version.create("4.8.1")
when "gcc-4.7" then Version.create("4.7.1")
else Version::NULL
end
end
end
describe "#compiler" do
it "raises an error if no matching compiler can be found" do
software_spec.fails_with(:clang)
software_spec.fails_with(:llvm)
software_spec.fails_with(:gcc)
software_spec.fails_with(gcc: "4.8")
software_spec.fails_with(gcc: "4.7")
expect { subject.compiler }.to raise_error(CompilerSelectionError)
end
it "defaults to cc" do
expect(subject.compiler).to eq(cc)
end
it "returns gcc if it fails with clang" do
software_spec.fails_with(:clang)
expect(subject.compiler).to eq(:gcc)
end
it "returns clang if it fails with llvm" do
software_spec.fails_with(:llvm)
expect(subject.compiler).to eq(:clang)
end
it "returns clang if it fails with gcc" do
software_spec.fails_with(:gcc)
expect(subject.compiler).to eq(:clang)
end
it "returns clang if it fails with non-Apple gcc" do
software_spec.fails_with(gcc: "4.8")
expect(subject.compiler).to eq(:clang)
end
it "still returns gcc-4.8 if it fails with gcc without a specific version" do
software_spec.fails_with(:clang)
software_spec.fails_with(:gcc)
expect(subject.compiler).to eq("gcc-4.8")
end
it "returns gcc if it fails with clang and llvm" do
software_spec.fails_with(:clang)
software_spec.fails_with(:llvm)
expect(subject.compiler).to eq(:gcc)
end
it "returns clang if it fails with gcc and llvm" do
software_spec.fails_with(:gcc)
software_spec.fails_with(:llvm)
expect(subject.compiler).to eq(:clang)
end
example "returns gcc if it fails with a specific gcc version" do
software_spec.fails_with(:clang)
software_spec.fails_with(gcc: "4.8")
expect(subject.compiler).to eq(:gcc)
end
example "returns a lower version of gcc if it fails with the highest version" do
software_spec.fails_with(:clang)
software_spec.fails_with(:gcc)
software_spec.fails_with(:llvm)
software_spec.fails_with(gcc: "4.8")
expect(subject.compiler).to eq("gcc-4.7")
end
it "prefers gcc" do
software_spec.fails_with(:clang)
software_spec.fails_with(:gcc)
expect(subject.compiler).to eq("gcc-4.8")
end
it "raises an error when gcc is missing" do
allow(versions).to receive(:gcc_build_version).and_return(Version::NULL)
software_spec.fails_with(:clang)
software_spec.fails_with(:llvm)
software_spec.fails_with(gcc: "4.8")
software_spec.fails_with(gcc: "4.7")
expect { subject.compiler }.to raise_error(CompilerSelectionError)
end
it "raises an error when llvm and gcc are missing" do
allow(versions).to receive(:gcc_build_version).and_return(Version::NULL)
software_spec.fails_with(:clang)
software_spec.fails_with(gcc: "4.8")
software_spec.fails_with(gcc: "4.7")
expect { subject.compiler }.to raise_error(CompilerSelectionError)
end
end
end

View File

@ -1,117 +0,0 @@
require "testing_env"
require "compilers"
require "software_spec"
class CompilerSelectorTests < Homebrew::TestCase
class Double < SoftwareSpec
def <<(cc)
fails_with(cc)
self
end
end
class CompilerVersions
attr_accessor :gcc_4_0_build_version, :gcc_build_version,
:clang_build_version
def initialize
@gcc_4_0_build_version = Version::NULL
@gcc_build_version = Version.create("5666")
@llvm_build_version = Version::NULL
@clang_build_version = Version.create("425")
end
def non_apple_gcc_version(name)
case name
when "gcc-4.8" then Version.create("4.8.1")
when "gcc-4.7" then Version.create("4.7.1")
else Version::NULL
end
end
end
def setup
super
@f = Double.new
@cc = :clang
@versions = CompilerVersions.new
@selector = CompilerSelector.new(
@f, @versions, [:clang, :gcc, :llvm, :gnu]
)
end
def actual_cc
@selector.compiler
end
def test_all_compiler_failures
@f << :clang << :llvm << :gcc << { gcc: "4.8" } << { gcc: "4.7" }
assert_raises(CompilerSelectionError) { actual_cc }
end
def test_no_compiler_failures
assert_equal @cc, actual_cc
end
def test_fails_with_clang
@f << :clang
assert_equal :gcc, actual_cc
end
def test_fails_with_llvm
@f << :llvm
assert_equal :clang, actual_cc
end
def test_fails_with_gcc
@f << :gcc
assert_equal :clang, actual_cc
end
def test_fails_with_non_apple_gcc
@f << { gcc: "4.8" }
assert_equal :clang, actual_cc
end
def test_mixed_failures_1
@f << :clang << :gcc
assert_equal "gcc-4.8", actual_cc
end
def test_mixed_failures_2
@f << :clang << :llvm
assert_equal :gcc, actual_cc
end
def test_mixed_failures_3
@f << :gcc << :llvm
assert_equal :clang, actual_cc
end
def test_mixed_failures_4
@f << :clang << { gcc: "4.8" }
assert_equal :gcc, actual_cc
end
def test_mixed_failures_5
@f << :clang << :gcc << :llvm << { gcc: "4.8" }
assert_equal "gcc-4.7", actual_cc
end
def test_gcc_precedence
@f << :clang << :gcc
assert_equal "gcc-4.8", actual_cc
end
def test_missing_gcc
@versions.gcc_build_version = Version::NULL
@f << :clang << :llvm << { gcc: "4.8" } << { gcc: "4.7" }
assert_raises(CompilerSelectionError) { actual_cc }
end
def test_missing_llvm_and_gcc
@versions.gcc_build_version = Version::NULL
@f << :clang << { gcc: "4.8" } << { gcc: "4.7" }
assert_raises(CompilerSelectionError) { actual_cc }
end
end

Some files were not shown because too many files have changed in this diff Show More