Clean up code style and remove .rubocop_todo.yml.

This commit is contained in:
Markus Reiter 2017-10-07 00:31:28 +02:00
parent 91ab116ace
commit 175ca909ee
44 changed files with 296 additions and 421 deletions

View File

@ -1,6 +1,5 @@
inherit_from: inherit_from:
- ../.rubocop.yml - ../.rubocop.yml
- .rubocop_todo.yml
AllCops: AllCops:
Include: Include:
@ -26,9 +25,26 @@ Lint/NestedMethodDefinition:
Lint/ParenthesesAsGroupedExpression: Lint/ParenthesesAsGroupedExpression:
Enabled: true Enabled: true
Metrics/BlockNesting:
Max: 5
Metrics/ModuleLength:
Max: 360
Metrics/ParameterLists: Metrics/ParameterLists:
CountKeywordArgs: false CountKeywordArgs: false
# we won't change backward compatible method names
Naming/MethodName:
Exclude:
- 'compat/**/*'
# we won't change backward compatible predicate names
Naming/PredicateName:
Exclude:
- 'compat/**/*'
NameWhitelist: is_32_bit?, is_64_bit?
Style/BlockDelimiters: Style/BlockDelimiters:
Exclude: Exclude:
- '**/*_spec.rb' - '**/*_spec.rb'
@ -41,14 +57,3 @@ Style/GuardClause:
# hash-rockets preferred for formulae, a: 1 preferred elsewhere # hash-rockets preferred for formulae, a: 1 preferred elsewhere
Style/HashSyntax: Style/HashSyntax:
EnforcedStyle: ruby19_no_mixed_keys EnforcedStyle: ruby19_no_mixed_keys
# we won't change backward compatible method names
Naming/MethodName:
Exclude:
- 'compat/**/*'
# we won't change backward compatible predicate names
Naming/PredicateName:
Exclude:
- 'compat/**/*'
NameWhitelist: is_32_bit?, is_64_bit?

View File

@ -1,138 +0,0 @@
# This configuration was generated by
# `rubocop --auto-gen-config --exclude-limit 100`
# on 2017-01-27 21:44:55 +0000 using RuboCop version 0.47.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 17
Lint/HandleExceptions:
Exclude:
- 'cmd/install.rb'
- 'cmd/reinstall.rb'
- 'cmd/tap.rb'
- 'cmd/update-report.rb'
- 'cmd/upgrade.rb'
- 'cmd/uses.rb'
- 'descriptions.rb'
- 'diagnostic.rb'
- 'extend/ENV/super.rb'
- 'extend/pathname.rb'
- 'formula.rb'
- 'formula_versions.rb'
- 'test/ENV_test.rb'
# Offense count: 3
Lint/IneffectiveAccessModifier:
Exclude:
- 'formula.rb'
- 'version.rb'
# Offense count: 1
Lint/Loop:
Exclude:
- 'patch.rb'
# Offense count: 28
Lint/RescueException:
Exclude:
- 'brew.rb'
- 'build.rb'
- 'cmd/fetch.rb'
- 'cmd/reinstall.rb'
- 'cmd/update-report.rb'
- 'debrew.rb'
- 'dev-cmd/pull.rb'
- 'dev-cmd/test.rb'
- 'formula.rb'
- 'formula_installer.rb'
- 'migrator.rb'
- 'postinstall.rb'
- 'readall.rb'
- 'test.rb'
- 'test/ENV_test.rb'
- 'utils/fork.rb'
# Offense count: 1
Lint/ShadowedException:
Exclude:
- 'utils/fork.rb'
# Offense count: 13
# Configuration parameters: CountBlocks.
Metrics/BlockNesting:
Max: 5
# Offense count: 19
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 400
# Offense count: 1
# Configuration parameters: CountKeywordArgs.
Metrics/ParameterLists:
Max: 6
# Offense count: 2
Security/MarshalLoad:
Exclude:
- 'dependency.rb'
- 'utils/fork.rb'
# Offense count: 1
Naming/AccessorMethodName:
Exclude:
- 'extend/ENV/super.rb'
# Offense count: 6
Style/ClassVars:
Exclude:
- 'dev-cmd/audit.rb'
- 'formula_installer.rb'
- 'test/support/helper/fs_leak_logger.rb'
# Offense count: 13
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: compact, expanded
Style/EmptyMethod:
Exclude:
- 'debrew/irb.rb'
- 'download_strategy.rb'
- 'extend/ENV/super.rb'
- 'formula.rb'
- 'patch.rb'
# Offense count: 13
# Configuration parameters: AllowedVariables.
Style/GlobalVars:
Exclude:
- 'diagnostic.rb'
- 'utils.rb'
# Offense count: 1
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: module_function, extend_self
Style/ModuleFunction:
Exclude:
- 'os/mac/xcode.rb'
# Offense count: 8
Style/MultilineBlockChain:
Exclude:
- 'cmd/search.rb'
- 'dev-cmd/aspell-dictionaries.rb'
- 'dev-cmd/audit.rb'
- 'dev-cmd/man.rb'
- 'diagnostic.rb'
- 'test/patching_test.rb'
# Offense count: 4
# Cop supports --auto-correct.
Style/MutableConstant:
Exclude:
- 'dependency_collector.rb'
- 'formulary.rb'
- 'tab.rb'
- 'tap.rb'

View File

@ -146,7 +146,7 @@ rescue MethodDeprecatedError => e
$stderr.puts " #{Formatter.url(e.issues_url)}" $stderr.puts " #{Formatter.url(e.issues_url)}"
end end
exit 1 exit 1
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe e onoe e
if internal_cmd && defined?(OS::ISSUES_URL) && if internal_cmd && defined?(OS::ISSUES_URL) &&
!ENV["HOMEBREW_NO_AUTO_UPDATE"] !ENV["HOMEBREW_NO_AUTO_UPDATE"]

View File

@ -190,7 +190,7 @@ begin
options = Options.create(ARGV.flags_only) options = Options.create(ARGV.flags_only)
build = Build.new(formula, options) build = Build.new(formula, options)
build.install build.install
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe) Marshal.dump(e, error_pipe)
error_pipe.close error_pipe.close
exit! 1 exit! 1

View File

