From 175ca909ee1a5b57aa0cae2c879920511f311b14 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 7 Oct 2017 00:31:28 +0200 Subject: [PATCH] Clean up code style and remove `.rubocop_todo.yml`. --- Library/Homebrew/.rubocop.yml | 29 ++- Library/Homebrew/.rubocop_todo.yml | 138 ------------ Library/Homebrew/brew.rb | 2 +- Library/Homebrew/build.rb | 2 +- Library/Homebrew/cmd/fetch.rb | 6 +- Library/Homebrew/cmd/install.rb | 1 + Library/Homebrew/cmd/reinstall.rb | 4 +- Library/Homebrew/cmd/style.rb | 1 + Library/Homebrew/cmd/tap.rb | 3 +- Library/Homebrew/cmd/update-report.rb | 6 +- Library/Homebrew/cmd/upgrade.rb | 1 + Library/Homebrew/cmd/uses.rb | 6 +- Library/Homebrew/debrew.rb | 6 +- Library/Homebrew/debrew/irb.rb | 3 +- Library/Homebrew/dependency.rb | 2 +- Library/Homebrew/dependency_collector.rb | 11 +- Library/Homebrew/descriptions.rb | 4 +- .../Homebrew/dev-cmd/aspell-dictionaries.rb | 5 +- Library/Homebrew/dev-cmd/audit.rb | 18 +- Library/Homebrew/dev-cmd/bottle.rb | 9 +- Library/Homebrew/dev-cmd/man.rb | 9 +- Library/Homebrew/dev-cmd/pull.rb | 4 +- Library/Homebrew/dev-cmd/test.rb | 2 +- Library/Homebrew/diagnostic.rb | 22 +- Library/Homebrew/download_strategy.rb | 18 +- Library/Homebrew/extend/ENV/super.rb | 9 +- Library/Homebrew/extend/cachable.rb | 9 + Library/Homebrew/extend/pathname.rb | 2 +- Library/Homebrew/formula.rb | 55 +++-- Library/Homebrew/formula_installer.rb | 45 ++-- Library/Homebrew/formula_versions.rb | 2 +- Library/Homebrew/formulary.rb | 9 +- Library/Homebrew/migrator.rb | 6 +- Library/Homebrew/os/mac/xcode.rb | 2 +- Library/Homebrew/patch.rb | 12 +- Library/Homebrew/postinstall.rb | 2 +- Library/Homebrew/readall.rb | 2 +- Library/Homebrew/tab.rb | 12 +- Library/Homebrew/tap.rb | 11 +- Library/Homebrew/test.rb | 2 +- .../Homebrew/test/formula_installer_spec.rb | 2 +- Library/Homebrew/utils.rb | 6 +- Library/Homebrew/utils/fork.rb | 7 +- Library/Homebrew/version.rb | 210 +++++++++--------- 44 files changed, 296 insertions(+), 421 deletions(-) delete mode 100644 Library/Homebrew/.rubocop_todo.yml create mode 100644 Library/Homebrew/extend/cachable.rb diff --git a/Library/Homebrew/.rubocop.yml b/Library/Homebrew/.rubocop.yml index 3b440c33c8..1434686432 100644 --- a/Library/Homebrew/.rubocop.yml +++ b/Library/Homebrew/.rubocop.yml @@ -1,6 +1,5 @@ inherit_from: - ../.rubocop.yml - - .rubocop_todo.yml AllCops: Include: @@ -26,9 +25,26 @@ Lint/NestedMethodDefinition: Lint/ParenthesesAsGroupedExpression: Enabled: true +Metrics/BlockNesting: + Max: 5 + +Metrics/ModuleLength: + Max: 360 + Metrics/ParameterLists: 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: Exclude: - '**/*_spec.rb' @@ -41,14 +57,3 @@ Style/GuardClause: # hash-rockets preferred for formulae, a: 1 preferred elsewhere Style/HashSyntax: 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? diff --git a/Library/Homebrew/.rubocop_todo.yml b/Library/Homebrew/.rubocop_todo.yml deleted file mode 100644 index 96c2f3676c..0000000000 --- a/Library/Homebrew/.rubocop_todo.yml +++ /dev/null @@ -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' diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb index 41955e60e0..86b40a79da 100644 --- a/Library/Homebrew/brew.rb +++ b/Library/Homebrew/brew.rb @@ -146,7 +146,7 @@ rescue MethodDeprecatedError => e $stderr.puts " #{Formatter.url(e.issues_url)}" end exit 1 -rescue Exception => e +rescue Exception => e # rubocop:disable Lint/RescueException onoe e if internal_cmd && defined?(OS::ISSUES_URL) && !ENV["HOMEBREW_NO_AUTO_UPDATE"] diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index cd2fa4c022..836b360daa 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -190,7 +190,7 @@ begin options = Options.create(ARGV.flags_only) build = Build.new(formula, options) build.install -rescue Exception => e +rescue Exception => e # rubocop:disable Lint/RescueException Marshal.dump(e, error_pipe) error_pipe.close exit! 1 diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 006c637466..4117539927 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -49,8 +49,10 @@ module Homebrew if fetch_bottle?(f) begin fetch_formula(f.bottle) - rescue Exception => e - raise if ARGV.homebrew_developer? || e.is_a?(Interrupt) + rescue Interrupt + raise + rescue => e + raise if ARGV.homebrew_developer? fetched_bottle = false onoe e.message opoo "Bottle fetch failed: fetching the source." diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 732e96b004..ca8f294772 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -339,6 +339,7 @@ module Homebrew rescue FormulaInstallationAlreadyAttemptedError # 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. + return rescue CannotInstallFormulaError => e ofail e.message end diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index 94096d2dd4..6727c0b6bb 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -47,8 +47,8 @@ module Homebrew fi.install fi.finish rescue FormulaInstallationAlreadyAttemptedError - # next - rescue Exception + return + rescue Exception # rubocop:disable Lint/RescueException ignore_interrupts { restore_backup(keg, keg_was_linked) } raise else diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb index e816db5dc6..58f430a27d 100644 --- a/Library/Homebrew/cmd/style.rb +++ b/Library/Homebrew/cmd/style.rb @@ -117,6 +117,7 @@ module Homebrew case output_type when :print + args << "--debug" if ARGV.debug? args << "--display-cop-names" if ARGV.include? "--display-cop-names" args << "--format" << "simple" if files system(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", *args) diff --git a/Library/Homebrew/cmd/tap.rb b/Library/Homebrew/cmd/tap.rb index 2a07c1b2f3..fa520e2c56 100644 --- a/Library/Homebrew/cmd/tap.rb +++ b/Library/Homebrew/cmd/tap.rb @@ -54,8 +54,7 @@ module Homebrew quiet: ARGV.quieter? rescue TapRemoteMismatchError => e odie e - rescue TapAlreadyTappedError, TapAlreadyUnshallowError - # Do nothing. + rescue TapAlreadyTappedError, TapAlreadyUnshallowError # rubocop:disable Lint/HandleExceptions end end end diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 781ee88081..0974df0b41 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -372,7 +372,7 @@ class Reporter new_version = formula.pkg_version old_version = FormulaVersions.new(formula).formula_at_revision(@initial_revision, &:pkg_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? end @report[:M] << tap.formula_file_to_name(src) @@ -460,7 +460,7 @@ class Reporter unless Formulary.factory(new_full_name).keg_only? system HOMEBREW_BREW_FILE, "link", new_full_name, "--overwrite" end - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer? end next @@ -521,7 +521,7 @@ class Reporter begin 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? next end diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 1cdb497cf6..f1ce3c7da4 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -150,6 +150,7 @@ module Homebrew rescue FormulaInstallationAlreadyAttemptedError # 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. + return rescue CannotInstallFormulaError => e ofail e rescue BuildError => e diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb index 24684c3b6c..0b09e1bf19 100644 --- a/Library/Homebrew/cmd/uses.rb +++ b/Library/Homebrew/cmd/uses.rb @@ -74,12 +74,13 @@ module Homebrew end end - dep_formulae = deps.map do |dep| + dep_formulae = deps.flat_map do |dep| begin dep.to_formula rescue + [] end - end.compact + end reqs_by_formula = ([f] + dep_formulae).flat_map do |formula| formula.requirements.map { |req| [formula, req] } @@ -118,6 +119,7 @@ module Homebrew rescue FormulaUnavailableError # Silently ignore this case as we don't care about things used in # taps that aren't currently tapped. + next end end end diff --git a/Library/Homebrew/debrew.rb b/Library/Homebrew/debrew.rb index 5bc3d2daad..6206eb8a27 100644 --- a/Library/Homebrew/debrew.rb +++ b/Library/Homebrew/debrew.rb @@ -9,7 +9,7 @@ module Debrew module Raise def raise(*) super - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException e.extend(Ignorable) super(e) unless Debrew.debug(e) == :ignore end @@ -92,7 +92,7 @@ module Debrew yield rescue SystemExit original_raise - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException debug(e) ensure @active = false @@ -119,7 +119,7 @@ module Debrew if e.is_a?(Ignorable) menu.choice(:irb) do 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" set_trace_func(nil) synchronize { IRB.start_within(binding) } diff --git a/Library/Homebrew/debrew/irb.rb b/Library/Homebrew/debrew/irb.rb index 069dbe6760..eeb3758a98 100644 --- a/Library/Homebrew/debrew/irb.rb +++ b/Library/Homebrew/debrew/irb.rb @@ -4,8 +4,7 @@ module IRB @setup_done = false extend Module.new { - def parse_opts - end + def parse_opts; end def start_within(binding) unless @setup_done diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 0fbc2625b1..7f0e7fbffe 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -64,7 +64,7 @@ class Dependency end def self._load(marshaled) - new(*Marshal.load(marshaled)) + new(*Marshal.load(marshaled)) # rubocop:disable Security/MarshalLoad end class << self diff --git a/Library/Homebrew/dependency_collector.rb b/Library/Homebrew/dependency_collector.rb index fff80a28cf..f855669e0a 100644 --- a/Library/Homebrew/dependency_collector.rb +++ b/Library/Homebrew/dependency_collector.rb @@ -4,6 +4,7 @@ require "ld64_dependency" require "requirement" require "requirements" require "set" +require "extend/cachable" ## A dependency is a formula that another formula needs to install. ## 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 # specifications into the proper kinds of dependencies and requirements. class DependencyCollector + extend Cachable + # Define the languages that we can handle as external dependencies. LANGUAGE_MODULES = Set[ :lua, :lua51, :perl, :python, :python3, :ruby ].freeze - CACHE = {} - - def self.clear_cache - CACHE.clear - end - attr_reader :deps, :requirements def initialize @@ -45,7 +42,7 @@ class DependencyCollector end 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 def cache_key(spec) diff --git a/Library/Homebrew/descriptions.rb b/Library/Homebrew/descriptions.rb index ac1d68216a..bc19826731 100644 --- a/Library/Homebrew/descriptions.rb +++ b/Library/Homebrew/descriptions.rb @@ -78,10 +78,10 @@ class Descriptions formula_names.each do |name| begin - desc = Formulary.factory(name).desc + @cache[name] = Formulary.factory(name).desc rescue FormulaUnavailableError, *FormulaVersions::IGNORED_EXCEPTIONS + @cache.delete(name) end - @cache[name] = desc end save_cache if options[:save] end diff --git a/Library/Homebrew/dev-cmd/aspell-dictionaries.rb b/Library/Homebrew/dev-cmd/aspell-dictionaries.rb index 955e41b01f..ab0e66d2bf 100644 --- a/Library/Homebrew/dev-cmd/aspell-dictionaries.rb +++ b/Library/Homebrew/dev-cmd/aspell-dictionaries.rb @@ -27,13 +27,12 @@ module Homebrew end end - languages.inject([]) do |resources, (lang, path)| + languages.each do |lang, path| r = Resource.new(lang) r.owner = Formulary.factory("aspell") r.url "#{dict_url}/#{path}" r.mirror "#{dict_mirror}/#{path}" - resources << r - end.each(&:fetch).each do |r| + r.fetch puts <<-EOS option "with-lang-#{r.name}", "Install #{r.name} dictionary" resource "#{r.name}" do diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 16ae7cba10..6afd1f8028 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -53,7 +53,7 @@ module Homebrew module_function def audit - Homebrew.inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D" + inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D" Homebrew.auditing = true formula_count = 0 @@ -387,8 +387,10 @@ class FormulaAuditor end end - # core aliases + tap alias names + tap alias full name - @@aliases ||= Formula.aliases + Formula.tap_aliases + def self.aliases + # core aliases + tap alias names + tap alias full name + @aliases ||= Formula.aliases + Formula.tap_aliases + end def audit_formula_name return unless @strict @@ -442,7 +444,7 @@ class FormulaAuditor problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'." end - if @@aliases.include?(dep.name) && + if self.class.aliases.include?(dep.name) && (dep_f.core_formula? || !dep_f.versioned_formula?) problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'." 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." end - dep.options.reject do |opt| - next true if dep_f.option_defined?(opt) - dep_f.requirements.detect do |r| + dep.options.each do |opt| + next if dep_f.option_defined?(opt) + next if dep_f.requirements.detect do |r| if r.recommended? opt.name == "with-#{r.name}" elsif r.optional? opt.name == "without-#{r.name}" end end - end.each do |opt| + problem "Dependency #{dep} does not define option #{opt.name.inspect}" end diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 8dfd0d12c6..fb862c7733 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -75,7 +75,7 @@ module Homebrew @put_filenames ||= [] - return if @put_filenames.include? filename + return if @put_filenames.include?(filename) puts Formatter.error(filename.to_s) @put_filenames << filename @@ -84,8 +84,7 @@ module Homebrew result = false keg.each_unique_file_matching(string) do |file| - # skip document file. - next if Metafiles::EXTENSIONS.include? file.extname + next if Metafiles::EXTENSIONS.include?(file.extname) # Skip document files. linked_libraries = Keg.file_linked_libraries(file, string) result ||= !linked_libraries.empty? @@ -156,9 +155,7 @@ module Homebrew return ofail "Formula not installed or up-to-date: #{f.full_name}" end - tap = f.tap - - unless tap + unless tap = f.tap unless ARGV.include?("--force-core-tap") return ofail "Formula not from core or any taps: #{f.full_name}" end diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb index 472bb7c2b1..b2bb3c8c34 100644 --- a/Library/Homebrew/dev-cmd/man.rb +++ b/Library/Homebrew/dev-cmd/man.rb @@ -48,12 +48,9 @@ module Homebrew def path_glob_commands(glob) Pathname.glob(glob) .sort_by { |source_file| sort_key_for_path(source_file) } - .map do |source_file| - source_file.read.lines - .grep(/^#:/) - .map { |line| line.slice(2..-1) } - .join - end.reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") } + .map(&:read).map(&:lines) + .map { |lines| lines.grep(/^#:/).map { |line| line.slice(2..-1) }.join } + .reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") } end def build_man_page diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index cd0d6fbd06..8cb2703035 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -154,8 +154,8 @@ module Homebrew begin f = Formula[name] - # Make sure we catch syntax errors. - rescue Exception + rescue Exception # rubocop:disable Lint/RescueException + # Make sure we catch syntax errors. next end diff --git a/Library/Homebrew/dev-cmd/test.rb b/Library/Homebrew/dev-cmd/test.rb index ab2b0edb0a..6622a8c257 100644 --- a/Library/Homebrew/dev-cmd/test.rb +++ b/Library/Homebrew/dev-cmd/test.rb @@ -84,7 +84,7 @@ module Homebrew rescue ::Test::Unit::AssertionFailedError => e ofail "#{f.full_name}: failed" puts e.message - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException ofail "#{f.full_name}: failed" puts e, e.backtrace ensure diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index 88aa4dbc90..3edf31012f 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -151,8 +151,10 @@ module Homebrew return unless File.directory?(dir) files = Dir.chdir(dir) do - Dir[pattern].select { |f| File.file?(f) && !File.symlink?(f) } - Dir.glob(white_list) - end.map { |file| File.join(dir, file) } + (Dir.glob(pattern) - Dir.glob(white_list)) + .select { |f| File.file?(f) && !File.symlink?(f) } + .map { |f| File.join(dir, f) } + end return if files.empty? inject_file_list(files, message) @@ -427,15 +429,15 @@ module Homebrew end def check_user_path_1 - $seen_prefix_bin = false - $seen_prefix_sbin = false + @seen_prefix_bin = false + @seen_prefix_sbin = false message = "" paths(ENV["HOMEBREW_PATH"]).each do |p| case p when "/usr/bin" - unless $seen_prefix_bin + unless @seen_prefix_bin # only show the doctor message if there are any conflicts # rationale: a default install should not trigger any brew doctor messages conflicts = Dir["#{HOMEBREW_PREFIX}/bin/*"] @@ -458,9 +460,9 @@ module Homebrew end end when "#{HOMEBREW_PREFIX}/bin" - $seen_prefix_bin = true + @seen_prefix_bin = true when "#{HOMEBREW_PREFIX}/sbin" - $seen_prefix_sbin = true + @seen_prefix_sbin = true end end @@ -468,7 +470,7 @@ module Homebrew end def check_user_path_2 - return if $seen_prefix_bin + return if @seen_prefix_bin <<-EOS.undent Homebrew's bin was not found in your PATH. @@ -478,7 +480,7 @@ module Homebrew end 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 sbin = HOMEBREW_PREFIX/"sbin" @@ -952,6 +954,7 @@ module Homebrew Putting non-prefixed coreutils in your path can cause gmp builds to fail. EOS rescue FormulaUnavailableError + return end 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. EOS rescue FormulaUnavailableError + return end def check_for_pydistutils_cfg_in_home diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 7012fccc81..e69a56ddfa 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -18,8 +18,7 @@ class AbstractDownloadStrategy end # Download and cache the resource as {#cached_location}. - def fetch - end + def fetch; end # Suppress output def shutup! @@ -37,13 +36,11 @@ class AbstractDownloadStrategy # Unpack {#cached_location} into the current working directory, and possibly # chdir into the newly-unpacked directory. # Unlike {Resource#stage}, this does not take a block. - def stage - end + def stage; end # @!attribute [r] cached_location # The path to the cached file or directory associated with the resource. - def cached_location - end + def cached_location; end # @!attribute [r] # return most recent modified time for all files in the current working directory after stage. @@ -204,14 +201,11 @@ class VCSDownloadStrategy < AbstractDownloadStrategy true end - def clone_repo - end + def clone_repo; end - def update - end + def update; end - def current_revision - end + def current_revision; end def extract_ref(specs) key = REF_TYPES.find { |type| specs.key?(type) } diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb index b518c22a1c..b4f0dfcac0 100644 --- a/Library/Homebrew/extend/ENV/super.rb +++ b/Library/Homebrew/extend/ENV/super.rb @@ -24,8 +24,7 @@ module Superenv end # @private - def self.bin - end + def self.bin; end def reset super @@ -324,11 +323,9 @@ module Superenv end end - def set_x11_env_if_installed - end + def set_x11_env_if_installed; end - def set_cpu_flags(*) - end + def set_cpu_flags(_, _ = "", _ = {}); end end require "extend/os/extend/ENV/super" diff --git a/Library/Homebrew/extend/cachable.rb b/Library/Homebrew/extend/cachable.rb new file mode 100644 index 0000000000..69d86ccb7b --- /dev/null +++ b/Library/Homebrew/extend/cachable.rb @@ -0,0 +1,9 @@ +module Cachable + def cache + @cache ||= {} + end + + def clear_cache + cache.clear + end +end diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index e1acd1f775..e3d6880ba6 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -186,7 +186,7 @@ class Pathname begin tf.chown(uid, gid) tf.chmod(old_stat.mode) - rescue Errno::EPERM + rescue Errno::EPERM # rubocop:disable Lint/HandleExceptions end File.rename(tf.path, self) diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index d999b9c5fe..61042aae76 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -1041,14 +1041,14 @@ class Formula # keg's formula is deleted. begin keg = Keg.for(path) - rescue NotAKegError, Errno::ENOENT + rescue NotAKegError, Errno::ENOENT # rubocop:disable Lint/HandleExceptions # file doesn't belong to any keg. else 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. begin Formulary.factory(keg.name) - rescue FormulaUnavailableError + rescue FormulaUnavailableError # rubocop:disable Lint/HandleExceptions # formula for this keg is deleted, so defer to whitelist rescue TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError return false # this keg belongs to another formula @@ -1379,12 +1379,13 @@ class Formula # An array of all installed {Formula} # @private def self.installed - @installed ||= racks.map do |rack| + @installed ||= racks.flat_map do |rack| begin Formulary.from_rack(rack) rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError + [] end - end.compact.uniq(&:name) + end.uniq(&:name) end def self.installed_with_alias_path(alias_path) @@ -1642,7 +1643,7 @@ class Formula with_logging("test") do test end - rescue Exception + rescue Exception # rubocop:disable Lint/RescueException staging.retain! if ARGV.debug? raise end @@ -1667,8 +1668,7 @@ class Formula end # @private - def test - end + def test; end # @private def test_fixtures(file) @@ -1683,8 +1683,7 @@ class Formula # system "./configure", "--prefix=#{prefix}" # system "make", "install" # end - def install - end + def install; end protected @@ -1932,29 +1931,29 @@ class Formula end end - def self.method_added(method) - case method - when :brew - raise "You cannot override Formula#brew in class #{name}" - when :test - define_method(:test_defined?) { true } - when :options - instance = allocate - - specs.each do |spec| - instance.options.each do |opt, desc| - spec.option(opt[/^--(.+)$/, 1], desc) - end - end - - remove_method(:options) - end - end - # The methods below define the formula DSL. class << self include BuildEnvironment::DSL + def method_added(method) + case method + when :brew + raise "You cannot override Formula#brew in class #{name}" + when :test + define_method(:test_defined?) { true } + when :options + instance = allocate + + specs.each do |spec| + instance.options.each do |opt, desc| + spec.option(opt[/^--(.+)$/, 1], desc) + end + end + + remove_method(:options) + end + end + # The reason for why this software is not linked (by default) to # {::HOMEBREW_PREFIX}. # @private diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 56238ad734..7cd87e7513 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -58,13 +58,14 @@ class FormulaInstaller @options = Options.new @invalid_option_names = [] @requirement_messages = [] - - @@attempted ||= Set.new - @poured_bottle = false @pour_failed = false end + def self.attempted + @attempted ||= Set.new + end + # 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 # can proceed. Only invoked when the user has no developer tools. @@ -145,7 +146,7 @@ class FormulaInstaller end def check_install_sanity - raise FormulaInstallationAlreadyAttemptedError, formula if @@attempted.include?(formula) + raise FormulaInstallationAlreadyAttemptedError, formula if self.class.attempted.include?(formula) return if ignore_deps? @@ -287,12 +288,12 @@ class FormulaInstaller end end - @@attempted << formula + self.class.attempted << formula if pour_bottle?(warn: true) begin pour - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException # any exceptions must leave us with nothing installed ignore_interrupts do formula.prefix.rmtree if formula.prefix.directory? @@ -567,7 +568,7 @@ class FormulaInstaller oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}" fi.install fi.finish - rescue Exception + rescue Exception # rubocop:disable Lint/RescueException ignore_interrupts do tmp_keg.rename(installed_keg) if tmp_keg && !installed_keg.directory? linked_keg.link if keg_was_linked @@ -723,7 +724,7 @@ class FormulaInstaller if !formula.prefix.directory? || Keg.new(formula.prefix).empty_installation? raise "Empty installation" end - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException e.options = display_options(formula) if e.is_a?(BuildError) ignore_interrupts do # any exceptions must leave us with nothing installed @@ -784,7 +785,7 @@ class FormulaInstaller puts " brew link #{formula.name}" @show_summary_heading = true Homebrew.failed = true - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "An unexpected error occurred during the `brew link` step" puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}" puts e @@ -815,7 +816,7 @@ class FormulaInstaller formula.plist_path.chmod 0644 log = formula.var/"log" 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" ohai e, e.backtrace if debug? Homebrew.failed = true @@ -823,7 +824,7 @@ class FormulaInstaller def fix_dynamic_linkage(keg) keg.fix_dynamic_linkage - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "Failed to fix install linkage" puts "The formula built, but you may encounter issues using it or linking other" puts "formula against it." @@ -835,7 +836,7 @@ class FormulaInstaller def clean ohai "Cleaning" if verbose? Cleaner.new(formula).clean - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException opoo "The cleaning step did not complete successfully" puts "Still, the installation was successful, so we will link it into your prefix" ohai e, e.backtrace if debug? @@ -845,7 +846,7 @@ class FormulaInstaller def post_install Homebrew.run_post_install(formula) - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException opoo "The post-install step did not complete successfully" puts "You can try again using `brew postinstall #{formula.full_name}`" ohai e, e.backtrace if debug? @@ -905,27 +906,31 @@ class FormulaInstaller super end + def self.locked + @locked ||= [] + end + private attr_predicate :hold_locks? def lock - return unless (@@locked ||= []).empty? + return unless self.class.locked.empty? unless ignore_deps? formula.recursive_dependencies.each do |dep| - @@locked << dep.to_formula + self.class.locked << dep.to_formula end end - @@locked.unshift(formula) - @@locked.uniq! - @@locked.each(&:lock) + self.class.locked.unshift(formula) + self.class.locked.uniq! + self.class.locked.each(&:lock) @hold_locks = true end def unlock return unless hold_locks? - @@locked.each(&:unlock) - @@locked.clear + self.class.locked.each(&:unlock) + self.class.locked.clear @hold_locks = false end diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb index bb68035679..c10c69e674 100644 --- a/Library/Homebrew/formula_versions.rb +++ b/Library/Homebrew/formula_versions.rb @@ -44,7 +44,7 @@ class FormulaVersions # continue walking the history ohai "#{e} in #{name} at revision #{rev}", e.backtrace if ARGV.debug? rescue FormulaUnavailableError - # Suppress this error + return ensure Homebrew.raise_deprecation_exceptions = false end diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 0eb34ee2ab..fddeac6312 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -1,18 +1,19 @@ require "digest/md5" require "tap" +require "extend/cachable" # The Formulary is responsible for creating instances of Formula. # It is not meant to be used directly from formulae. module Formulary - FORMULAE = {} + extend Cachable def self.formula_class_defined?(path) - FORMULAE.key?(path) + cache.key?(path) end def self.formula_class_get(path) - FORMULAE.fetch(path) + cache.fetch(path) end def self.load_formula(name, path, contents, namespace) @@ -44,7 +45,7 @@ module Formulary contents = path.open("r") { |f| ensure_utf8_encoding(f).read } namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}" klass = load_formula(name, path, contents, namespace) - FORMULAE[path] = klass + cache[path] = klass end if IO.method_defined?(:set_encoding) diff --git a/Library/Homebrew/migrator.rb b/Library/Homebrew/migrator.rb index 7ecdafe2fb..0eb7492dfd 100644 --- a/Library/Homebrew/migrator.rb +++ b/Library/Homebrew/migrator.rb @@ -100,7 +100,7 @@ class Migrator begin migrator = Migrator.new(formula) migrator.migrate - rescue Exception => e + rescue => e onoe e end end @@ -196,7 +196,7 @@ class Migrator update_tabs rescue Interrupt ignore_interrupts { backup_oldname } - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "Error occurred while migrating." puts e puts e.backtrace if ARGV.debug? @@ -304,7 +304,7 @@ class Migrator puts puts "You can try again using:" puts " brew link #{formula.name}" - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "An unexpected error occurred during linking" puts e puts e.backtrace if ARGV.debug? diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index 59e7026bdc..5071aafcf0 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -183,7 +183,7 @@ module OS end module CLT - extend self + module_function STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo".freeze FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI".freeze diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb index 7045adf5e6..8a1b00930d 100644 --- a/Library/Homebrew/patch.rb +++ b/Library/Homebrew/patch.rb @@ -60,8 +60,7 @@ class EmbeddedPatch false end - def contents - end + def contents; end def apply data = contents.gsub("HOMEBREW_PREFIX", HOMEBREW_PREFIX) @@ -87,10 +86,13 @@ class DATAPatch < EmbeddedPatch def contents data = "" path.open("rb") do |f| - begin + loop do line = f.gets - end until line.nil? || line =~ /^__END__$/ - data << line while line = f.gets + break if line.nil? || line =~ /^__END__$/ + end + while line = f.gets + data << line + end end data end diff --git a/Library/Homebrew/postinstall.rb b/Library/Homebrew/postinstall.rb index 0b6d8f6b01..53a5b7e751 100644 --- a/Library/Homebrew/postinstall.rb +++ b/Library/Homebrew/postinstall.rb @@ -14,7 +14,7 @@ begin formula = ARGV.resolved_formulae.first formula.extend(Debrew::Formula) if ARGV.debug? formula.run_post_install -rescue Exception => e +rescue Exception => e # rubocop:disable Lint/RescueException Marshal.dump(e, error_pipe) error_pipe.close exit! 1 diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb index 3595c16be4..5f4fd947c6 100644 --- a/Library/Homebrew/readall.rb +++ b/Library/Homebrew/readall.rb @@ -52,7 +52,7 @@ module Readall Formulary.factory(file) rescue Interrupt raise - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "Invalid formula: #{file}" puts e failed = true diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index af19cabe67..aa0208d51a 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -3,18 +3,16 @@ require "ostruct" require "options" require "json" require "development_tools" +require "extend/cachable" # 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 # should not be called directly, instead use one of the class methods like # `Tab.create`. class Tab < OpenStruct - FILENAME = "INSTALL_RECEIPT.json".freeze - CACHE = {} + extend Cachable - def self.clear_cache - CACHE.clear - end + FILENAME = "INSTALL_RECEIPT.json".freeze # Instantiates a Tab for a new installation of a formula. def self.create(formula, compiler, stdlib) @@ -57,7 +55,7 @@ class Tab < OpenStruct # Returns the Tab for an install receipt at `path`. # Results are cached. 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 # Like Tab.from_file, but bypass the cache. @@ -343,7 +341,7 @@ class Tab < OpenStruct # will no longer be valid. Formula.clear_installed_formulae_cache unless tabfile.exist? - CACHE[tabfile] = self + self.class.cache[tabfile] = self tabfile.atomic_write(to_json) end diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index f4e7631b49..78dc4cf4e7 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -1,4 +1,5 @@ require "extend/string" +require "extend/cachable" require "readall" # 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 # name without leading `homebrew-`. class Tap + extend Cachable + TAP_DIRECTORY = HOMEBREW_LIBRARY/"Taps" - CACHE = {} - - def self.clear_cache - CACHE.clear - end - def self.fetch(*args) case args.length when 1 @@ -38,7 +35,7 @@ class Tap end 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 def self.from_path(path) diff --git a/Library/Homebrew/test.rb b/Library/Homebrew/test.rb index d9ec8250ee..3d5e62a884 100644 --- a/Library/Homebrew/test.rb +++ b/Library/Homebrew/test.rb @@ -27,7 +27,7 @@ begin Timeout.timeout TEST_TIMEOUT_SECONDS do raise "test returned false" if formula.run_test == false end -rescue Exception => e +rescue Exception => e # rubocop:disable Lint/RescueException Marshal.dump(e, error_pipe) error_pipe.close exit! 1 diff --git a/Library/Homebrew/test/formula_installer_spec.rb b/Library/Homebrew/test/formula_installer_spec.rb index 7365b27589..7b729312b7 100644 --- a/Library/Homebrew/test/formula_installer_spec.rb +++ b/Library/Homebrew/test/formula_installer_spec.rb @@ -107,7 +107,7 @@ describe FormulaInstaller do end EOS - Formulary::FORMULAE.delete(dep_path) + Formulary.cache.delete(dep_path) dependency = Formulary.factory(dep_name) dependent = formula do diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index d293b2a6fa..237ffa74e8 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -229,10 +229,9 @@ module Homebrew EOS end - # Hash of Module => Set(method_names) - @injected_dump_stat_modules = {} - + # rubocop:disable Style/GlobalVars def inject_dump_stats!(the_module, pattern) + @injected_dump_stat_modules ||= {} @injected_dump_stat_modules[the_module] ||= [] injected_methods = @injected_dump_stat_modules[the_module] the_module.module_eval do @@ -260,6 +259,7 @@ module Homebrew end end end + # rubocop:enable Style/GlobalVars end def with_system_path diff --git a/Library/Homebrew/utils/fork.rb b/Library/Homebrew/utils/fork.rb index 2f2a403e2a..57ddbfae29 100644 --- a/Library/Homebrew/utils/fork.rb +++ b/Library/Homebrew/utils/fork.rb @@ -14,7 +14,7 @@ module Utils read.close write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) yield - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException Marshal.dump(e, write) write.close exit! @@ -26,8 +26,11 @@ module Utils ignore_interrupts(:quietly) do # the child will receive the interrupt and marshal it back begin 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 retry unless Process.waitpid(pid, Process::WNOHANG) + # rubocop:enable Lint/ShadowedException else socket.send_io(write) socket.close @@ -36,7 +39,7 @@ module Utils data = read.read read.close 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 "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success? end diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index 3ac7480371..d43e0c6657 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -213,110 +213,6 @@ class Version 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) version = _parse(spec) 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) return m.captures.first unless m.nil? 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 class HeadVersion < Version