@ -49,8 +49,10 @@ module Homebrew
if fetch_bottle?(f) if fetch_bottle?(f)
begin begin
fetch_formula(f.bottle) fetch_formula(f.bottle)
rescue Exception => e rescue Interrupt
raise if ARGV.homebrew_developer? || e.is_a?(Interrupt) raise
rescue => e
raise if ARGV.homebrew_developer?
fetched_bottle = false fetched_bottle = false
onoe e.message onoe e.message
opoo "Bottle fetch failed: fetching the source." opoo "Bottle fetch failed: fetching the source."

View File

@ -339,6 +339,7 @@ module Homebrew
rescue FormulaInstallationAlreadyAttemptedError rescue FormulaInstallationAlreadyAttemptedError
# We already attempted to install f as part of the dependency tree of # We already attempted to install f as part of the dependency tree of
# another formula. In that case, don't generate an error, just move on. # another formula. In that case, don't generate an error, just move on.
return
rescue CannotInstallFormulaError => e rescue CannotInstallFormulaError => e
ofail e.message ofail e.message
end end

View File

@ -47,8 +47,8 @@ module Homebrew
fi.install fi.install
fi.finish fi.finish
rescue FormulaInstallationAlreadyAttemptedError rescue FormulaInstallationAlreadyAttemptedError
# next return
rescue Exception rescue Exception # rubocop:disable Lint/RescueException
ignore_interrupts { restore_backup(keg, keg_was_linked) } ignore_interrupts { restore_backup(keg, keg_was_linked) }
raise raise
else else

View File

@ -117,6 +117,7 @@ module Homebrew
case output_type case output_type
when :print when :print
args << "--debug" if ARGV.debug?
args << "--display-cop-names" if ARGV.include? "--display-cop-names" args << "--display-cop-names" if ARGV.include? "--display-cop-names"
args << "--format" << "simple" if files args << "--format" << "simple" if files
system(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", *args) system(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", *args)

View File

@ -54,8 +54,7 @@ module Homebrew
quiet: ARGV.quieter? quiet: ARGV.quieter?
rescue TapRemoteMismatchError => e rescue TapRemoteMismatchError => e
odie e odie e
rescue TapAlreadyTappedError, TapAlreadyUnshallowError rescue TapAlreadyTappedError, TapAlreadyUnshallowError # rubocop:disable Lint/HandleExceptions
# Do nothing.
end end
end end
end end

View File

@ -372,7 +372,7 @@ class Reporter
new_version = formula.pkg_version new_version = formula.pkg_version
old_version = FormulaVersions.new(formula).formula_at_revision(@initial_revision, &:pkg_version) old_version = FormulaVersions.new(formula).formula_at_revision(@initial_revision, &:pkg_version)
next if new_version == old_version next if new_version == old_version
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer? onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer?
end end
@report[:M] << tap.formula_file_to_name(src) @report[:M] << tap.formula_file_to_name(src)
@ -460,7 +460,7 @@ class Reporter
unless Formulary.factory(new_full_name).keg_only? unless Formulary.factory(new_full_name).keg_only?
system HOMEBREW_BREW_FILE, "link", new_full_name, "--overwrite" system HOMEBREW_BREW_FILE, "link", new_full_name, "--overwrite"
end end
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer? onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer?
end end
next next
@ -521,7 +521,7 @@ class Reporter
begin begin
f = Formulary.factory(new_full_name) f = Formulary.factory(new_full_name)
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer? onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer?
next next
end end

View File

@ -150,6 +150,7 @@ module Homebrew
rescue FormulaInstallationAlreadyAttemptedError rescue FormulaInstallationAlreadyAttemptedError
# We already attempted to upgrade f as part of the dependency tree of # We already attempted to upgrade f as part of the dependency tree of
# another formula. In that case, don't generate an error, just move on. # another formula. In that case, don't generate an error, just move on.
return
rescue CannotInstallFormulaError => e rescue CannotInstallFormulaError => e
ofail e ofail e
rescue BuildError => e rescue BuildError => e

View File

@ -74,12 +74,13 @@ module Homebrew
end end
end end
dep_formulae = deps.map do |dep| dep_formulae = deps.flat_map do |dep|
begin begin
dep.to_formula dep.to_formula
rescue rescue
[]
end
end end
end.compact
reqs_by_formula = ([f] + dep_formulae).flat_map do |formula| reqs_by_formula = ([f] + dep_formulae).flat_map do |formula|
formula.requirements.map { |req| [formula, req] } formula.requirements.map { |req| [formula, req] }
@ -118,6 +119,7 @@ module Homebrew
rescue FormulaUnavailableError rescue FormulaUnavailableError
# Silently ignore this case as we don't care about things used in # Silently ignore this case as we don't care about things used in
# taps that aren't currently tapped. # taps that aren't currently tapped.
next
end end
end end
end end

View File

@ -9,7 +9,7 @@ module Debrew
module Raise module Raise
def raise(*) def raise(*)
super super
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
e.extend(Ignorable) e.extend(Ignorable)
super(e) unless Debrew.debug(e) == :ignore super(e) unless Debrew.debug(e) == :ignore
end end
@ -92,7 +92,7 @@ module Debrew
yield yield
rescue SystemExit rescue SystemExit
original_raise original_raise
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
debug(e) debug(e)
ensure ensure
@active = false @active = false
@ -119,7 +119,7 @@ module Debrew
if e.is_a?(Ignorable) if e.is_a?(Ignorable)
menu.choice(:irb) do menu.choice(:irb) do
puts "When you exit this IRB session, execution will continue." puts "When you exit this IRB session, execution will continue."
set_trace_func proc { |event, _, _, id, binding, klass| set_trace_func proc { |event, _, _, id, binding, klass| # rubocop:disable Metrics/ParameterLists
if klass == Raise && id == :raise && event == "return" if klass == Raise && id == :raise && event == "return"
set_trace_func(nil) set_trace_func(nil)
synchronize { IRB.start_within(binding) } synchronize { IRB.start_within(binding) }

View File

@ -4,8 +4,7 @@ module IRB
@setup_done = false @setup_done = false
extend Module.new { extend Module.new {
def parse_opts def parse_opts; end
end
def start_within(binding) def start_within(binding)
unless @setup_done unless @setup_done

View File

@ -64,7 +64,7 @@ class Dependency
end end
def self._load(marshaled) def self._load(marshaled)
new(*Marshal.load(marshaled)) new(*Marshal.load(marshaled)) # rubocop:disable Security/MarshalLoad
end end
class << self class << self

View File

@ -4,6 +4,7 @@ require "ld64_dependency"
require "requirement" require "requirement"
require "requirements" require "requirements"
require "set" require "set"
require "extend/cachable"
## A dependency is a formula that another formula needs to install. ## A dependency is a formula that another formula needs to install.
## A requirement is something other than a formula that another formula ## A requirement is something other than a formula that another formula
@ -16,17 +17,13 @@ require "set"
# This class is used by `depends_on` in the formula DSL to turn dependency # This class is used by `depends_on` in the formula DSL to turn dependency
# specifications into the proper kinds of dependencies and requirements. # specifications into the proper kinds of dependencies and requirements.
class DependencyCollector class DependencyCollector
extend Cachable
# Define the languages that we can handle as external dependencies. # Define the languages that we can handle as external dependencies.
LANGUAGE_MODULES = Set[ LANGUAGE_MODULES = Set[
:lua, :lua51, :perl, :python, :python3, :ruby :lua, :lua51, :perl, :python, :python3, :ruby
].freeze ].freeze
CACHE = {}
def self.clear_cache
CACHE.clear
end
attr_reader :deps, :requirements attr_reader :deps, :requirements
def initialize def initialize
@ -45,7 +42,7 @@ class DependencyCollector
end end
def fetch(spec) def fetch(spec)
CACHE.fetch(cache_key(spec)) { |key| CACHE[key] = build(spec) } self.class.cache.fetch(cache_key(spec)) { |key| self.class.cache[key] = build(spec) }
end end
def cache_key(spec) def cache_key(spec)

View File

@ -78,10 +78,10 @@ class Descriptions
formula_names.each do |name| formula_names.each do |name|
begin begin
desc = Formulary.factory(name).desc @cache[name] = Formulary.factory(name).desc
rescue FormulaUnavailableError, *FormulaVersions::IGNORED_EXCEPTIONS rescue FormulaUnavailableError, *FormulaVersions::IGNORED_EXCEPTIONS
@cache.delete(name)
end end
@cache[name] = desc
end end
save_cache if options[:save] save_cache if options[:save]
end end

View File

@ -27,13 +27,12 @@ module Homebrew
end end
end end
languages.inject([]) do |resources, (lang, path)| languages.each do |lang, path|
r = Resource.new(lang) r = Resource.new(lang)
r.owner = Formulary.factory("aspell") r.owner = Formulary.factory("aspell")
r.url "#{dict_url}/#{path}" r.url "#{dict_url}/#{path}"
r.mirror "#{dict_mirror}/#{path}" r.mirror "#{dict_mirror}/#{path}"
resources << r r.fetch
end.each(&:fetch).each do |r|
puts <<-EOS puts <<-EOS
option "with-lang-#{r.name}", "Install #{r.name} dictionary" option "with-lang-#{r.name}", "Install #{r.name} dictionary"
resource "#{r.name}" do resource "#{r.name}" do

View File

@ -53,7 +53,7 @@ module Homebrew
module_function module_function
def audit def audit
Homebrew.inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D" inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D"
Homebrew.auditing = true Homebrew.auditing = true
formula_count = 0 formula_count = 0
@ -387,8 +387,10 @@ class FormulaAuditor
end end
end end
def self.aliases
# core aliases + tap alias names + tap alias full name # core aliases + tap alias names + tap alias full name
@@aliases ||= Formula.aliases + Formula.tap_aliases @aliases ||= Formula.aliases + Formula.tap_aliases
end
def audit_formula_name def audit_formula_name
return unless @strict return unless @strict
@ -442,7 +444,7 @@ 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 self.class.aliases.include?(dep.name) &&
(dep_f.core_formula? || !dep_f.versioned_formula?) (dep_f.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
@ -453,16 +455,16 @@ class FormulaAuditor
problem "Dependency '#{dep.name}' may be unnecessary as it is provided by macOS; try to build this formula without it." problem "Dependency '#{dep.name}' may be unnecessary as it is provided by macOS; try to build this formula without it."
end end
dep.options.reject do |opt| dep.options.each do |opt|
next true if dep_f.option_defined?(opt) next if dep_f.option_defined?(opt)
dep_f.requirements.detect do |r| next if dep_f.requirements.detect do |r|
if r.recommended? if r.recommended?
opt.name == "with-#{r.name}" opt.name == "with-#{r.name}"
elsif r.optional? elsif r.optional?
opt.name == "without-#{r.name}" opt.name == "without-#{r.name}"
end end
end end
end.each do |opt|
problem "Dependency #{dep} does not define option #{opt.name.inspect}" problem "Dependency #{dep} does not define option #{opt.name.inspect}"
end end

View File

@ -75,7 +75,7 @@ module Homebrew
@put_filenames ||= [] @put_filenames ||= []
return if @put_filenames.include? filename return if @put_filenames.include?(filename)
puts Formatter.error(filename.to_s) puts Formatter.error(filename.to_s)
@put_filenames << filename @put_filenames << filename
@ -84,8 +84,7 @@ module Homebrew
result = false result = false
keg.each_unique_file_matching(string) do |file| keg.each_unique_file_matching(string) do |file|
# skip document file. next if Metafiles::EXTENSIONS.include?(file.extname) # Skip document files.
next if Metafiles::EXTENSIONS.include? file.extname
linked_libraries = Keg.file_linked_libraries(file, string) linked_libraries = Keg.file_linked_libraries(file, string)
result ||= !linked_libraries.empty? result ||= !linked_libraries.empty?
@ -156,9 +155,7 @@ module Homebrew
return ofail "Formula not installed or up-to-date: #{f.full_name}" return ofail "Formula not installed or up-to-date: #{f.full_name}"
end end
tap = f.tap unless tap = f.tap
unless tap
unless ARGV.include?("--force-core-tap") unless ARGV.include?("--force-core-tap")
return ofail "Formula not from core or any taps: #{f.full_name}" return ofail "Formula not from core or any taps: #{f.full_name}"
end end

View File

@ -48,12 +48,9 @@ module Homebrew
def path_glob_commands(glob) def path_glob_commands(glob)
Pathname.glob(glob) Pathname.glob(glob)
.sort_by { |source_file| sort_key_for_path(source_file) } .sort_by { |source_file| sort_key_for_path(source_file) }
.map do |source_file| .map(&:read).map(&:lines)
source_file.read.lines .map { |lines| lines.grep(/^#:/).map { |line| line.slice(2..-1) }.join }
.grep(/^#:/) .reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") }
.map { |line| line.slice(2..-1) }
.join
end.reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") }
end end
def build_man_page def build_man_page

View File

@ -154,8 +154,8 @@ module Homebrew
begin begin
f = Formula[name] f = Formula[name]
rescue Exception # rubocop:disable Lint/RescueException
# Make sure we catch syntax errors. # Make sure we catch syntax errors.
rescue Exception
next next
end end

View File

@ -84,7 +84,7 @@ module Homebrew
rescue ::Test::Unit::AssertionFailedError => e rescue ::Test::Unit::AssertionFailedError => e
ofail "#{f.full_name}: failed" ofail "#{f.full_name}: failed"
puts e.message puts e.message
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
ofail "#{f.full_name}: failed" ofail "#{f.full_name}: failed"
puts e, e.backtrace puts e, e.backtrace
ensure ensure

View File

@ -151,8 +151,10 @@ module Homebrew
return unless File.directory?(dir) return unless File.directory?(dir)
files = Dir.chdir(dir) do files = Dir.chdir(dir) do
Dir[pattern].select { |f| File.file?(f) && !File.symlink?(f) } - Dir.glob(white_list) (Dir.glob(pattern) - Dir.glob(white_list))
end.map { |file| File.join(dir, file) } .select { |f| File.file?(f) && !File.symlink?(f) }
.map { |f| File.join(dir, f) }
end
return if files.empty? return if files.empty?
inject_file_list(files, message) inject_file_list(files, message)
@ -427,15 +429,15 @@ module Homebrew
end end
def check_user_path_1 def check_user_path_1
$seen_prefix_bin = false @seen_prefix_bin = false
$seen_prefix_sbin = false @seen_prefix_sbin = false
message = "" message = ""
paths(ENV["HOMEBREW_PATH"]).each do |p| paths(ENV["HOMEBREW_PATH"]).each do |p|
case p case p
when "/usr/bin" when "/usr/bin"
unless $seen_prefix_bin unless @seen_prefix_bin
# only show the doctor message if there are any conflicts # only show the doctor message if there are any conflicts
# rationale: a default install should not trigger any brew doctor messages # rationale: a default install should not trigger any brew doctor messages
conflicts = Dir["#{HOMEBREW_PREFIX}/bin/*"] conflicts = Dir["#{HOMEBREW_PREFIX}/bin/*"]
@ -458,9 +460,9 @@ module Homebrew
end end
end end
when "#{HOMEBREW_PREFIX}/bin" when "#{HOMEBREW_PREFIX}/bin"
$seen_prefix_bin = true @seen_prefix_bin = true
when "#{HOMEBREW_PREFIX}/sbin" when "#{HOMEBREW_PREFIX}/sbin"
$seen_prefix_sbin = true @seen_prefix_sbin = true
end end
end end
@ -468,7 +470,7 @@ module Homebrew
end end
def check_user_path_2 def check_user_path_2
return if $seen_prefix_bin return if @seen_prefix_bin
<<-EOS.undent <<-EOS.undent
Homebrew's bin was not found in your PATH. Homebrew's bin was not found in your PATH.
@ -478,7 +480,7 @@ module Homebrew
end end
def check_user_path_3 def check_user_path_3
return if $seen_prefix_sbin return if @seen_prefix_sbin
# Don't complain about sbin not being in the path if it doesn't exist # Don't complain about sbin not being in the path if it doesn't exist
sbin = HOMEBREW_PREFIX/"sbin" sbin = HOMEBREW_PREFIX/"sbin"
@ -952,6 +954,7 @@ module Homebrew
Putting non-prefixed coreutils in your path can cause gmp builds to fail. Putting non-prefixed coreutils in your path can cause gmp builds to fail.
EOS EOS
rescue FormulaUnavailableError rescue FormulaUnavailableError
return
end end
def check_for_non_prefixed_findutils def check_for_non_prefixed_findutils
@ -966,6 +969,7 @@ module Homebrew
Putting non-prefixed findutils in your path can cause python builds to fail. Putting non-prefixed findutils in your path can cause python builds to fail.
EOS EOS
rescue FormulaUnavailableError rescue FormulaUnavailableError
return
end end
def check_for_pydistutils_cfg_in_home def check_for_pydistutils_cfg_in_home

View File

@ -18,8 +18,7 @@ class AbstractDownloadStrategy
end end
# Download and cache the resource as {#cached_location}. # Download and cache the resource as {#cached_location}.
def fetch def fetch; end
end
# Suppress output # Suppress output
def shutup! def shutup!
@ -37,13 +36,11 @@ class AbstractDownloadStrategy
# Unpack {#cached_location} into the current working directory, and possibly # Unpack {#cached_location} into the current working directory, and possibly
# chdir into the newly-unpacked directory. # chdir into the newly-unpacked directory.
# Unlike {Resource#stage}, this does not take a block. # Unlike {Resource#stage}, this does not take a block.
def stage def stage; end
end
# @!attribute [r] cached_location # @!attribute [r] cached_location
# The path to the cached file or directory associated with the resource. # The path to the cached file or directory associated with the resource.
def cached_location def cached_location; end
end
# @!attribute [r] # @!attribute [r]
# return most recent modified time for all files in the current working directory after stage. # return most recent modified time for all files in the current working directory after stage.
@ -204,14 +201,11 @@ class VCSDownloadStrategy < AbstractDownloadStrategy
true true
end end
def clone_repo def clone_repo; end
end
def update def update; end
end
def current_revision def current_revision; end
end
def extract_ref(specs) def extract_ref(specs)
key = REF_TYPES.find { |type| specs.key?(type) } key = REF_TYPES.find { |type| specs.key?(type) }

View File

@ -24,8 +24,7 @@ module Superenv
end end
# @private # @private
def self.bin def self.bin; end
end
def reset def reset
super super
@ -324,11 +323,9 @@ module Superenv
end end
end end
def set_x11_env_if_installed def set_x11_env_if_installed; end
end
def set_cpu_flags(*) def set_cpu_flags(_, _ = "", _ = {}); end
end
end end
require "extend/os/extend/ENV/super" require "extend/os/extend/ENV/super"

View File

@ -0,0 +1,9 @@
module Cachable
def cache
@cache ||= {}
end
def clear_cache
cache.clear
end
end

View File

@ -186,7 +186,7 @@ class Pathname
begin begin
tf.chown(uid, gid) tf.chown(uid, gid)
tf.chmod(old_stat.mode) tf.chmod(old_stat.mode)
rescue Errno::EPERM rescue Errno::EPERM # rubocop:disable Lint/HandleExceptions
end end
File.rename(tf.path, self) File.rename(tf.path, self)

View File

@ -1041,14 +1041,14 @@ class Formula
# keg's formula is deleted. # keg's formula is deleted.
begin begin
keg = Keg.for(path) keg = Keg.for(path)
rescue NotAKegError, Errno::ENOENT rescue NotAKegError, Errno::ENOENT # rubocop:disable Lint/HandleExceptions
# file doesn't belong to any keg. # file doesn't belong to any keg.
else else
tab_tap = Tab.for_keg(keg).tap tab_tap = Tab.for_keg(keg).tap
return false if tab_tap.nil? # this keg doesn't below to any core/tap formula, most likely coming from a DIY install. return false if tab_tap.nil? # this keg doesn't below to any core/tap formula, most likely coming from a DIY install.
begin begin
Formulary.factory(keg.name) Formulary.factory(keg.name)
rescue FormulaUnavailableError rescue FormulaUnavailableError # rubocop:disable Lint/HandleExceptions
# formula for this keg is deleted, so defer to whitelist # formula for this keg is deleted, so defer to whitelist
rescue TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError rescue TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
return false # this keg belongs to another formula return false # this keg belongs to another formula
@ -1379,12 +1379,13 @@ class Formula
# An array of all installed {Formula} # An array of all installed {Formula}
# @private # @private
def self.installed def self.installed
@installed ||= racks.map do |rack| @installed ||= racks.flat_map do |rack|
begin begin
Formulary.from_rack(rack) Formulary.from_rack(rack)
rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
[]
end end
end.compact.uniq(&:name) end.uniq(&:name)
end end
def self.installed_with_alias_path(alias_path) def self.installed_with_alias_path(alias_path)
@ -1642,7 +1643,7 @@ class Formula
with_logging("test") do with_logging("test") do
test test
end end
rescue Exception rescue Exception # rubocop:disable Lint/RescueException
staging.retain! if ARGV.debug? staging.retain! if ARGV.debug?
raise raise
end end
@ -1667,8 +1668,7 @@ class Formula
end end
# @private # @private
def test def test; end
end
# @private # @private
def test_fixtures(file) def test_fixtures(file)
@ -1683,8 +1683,7 @@ class Formula
# system "./configure", "--prefix=#{prefix}" # system "./configure", "--prefix=#{prefix}"
# system "make", "install" # system "make", "install"
# end</pre> # end</pre>
def install def install; end
end
protected protected
@ -1932,7 +1931,11 @@ class Formula
end end
end end
def self.method_added(method) # The methods below define the formula DSL.
class << self
include BuildEnvironment::DSL
def method_added(method)
case method case method
when :brew when :brew
raise "You cannot override Formula#brew in class #{name}" raise "You cannot override Formula#brew in class #{name}"
@ -1951,10 +1954,6 @@ class Formula
end end
end end
# The methods below define the formula DSL.
class << self
include BuildEnvironment::DSL
# The reason for why this software is not linked (by default) to # The reason for why this software is not linked (by default) to
# {::HOMEBREW_PREFIX}. # {::HOMEBREW_PREFIX}.
# @private # @private

View File

@ -58,13 +58,14 @@ class FormulaInstaller
@options = Options.new @options = Options.new
@invalid_option_names = [] @invalid_option_names = []
@requirement_messages = [] @requirement_messages = []
@@attempted ||= Set.new
@poured_bottle = false @poured_bottle = false
@pour_failed = false @pour_failed = false
end end
def self.attempted
@attempted ||= Set.new
end
# When no build tools are available and build flags are passed through ARGV, # When no build tools are available and build flags are passed through ARGV,
# it's necessary to interrupt the user before any sort of installation # it's necessary to interrupt the user before any sort of installation
# can proceed. Only invoked when the user has no developer tools. # can proceed. Only invoked when the user has no developer tools.
@ -145,7 +146,7 @@ class FormulaInstaller
end end
def check_install_sanity def check_install_sanity
raise FormulaInstallationAlreadyAttemptedError, formula if @@attempted.include?(formula) raise FormulaInstallationAlreadyAttemptedError, formula if self.class.attempted.include?(formula)
return if ignore_deps? return if ignore_deps?
@ -287,12 +288,12 @@ class FormulaInstaller
end end
end end
@@attempted << formula self.class.attempted << formula
if pour_bottle?(warn: true) if pour_bottle?(warn: true)
begin begin
pour pour
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
# any exceptions must leave us with nothing installed # any exceptions must leave us with nothing installed
ignore_interrupts do ignore_interrupts do
formula.prefix.rmtree if formula.prefix.directory? formula.prefix.rmtree if formula.prefix.directory?
@ -567,7 +568,7 @@ class FormulaInstaller
oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}" oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}"
fi.install fi.install
fi.finish fi.finish
rescue Exception rescue Exception # rubocop:disable Lint/RescueException
ignore_interrupts do ignore_interrupts do
tmp_keg.rename(installed_keg) if tmp_keg && !installed_keg.directory? tmp_keg.rename(installed_keg) if tmp_keg && !installed_keg.directory?
linked_keg.link if keg_was_linked linked_keg.link if keg_was_linked
@ -723,7 +724,7 @@ class FormulaInstaller
if !formula.prefix.directory? || Keg.new(formula.prefix).empty_installation? if !formula.prefix.directory? || Keg.new(formula.prefix).empty_installation?
raise "Empty installation" raise "Empty installation"
end end
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
e.options = display_options(formula) if e.is_a?(BuildError) e.options = display_options(formula) if e.is_a?(BuildError)
ignore_interrupts do ignore_interrupts do
# any exceptions must leave us with nothing installed # any exceptions must leave us with nothing installed
@ -784,7 +785,7 @@ class FormulaInstaller
puts " brew link #{formula.name}" puts " brew link #{formula.name}"
@show_summary_heading = true @show_summary_heading = true
Homebrew.failed = true Homebrew.failed = true
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "An unexpected error occurred during the `brew link` step" onoe "An unexpected error occurred during the `brew link` step"
puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}" puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}"
puts e puts e
@ -815,7 +816,7 @@ class FormulaInstaller
formula.plist_path.chmod 0644 formula.plist_path.chmod 0644
log = formula.var/"log" log = formula.var/"log"
log.mkpath if formula.plist.include? log.to_s log.mkpath if formula.plist.include? log.to_s
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Failed to install plist file" onoe "Failed to install plist file"
ohai e, e.backtrace if debug? ohai e, e.backtrace if debug?
Homebrew.failed = true Homebrew.failed = true
@ -823,7 +824,7 @@ class FormulaInstaller
def fix_dynamic_linkage(keg) def fix_dynamic_linkage(keg)
keg.fix_dynamic_linkage keg.fix_dynamic_linkage
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Failed to fix install linkage" onoe "Failed to fix install linkage"
puts "The formula built, but you may encounter issues using it or linking other" puts "The formula built, but you may encounter issues using it or linking other"
puts "formula against it." puts "formula against it."
@ -835,7 +836,7 @@ class FormulaInstaller
def clean def clean
ohai "Cleaning" if verbose? ohai "Cleaning" if verbose?
Cleaner.new(formula).clean Cleaner.new(formula).clean
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
opoo "The cleaning step did not complete successfully" opoo "The cleaning step did not complete successfully"
puts "Still, the installation was successful, so we will link it into your prefix" puts "Still, the installation was successful, so we will link it into your prefix"
ohai e, e.backtrace if debug? ohai e, e.backtrace if debug?
@ -845,7 +846,7 @@ class FormulaInstaller
def post_install def post_install
Homebrew.run_post_install(formula) Homebrew.run_post_install(formula)
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
opoo "The post-install step did not complete successfully" opoo "The post-install step did not complete successfully"
puts "You can try again using `brew postinstall #{formula.full_name}`" puts "You can try again using `brew postinstall #{formula.full_name}`"
ohai e, e.backtrace if debug? ohai e, e.backtrace if debug?
@ -905,27 +906,31 @@ class FormulaInstaller
super super
end end
def self.locked
@locked ||= []
end
private private
attr_predicate :hold_locks? attr_predicate :hold_locks?
def lock def lock
return unless (@@locked ||= []).empty? return unless self.class.locked.empty?
unless ignore_deps? unless ignore_deps?
formula.recursive_dependencies.each do |dep| formula.recursive_dependencies.each do |dep|
@@locked << dep.to_formula self.class.locked << dep.to_formula
end end
end end
@@locked.unshift(formula) self.class.locked.unshift(formula)
@@locked.uniq! self.class.locked.uniq!
@@locked.each(&:lock) self.class.locked.each(&:lock)
@hold_locks = true @hold_locks = true
end end
def unlock def unlock
return unless hold_locks? return unless hold_locks?
@@locked.each(&:unlock) self.class.locked.each(&:unlock)
@@locked.clear self.class.locked.clear
@hold_locks = false @hold_locks = false
end end

View File

@ -44,7 +44,7 @@ class FormulaVersions
# continue walking the history # continue walking the history
ohai "#{e} in #{name} at revision #{rev}", e.backtrace if ARGV.debug? ohai "#{e} in #{name} at revision #{rev}", e.backtrace if ARGV.debug?
rescue FormulaUnavailableError rescue FormulaUnavailableError
# Suppress this error return
ensure ensure
Homebrew.raise_deprecation_exceptions = false Homebrew.raise_deprecation_exceptions = false
end end

View File

@ -1,18 +1,19 @@
require "digest/md5" require "digest/md5"
require "tap" require "tap"
require "extend/cachable"
# The Formulary is responsible for creating instances of Formula. # The Formulary is responsible for creating instances of Formula.
# It is not meant to be used directly from formulae. # It is not meant to be used directly from formulae.
module Formulary module Formulary
FORMULAE = {} extend Cachable
def self.formula_class_defined?(path) def self.formula_class_defined?(path)
FORMULAE.key?(path) cache.key?(path)
end end
def self.formula_class_get(path) def self.formula_class_get(path)
FORMULAE.fetch(path) cache.fetch(path)
end end
def self.load_formula(name, path, contents, namespace) def self.load_formula(name, path, contents, namespace)
@ -44,7 +45,7 @@ module Formulary
contents = path.open("r") { |f| ensure_utf8_encoding(f).read } contents = path.open("r") { |f| ensure_utf8_encoding(f).read }
namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}" namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}"
klass = load_formula(name, path, contents, namespace) klass = load_formula(name, path, contents, namespace)
FORMULAE[path] = klass cache[path] = klass
end end
if IO.method_defined?(:set_encoding) if IO.method_defined?(:set_encoding)

View File

@ -100,7 +100,7 @@ class Migrator
begin begin
migrator = Migrator.new(formula) migrator = Migrator.new(formula)
migrator.migrate migrator.migrate
rescue Exception => e rescue => e
onoe e onoe e
end end
end end
@ -196,7 +196,7 @@ class Migrator
update_tabs update_tabs
rescue Interrupt rescue Interrupt
ignore_interrupts { backup_oldname } ignore_interrupts { backup_oldname }
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Error occurred while migrating." onoe "Error occurred while migrating."
puts e puts e
puts e.backtrace if ARGV.debug? puts e.backtrace if ARGV.debug?
@ -304,7 +304,7 @@ class Migrator
puts puts
puts "You can try again using:" puts "You can try again using:"
puts " brew link #{formula.name}" puts " brew link #{formula.name}"
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "An unexpected error occurred during linking" onoe "An unexpected error occurred during linking"
puts e puts e
puts e.backtrace if ARGV.debug? puts e.backtrace if ARGV.debug?

View File

@ -183,7 +183,7 @@ module OS
end end
module CLT module CLT
extend self module_function
STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo".freeze STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo".freeze
FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI".freeze FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI".freeze

View File

@ -60,8 +60,7 @@ class EmbeddedPatch
false false
end end
def contents def contents; end
end
def apply def apply
data = contents.gsub("HOMEBREW_PREFIX", HOMEBREW_PREFIX) data = contents.gsub("HOMEBREW_PREFIX", HOMEBREW_PREFIX)
@ -87,10 +86,13 @@ class DATAPatch < EmbeddedPatch
def contents def contents
data = "" data = ""
path.open("rb") do |f| path.open("rb") do |f|
begin loop do
line = f.gets line = f.gets
end until line.nil? || line =~ /^__END__$/ break if line.nil? || line =~ /^__END__$/
data << line while line = f.gets end
while line = f.gets
data << line
end
end end
data data
end end

View File

@ -14,7 +14,7 @@ begin
formula = ARGV.resolved_formulae.first formula = ARGV.resolved_formulae.first
formula.extend(Debrew::Formula) if ARGV.debug? formula.extend(Debrew::Formula) if ARGV.debug?
formula.run_post_install formula.run_post_install
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe) Marshal.dump(e, error_pipe)
error_pipe.close error_pipe.close
exit! 1 exit! 1

View File

@ -52,7 +52,7 @@ module Readall
Formulary.factory(file) Formulary.factory(file)
rescue Interrupt rescue Interrupt
raise raise
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Invalid formula: #{file}" onoe "Invalid formula: #{file}"
puts e puts e
failed = true failed = true

View File

@ -3,18 +3,16 @@ require "ostruct"
require "options" require "options"
require "json" require "json"
require "development_tools" require "development_tools"
require "extend/cachable"
# Inherit from OpenStruct to gain a generic initialization method that takes a # Inherit from OpenStruct to gain a generic initialization method that takes a
# hash and creates an attribute for each key and value. `Tab.new` probably # hash and creates an attribute for each key and value. `Tab.new` probably
# should not be called directly, instead use one of the class methods like # should not be called directly, instead use one of the class methods like
# `Tab.create`. # `Tab.create`.
class Tab < OpenStruct class Tab < OpenStruct
FILENAME = "INSTALL_RECEIPT.json".freeze extend Cachable
CACHE = {}
def self.clear_cache FILENAME = "INSTALL_RECEIPT.json".freeze
CACHE.clear
end
# Instantiates a Tab for a new installation of a formula. # Instantiates a Tab for a new installation of a formula.
def self.create(formula, compiler, stdlib) def self.create(formula, compiler, stdlib)
@ -57,7 +55,7 @@ class Tab < OpenStruct
# Returns the Tab for an install receipt at `path`. # Returns the Tab for an install receipt at `path`.
# Results are cached. # Results are cached.
def self.from_file(path) def self.from_file(path)
CACHE.fetch(path) { |p| CACHE[p] = from_file_content(File.read(p), p) } cache.fetch(path) { |p| cache[p] = from_file_content(File.read(p), p) }
end end
# Like Tab.from_file, but bypass the cache. # Like Tab.from_file, but bypass the cache.
@ -343,7 +341,7 @@ class Tab < OpenStruct
# will no longer be valid. # will no longer be valid.
Formula.clear_installed_formulae_cache unless tabfile.exist? Formula.clear_installed_formulae_cache unless tabfile.exist?
CACHE[tabfile] = self self.class.cache[tabfile] = self
tabfile.atomic_write(to_json) tabfile.atomic_write(to_json)
end end

View File

@ -1,4 +1,5 @@
require "extend/string" require "extend/string"
require "extend/cachable"
require "readall" require "readall"
# a {Tap} is used to extend the formulae provided by Homebrew core. # a {Tap} is used to extend the formulae provided by Homebrew core.
@ -8,14 +9,10 @@ require "readall"
# {#user} represents Github username and {#repo} represents repository # {#user} represents Github username and {#repo} represents repository
# name without leading `homebrew-`. # name without leading `homebrew-`.
class Tap class Tap
extend Cachable
TAP_DIRECTORY = HOMEBREW_LIBRARY/"Taps" TAP_DIRECTORY = HOMEBREW_LIBRARY/"Taps"
CACHE = {}
def self.clear_cache
CACHE.clear
end
def self.fetch(*args) def self.fetch(*args)
case args.length case args.length
when 1 when 1
@ -38,7 +35,7 @@ class Tap
end end
cache_key = "#{user}/#{repo}".downcase cache_key = "#{user}/#{repo}".downcase
CACHE.fetch(cache_key) { |key| CACHE[key] = Tap.new(user, repo) } cache.fetch(cache_key) { |key| cache[key] = Tap.new(user, repo) }
end end
def self.from_path(path) def self.from_path(path)

View File

@ -27,7 +27,7 @@ begin
Timeout.timeout TEST_TIMEOUT_SECONDS do Timeout.timeout TEST_TIMEOUT_SECONDS do
raise "test returned false" if formula.run_test == false raise "test returned false" if formula.run_test == false
end end
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe) Marshal.dump(e, error_pipe)
error_pipe.close error_pipe.close
exit! 1 exit! 1

View File

@ -107,7 +107,7 @@ describe FormulaInstaller do
end end
EOS EOS
Formulary::FORMULAE.delete(dep_path) Formulary.cache.delete(dep_path)
dependency = Formulary.factory(dep_name) dependency = Formulary.factory(dep_name)
dependent = formula do dependent = formula do

View File

@ -229,10 +229,9 @@ module Homebrew
EOS EOS
end end
# Hash of Module => Set(method_names) # rubocop:disable Style/GlobalVars
@injected_dump_stat_modules = {}
def inject_dump_stats!(the_module, pattern) def inject_dump_stats!(the_module, pattern)
@injected_dump_stat_modules ||= {}
@injected_dump_stat_modules[the_module] ||= [] @injected_dump_stat_modules[the_module] ||= []
injected_methods = @injected_dump_stat_modules[the_module] injected_methods = @injected_dump_stat_modules[the_module]
the_module.module_eval do the_module.module_eval do
@ -260,6 +259,7 @@ module Homebrew
end end
end end
end end
# rubocop:enable Style/GlobalVars
end end
def with_system_path def with_system_path

View File

@ -14,7 +14,7 @@ module Utils
read.close read.close
write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
yield yield
rescue Exception => e rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, write) Marshal.dump(e, write)
write.close write.close
exit! exit!
@ -26,8 +26,11 @@ module Utils
ignore_interrupts(:quietly) do # the child will receive the interrupt and marshal it back ignore_interrupts(:quietly) do # the child will receive the interrupt and marshal it back
begin begin
socket = server.accept_nonblock socket = server.accept_nonblock
# rubocop:disable Lint/ShadowedException
# FIXME: https://github.com/bbatsov/rubocop/issues/4843
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
retry unless Process.waitpid(pid, Process::WNOHANG) retry unless Process.waitpid(pid, Process::WNOHANG)
# rubocop:enable Lint/ShadowedException
else else
socket.send_io(write) socket.send_io(write)
socket.close socket.close
@ -36,7 +39,7 @@ module Utils
data = read.read data = read.read
read.close read.close
Process.wait(pid) unless socket.nil? Process.wait(pid) unless socket.nil?
raise Marshal.load(data) unless data.nil? || data.empty? raise Marshal.load(data) unless data.nil? || data.empty? # rubocop:disable Security/MarshalLoad
raise Interrupt if $CHILD_STATUS.exitstatus == 130 raise Interrupt if $CHILD_STATUS.exitstatus == 130
raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success? raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success?
end end

View File

@ -213,110 +213,6 @@ class Version
end end
end end
def initialize(val)
unless val.respond_to?(:to_str)
raise TypeError, "Version value must be a string; got a #{val.class} (#{val})"
end
@version = val.to_str
end
def detected_from_url?
false
end
def head?
false
end
def null?
false
end
def <=>(other)
# Needed to retain API compatibility with older string comparisons
# for compiler versions, etc.
other = Version.new(other) if other.is_a? String
# Used by the *_build_version comparisons, which formerly returned Fixnum
other = Version.new(other.to_s) if other.is_a? Integer
return 1 if other.nil?
return unless other.is_a?(Version)
return 0 if version == other.version
return 1 if head? && !other.head?
return -1 if !head? && other.head?
return 0 if head? && other.head?
ltokens = tokens
rtokens = other.tokens
max = max(ltokens.length, rtokens.length)
l = r = 0
while l < max
a = ltokens[l] || NULL_TOKEN
b = rtokens[r] || NULL_TOKEN
if a == b
l += 1
r += 1
next
elsif a.numeric? && b.numeric?
return a <=> b
elsif a.numeric?
return 1 if a > NULL_TOKEN
l += 1
elsif b.numeric?
return -1 if b > NULL_TOKEN
r += 1
else
return a <=> b
end
end
0
end
alias eql? ==
def hash
version.hash
end
def to_f
version.to_f
end
def to_s
version.dup
end
alias to_str to_s
protected
attr_reader :version
def tokens
@tokens ||= tokenize
end
private
def max(a, b)
(a > b) ? a : b
end
def tokenize
version.scan(SCAN_PATTERN).map! do |token|
case token
when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken
when /\A#{BetaToken::PATTERN}\z/o then BetaToken
when /\A#{RCToken::PATTERN}\z/o then RCToken
when /\A#{PreToken::PATTERN}\z/o then PreToken
when /\A#{PatchToken::PATTERN}\z/o then PatchToken
when /\A#{NumericToken::PATTERN}\z/o then NumericToken
when /\A#{StringToken::PATTERN}\z/o then StringToken
end.new(token)
end
end
def self.parse(spec) def self.parse(spec)
version = _parse(spec) version = _parse(spec)
version.nil? ? NULL : new(version) version.nil? ? NULL : new(version)
@ -461,6 +357,112 @@ class Version
m = /[-.vV]?((?:\d+\.)+\d+(?:[-_.]?(?i:alpha|beta|pre|rc)\.?\d{,2})?)/.match(spec_s) m = /[-.vV]?((?:\d+\.)+\d+(?:[-_.]?(?i:alpha|beta|pre|rc)\.?\d{,2})?)/.match(spec_s)
return m.captures.first unless m.nil? return m.captures.first unless m.nil?
end end
private_class_method :_parse
def initialize(val)
unless val.respond_to?(:to_str)
raise TypeError, "Version value must be a string; got a #{val.class} (#{val})"
end
@version = val.to_str
end
def detected_from_url?
false
end
def head?
false
end
def null?
false
end
def <=>(other)
# Needed to retain API compatibility with older string comparisons
# for compiler versions, etc.
other = Version.new(other) if other.is_a? String
# Used by the *_build_version comparisons, which formerly returned Fixnum
other = Version.new(other.to_s) if other.is_a? Integer
return 1 if other.nil?
return unless other.is_a?(Version)
return 0 if version == other.version
return 1 if head? && !other.head?
return -1 if !head? && other.head?
return 0 if head? && other.head?
ltokens = tokens
rtokens = other.tokens
max = max(ltokens.length, rtokens.length)
l = r = 0
while l < max
a = ltokens[l] || NULL_TOKEN
b = rtokens[r] || NULL_TOKEN
if a == b
l += 1
r += 1
next
elsif a.numeric? && b.numeric?
return a <=> b
elsif a.numeric?
return 1 if a > NULL_TOKEN
l += 1
elsif b.numeric?
return -1 if b > NULL_TOKEN
r += 1
else
return a <=> b
end
end
0
end
alias eql? ==
def hash
version.hash
end
def to_f
version.to_f
end
def to_s
version.dup
end
alias to_str to_s
protected
attr_reader :version
def tokens
@tokens ||= tokenize
end
private
def max(a, b)
(a > b) ? a : b
end
def tokenize
version.scan(SCAN_PATTERN).map! do |token|
case token
when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken
when /\A#{BetaToken::PATTERN}\z/o then BetaToken
when /\A#{RCToken::PATTERN}\z/o then RCToken
when /\A#{PreToken::PATTERN}\z/o then PreToken
when /\A#{PatchToken::PATTERN}\z/o then PatchToken
when /\A#{NumericToken::PATTERN}\z/o then NumericToken
when /\A#{StringToken::PATTERN}\z/o then StringToken
end.new(token)
end
end
end end
class HeadVersion < Version class HeadVersion < Version