summaryrefslogtreecommitdiff
path: root/lib/bundler/cli
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bundler/cli')
-rw-r--r--lib/bundler/cli/add.rb8
-rw-r--r--lib/bundler/cli/binstubs.rb16
-rw-r--r--lib/bundler/cli/cache.rb2
-rw-r--r--lib/bundler/cli/check.rb6
-rw-r--r--lib/bundler/cli/common.rb16
-rw-r--r--lib/bundler/cli/config.rb26
-rw-r--r--lib/bundler/cli/console.rb9
-rw-r--r--lib/bundler/cli/doctor.rb14
-rw-r--r--lib/bundler/cli/exec.rb2
-rw-r--r--lib/bundler/cli/gem.rb116
-rw-r--r--lib/bundler/cli/info.rb28
-rw-r--r--lib/bundler/cli/init.rb8
-rw-r--r--lib/bundler/cli/install.rb54
-rw-r--r--lib/bundler/cli/issue.rb2
-rw-r--r--lib/bundler/cli/lock.rb65
-rw-r--r--lib/bundler/cli/open.rb18
-rw-r--r--lib/bundler/cli/outdated.rb31
-rw-r--r--lib/bundler/cli/platform.rb14
-rw-r--r--lib/bundler/cli/plugin.rb24
-rw-r--r--lib/bundler/cli/pristine.rb68
-rw-r--r--lib/bundler/cli/show.rb6
-rw-r--r--lib/bundler/cli/update.rb11
-rw-r--r--lib/bundler/cli/viz.rb2
23 files changed, 294 insertions, 252 deletions
diff --git a/lib/bundler/cli/add.rb b/lib/bundler/cli/add.rb
index 5bcf30d82d..002d9e1d33 100644
--- a/lib/bundler/cli/add.rb
+++ b/lib/bundler/cli/add.rb
@@ -28,9 +28,9 @@ module Bundler
dependencies = gems.map {|g| Bundler::Dependency.new(g, version, options) }
Injector.inject(dependencies,
- :conservative_versioning => options[:version].nil?, # Perform conservative versioning only when version is not specified
- :optimistic => options[:optimistic],
- :strict => options[:strict])
+ conservative_versioning: options[:version].nil?, # Perform conservative versioning only when version is not specified
+ optimistic: options[:optimistic],
+ strict: options[:strict])
end
def validate_options!
@@ -40,7 +40,7 @@ module Bundler
raise InvalidOption, "Please specify gems to add." if gems.empty?
version.to_a.each do |v|
- raise InvalidOption, "Invalid gem requirement pattern '#{v}'" unless Gem::Requirement::PATTERN =~ v.to_s
+ raise InvalidOption, "Invalid gem requirement pattern '#{v}'" unless Gem::Requirement::PATTERN.match?(v.to_s)
end
end
end
diff --git a/lib/bundler/cli/binstubs.rb b/lib/bundler/cli/binstubs.rb
index 639c01ff39..8ce138df96 100644
--- a/lib/bundler/cli/binstubs.rb
+++ b/lib/bundler/cli/binstubs.rb
@@ -11,15 +11,15 @@ module Bundler
def run
Bundler.definition.validate_runtime!
path_option = options["path"]
- path_option = nil if path_option && path_option.empty?
+ path_option = nil if path_option&.empty?
Bundler.settings.set_command_option :bin, path_option if options["path"]
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
installer = Installer.new(Bundler.root, Bundler.definition)
installer_opts = {
- :force => options[:force],
- :binstubs_cmd => true,
- :all_platforms => options["all-platforms"],
+ force: options[:force],
+ binstubs_cmd: true,
+ all_platforms: options["all-platforms"],
}
if options[:all]
@@ -40,8 +40,12 @@ module Bundler
end
if options[:standalone]
- next Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") if gem_name == "bundler"
- Bundler.settings.temporary(:path => (Bundler.settings[:path] || Bundler.root)) do
+ if gem_name == "bundler"
+ Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") unless options[:all]
+ next
+ end
+
+ Bundler.settings.temporary(path: Bundler.settings[:path] || Bundler.root) do
installer.generate_standalone_bundler_executable_stubs(spec, installer_opts)
end
else
diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb
index c8698ed7e3..2e63a16ec3 100644
--- a/lib/bundler/cli/cache.rb
+++ b/lib/bundler/cli/cache.rb
@@ -19,7 +19,7 @@ module Bundler
# TODO: move cache contents here now that all bundles are locked
custom_path = Bundler.settings[:path] if options[:path]
- Bundler.settings.temporary(:cache_all_platforms => options["all-platforms"]) do
+ Bundler.settings.temporary(cache_all_platforms: options["all-platforms"]) do
Bundler.load.cache(custom_path)
end
end
diff --git a/lib/bundler/cli/check.rb b/lib/bundler/cli/check.rb
index 65c51337d2..33d31cdd27 100644
--- a/lib/bundler/cli/check.rb
+++ b/lib/bundler/cli/check.rb
@@ -17,7 +17,7 @@ module Bundler
begin
definition.resolve_only_locally!
not_installed = definition.missing_specs
- rescue GemNotFound, VersionConflict
+ rescue GemNotFound, SolveFailure
Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies."
Bundler.ui.warn "Install missing gems with `bundle install`."
exit 1
@@ -29,10 +29,10 @@ module Bundler
Bundler.ui.warn "Install missing gems with `bundle install`"
exit 1
elsif !Bundler.default_lockfile.file? && Bundler.frozen_bundle?
- Bundler.ui.error "This bundle has been frozen, but there is no #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} present"
+ Bundler.ui.error "This bundle has been frozen, but there is no #{SharedHelpers.relative_lockfile_path} present"
exit 1
else
- Bundler.load.lock(:preserve_unknown_sections => true) unless options[:"dry-run"]
+ Bundler.load.lock(preserve_unknown_sections: true) unless options[:"dry-run"]
Bundler.ui.info "The Gemfile's dependencies are satisfied"
end
end
diff --git a/lib/bundler/cli/common.rb b/lib/bundler/cli/common.rb
index ba259143b7..7ef6deb2cf 100644
--- a/lib/bundler/cli/common.rb
+++ b/lib/bundler/cli/common.rb
@@ -15,6 +15,7 @@ module Bundler
end
def self.output_fund_metadata_summary
+ return if Bundler.settings["ignore_funding_requests"]
definition = Bundler.definition
current_dependencies = definition.requested_dependencies
current_specs = definition.specs
@@ -40,7 +41,7 @@ module Bundler
end
def self.verbalize_groups(groups)
- groups.map!{|g| "'#{g}'" }
+ groups.map! {|g| "'#{g}'" }
group_list = [groups[0...-1].join(", "), groups[-1..-1]].
reject {|s| s.to_s.empty? }.join(" and ")
group_str = groups.size == 1 ? "group" : "groups"
@@ -53,9 +54,12 @@ module Bundler
Bundler.definition.specs.each do |spec|
return spec if spec.name == name
- specs << spec if regexp && spec.name =~ regexp
+ specs << spec if regexp && spec.name.match?(regexp)
end
+ default_spec = default_gem_spec(name)
+ specs << default_spec if default_spec
+
case specs.count
when 0
dep_in_other_group = Bundler.definition.current_dependencies.find {|dep|dep.name == name }
@@ -74,6 +78,11 @@ module Bundler
raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
end
+ def self.default_gem_spec(name)
+ gem_spec = Gem::Specification.find_all_by_name(name).last
+ gem_spec if gem_spec&.default_gem?
+ end
+
def self.ask_for_spec_from(specs)
specs.each_with_index do |spec, index|
Bundler.ui.info "#{index.succ} : #{spec.name}", true
@@ -109,7 +118,8 @@ module Bundler
definition.gem_version_promoter.tap do |gvp|
gvp.level = patch_level.first || :major
- gvp.strict = options[:strict] || options["update-strict"] || options["filter-strict"]
+ gvp.strict = options[:strict] || options["filter-strict"]
+ gvp.pre = options[:pre]
end
end
diff --git a/lib/bundler/cli/config.rb b/lib/bundler/cli/config.rb
index 8d2aba0916..77b502fe60 100644
--- a/lib/bundler/cli/config.rb
+++ b/lib/bundler/cli/config.rb
@@ -2,17 +2,17 @@
module Bundler
class CLI::Config < Thor
- class_option :parseable, :type => :boolean, :banner => "Use minimal formatting for more parseable output"
+ class_option :parseable, type: :boolean, banner: "Use minimal formatting for more parseable output"
def self.scope_options
- method_option :global, :type => :boolean, :banner => "Only change the global config"
- method_option :local, :type => :boolean, :banner => "Only change the local config"
+ method_option :global, type: :boolean, banner: "Only change the global config"
+ method_option :local, type: :boolean, banner: "Only change the local config"
end
private_class_method :scope_options
- desc "base NAME [VALUE]", "The Bundler 1 config interface", :hide => true
+ desc "base NAME [VALUE]", "The Bundler 1 config interface", hide: true
scope_options
- method_option :delete, :type => :boolean, :banner => "delete"
+ method_option :delete, type: :boolean, banner: "delete"
def base(name = nil, *value)
new_args =
if ARGV.size == 1
@@ -25,8 +25,9 @@ module Bundler
["config", "get", ARGV[1]]
end
- SharedHelpers.major_deprecation 3,
- "Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle #{new_args.join(" ")}` instead."
+ message = "Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle #{new_args.join(" ")}` instead."
+ removed_message = "Using the `config` command without a subcommand [list, get, set, unset] is has been removed. Use `bundle #{new_args.join(" ")}` instead."
+ SharedHelpers.major_deprecation 3, message, removed_message: removed_message
Base.new(options, name, value, self).run
end
@@ -180,7 +181,7 @@ module Bundler
scopes = %w[global local].select {|s| options[s] }
case scopes.size
when 0
- @scope = "global"
+ @scope = inside_app? ? "local" : "global"
@explicit_scope = false
when 1
@scope = scopes.first
@@ -189,6 +190,15 @@ module Bundler
"The options #{scopes.join " and "} were specified. Please only use one of the switches at a time."
end
end
+
+ private
+
+ def inside_app?
+ Bundler.root
+ true
+ rescue GemfileNotFound
+ false
+ end
end
end
end
diff --git a/lib/bundler/cli/console.rb b/lib/bundler/cli/console.rb
index 97b8dc0663..840cf14fd7 100644
--- a/lib/bundler/cli/console.rb
+++ b/lib/bundler/cli/console.rb
@@ -9,8 +9,9 @@ module Bundler
end
def run
- Bundler::SharedHelpers.major_deprecation 2, "bundle console will be replaced " \
- "by `bin/console` generated by `bundle gem <name>`"
+ message = "bundle console will be replaced by `bin/console` generated by `bundle gem <name>`"
+ removed_message = "bundle console has been replaced by `bin/console` generated by `bundle gem <name>`"
+ Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
group ? Bundler.require(:default, *group.split(" ").map!(&:to_sym)) : Bundler.require
ARGV.clear
@@ -30,9 +31,9 @@ module Bundler
def get_constant(name)
const_name = {
- "pry" => :Pry,
+ "pry" => :Pry,
"ripl" => :Ripl,
- "irb" => :IRB,
+ "irb" => :IRB,
}[name]
Object.const_get(const_name)
rescue NameError
diff --git a/lib/bundler/cli/doctor.rb b/lib/bundler/cli/doctor.rb
index 74444ad0ce..1f6fc93c16 100644
--- a/lib/bundler/cli/doctor.rb
+++ b/lib/bundler/cli/doctor.rb
@@ -6,8 +6,8 @@ require "fiddle"
module Bundler
class CLI::Doctor
- DARWIN_REGEX = /\s+(.+) \(compatibility /.freeze
- LDD_REGEX = /\t\S+ => (\S+) \(\S+\)/.freeze
+ DARWIN_REGEX = /\s+(.+) \(compatibility /
+ LDD_REGEX = /\t\S+ => (\S+) \(\S+\)/
attr_reader :options
@@ -73,12 +73,10 @@ module Bundler
definition.specs.each do |spec|
bundles_for_gem(spec).each do |bundle|
bad_paths = dylibs(bundle).select do |f|
- begin
- Fiddle.dlopen(f)
- false
- rescue Fiddle::DLError
- true
- end
+ Fiddle.dlopen(f)
+ false
+ rescue Fiddle::DLError
+ true
end
if bad_paths.any?
broken_links[spec] ||= []
diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb
index 42b602a055..f81cd5d2c4 100644
--- a/lib/bundler/cli/exec.rb
+++ b/lib/bundler/cli/exec.rb
@@ -12,7 +12,7 @@ module Bundler
@options = options
@cmd = args.shift
@args = args
- @args << { :close_others => !options.keep_file_descriptors? } unless Bundler.current_ruby.jruby?
+ @args << { close_others: !options.keep_file_descriptors? } unless Bundler.current_ruby.jruby?
end
def run
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index c4c76d1b69..b6571d0e86 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -11,11 +11,11 @@ module Bundler
class CLI::Gem
TEST_FRAMEWORK_VERSIONS = {
"rspec" => "3.0",
- "minitest" => "5.0",
+ "minitest" => "5.16",
"test-unit" => "3.0",
}.freeze
- attr_reader :options, :gem_name, :thor, :name, :target
+ attr_reader :options, :gem_name, :thor, :name, :target, :extension
def initialize(options, gem_name, thor)
@options = options
@@ -28,7 +28,10 @@ module Bundler
@name = @gem_name
@target = SharedHelpers.pwd.join(gem_name)
- validate_ext_name if options[:ext]
+ @extension = options[:ext]
+
+ validate_ext_name if @extension
+ validate_rust_builder_rubygems_version if @extension == "rust"
end
def run
@@ -55,22 +58,23 @@ module Bundler
end
config = {
- :name => name,
- :underscored_name => underscored_name,
- :namespaced_path => namespaced_path,
- :makefile_path => "#{underscored_name}/#{underscored_name}",
- :constant_name => constant_name,
- :constant_array => constant_array,
- :author => git_author_name.empty? ? "TODO: Write your name" : git_author_name,
- :email => git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
- :test => options[:test],
- :ext => options[:ext],
- :exe => options[:exe],
- :bundler_version => bundler_dependency_version,
- :git => use_git,
- :github_username => github_username.empty? ? "[USERNAME]" : github_username,
- :required_ruby_version => required_ruby_version,
- :minitest_constant_name => minitest_constant_name,
+ name: name,
+ underscored_name: underscored_name,
+ namespaced_path: namespaced_path,
+ makefile_path: "#{underscored_name}/#{underscored_name}",
+ constant_name: constant_name,
+ constant_array: constant_array,
+ author: git_author_name.empty? ? "TODO: Write your name" : git_author_name,
+ email: git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
+ test: options[:test],
+ ext: extension,
+ exe: options[:exe],
+ bundler_version: bundler_dependency_version,
+ git: use_git,
+ github_username: github_username.empty? ? "[USERNAME]" : github_username,
+ required_ruby_version: required_ruby_version,
+ rust_builder_required_rubygems_version: rust_builder_required_rubygems_version,
+ minitest_constant_name: minitest_constant_name,
}
ensure_safe_gem_name(name, constant_array)
@@ -132,12 +136,13 @@ module Bundler
case config[:ci]
when "github"
templates.merge!("github/workflows/main.yml.tt" => ".github/workflows/main.yml")
- when "travis"
- templates.merge!("travis.yml.tt" => ".travis.yml")
+ config[:ci_config_path] = ".github "
when "gitlab"
templates.merge!("gitlab-ci.yml.tt" => ".gitlab-ci.yml")
+ config[:ci_config_path] = ".gitlab-ci.yml "
when "circle"
templates.merge!("circleci/config.yml.tt" => ".circleci/config.yml")
+ config[:ci_config_path] = ".circleci "
end
if ask_and_set(:mit, "Do you want to license your code permissively under the MIT license?",
@@ -188,14 +193,23 @@ module Bundler
templates.merge!("exe/newgem.tt" => "exe/#{name}") if config[:exe]
- if options[:ext]
+ if extension == "c"
templates.merge!(
- "ext/newgem/extconf.rb.tt" => "ext/#{name}/extconf.rb",
+ "ext/newgem/extconf-c.rb.tt" => "ext/#{name}/extconf.rb",
"ext/newgem/newgem.h.tt" => "ext/#{name}/#{underscored_name}.h",
"ext/newgem/newgem.c.tt" => "ext/#{name}/#{underscored_name}.c"
)
end
+ if extension == "rust"
+ templates.merge!(
+ "Cargo.toml.tt" => "Cargo.toml",
+ "ext/newgem/Cargo.toml.tt" => "ext/#{name}/Cargo.toml",
+ "ext/newgem/extconf-rust.rb.tt" => "ext/#{name}/extconf.rb",
+ "ext/newgem/src/lib.rs.tt" => "ext/#{name}/src/lib.rs",
+ )
+ end
+
if target.exist? && !target.directory?
Bundler.ui.error "Couldn't create a new gem named `#{gem_name}` because there's an existing file named `#{gem_name}`."
exit Bundler::BundlerError.all_errors[Bundler::GenericSystemCallError]
@@ -221,9 +235,7 @@ module Bundler
end
if use_git
- Dir.chdir(target) do
- `git add .`
- end
+ IO.popen(%w[git add .], { chdir: target }, &:read)
end
# Open gemspec in editor
@@ -270,7 +282,7 @@ module Bundler
Bundler.ui.info hint_text("test")
result = Bundler.ui.ask "Enter a test framework. rspec/minitest/test-unit/(none):"
- if result =~ /rspec|minitest|test-unit/
+ if /rspec|minitest|test-unit/.match?(result)
test_framework = result
else
test_framework = false
@@ -306,12 +318,11 @@ module Bundler
"* CircleCI: https://circleci.com/\n" \
"* GitHub Actions: https://github.com/features/actions\n" \
"* GitLab CI: https://docs.gitlab.com/ee/ci/\n" \
- "* Travis CI: https://travis-ci.org/\n" \
"\n"
Bundler.ui.info hint_text("ci")
- result = Bundler.ui.ask "Enter a CI service. github/travis/gitlab/circle/(none):"
- if result =~ /github|travis|gitlab|circle/
+ result = Bundler.ui.ask "Enter a CI service. github/gitlab/circle/(none):"
+ if /github|gitlab|circle/.match?(result)
ci_template = result
else
ci_template = false
@@ -337,12 +348,12 @@ module Bundler
Bundler.ui.confirm "Do you want to add a code linter and formatter to your gem? " \
"Supported Linters:\n" \
"* RuboCop: https://rubocop.org\n" \
- "* Standard: https://github.com/testdouble/standard\n" \
+ "* Standard: https://github.com/standardrb/standard\n" \
"\n"
Bundler.ui.info hint_text("linter")
result = Bundler.ui.ask "Enter a linter. rubocop/standard/(none):"
- if result =~ /rubocop|standard/
+ if /rubocop|standard/.match?(result)
linter_template = result
else
linter_template = false
@@ -368,15 +379,20 @@ module Bundler
def deprecated_rubocop_option
if !options[:rubocop].nil?
if options[:rubocop]
- Bundler::SharedHelpers.major_deprecation 2, "--rubocop is deprecated, use --linter=rubocop"
+ Bundler::SharedHelpers.major_deprecation 2,
+ "--rubocop is deprecated, use --linter=rubocop",
+ removed_message: "--rubocop has been removed, use --linter=rubocop"
"rubocop"
else
- Bundler::SharedHelpers.major_deprecation 2, "--no-rubocop is deprecated, use --linter"
+ Bundler::SharedHelpers.major_deprecation 2,
+ "--no-rubocop is deprecated, use --linter",
+ removed_message: "--no-rubocop has been removed, use --linter"
false
end
elsif !Bundler.settings["gem.rubocop"].nil?
Bundler::SharedHelpers.major_deprecation 2,
- "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead"
+ "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead",
+ removed_message: "config gem.rubocop has been removed; we've updated your config to use gem.linter instead"
Bundler.settings["gem.rubocop"] ? "rubocop" : false
end
end
@@ -389,7 +405,7 @@ module Bundler
end
def ensure_safe_gem_name(name, constant_array)
- if name =~ /^\d/
+ if /^\d/.match?(name)
Bundler.ui.error "Invalid gem name #{name} Please give a name which does not start with numbers."
exit 1
end
@@ -415,28 +431,26 @@ module Bundler
thor.run(%(#{editor} "#{file}"))
end
+ def rust_builder_required_rubygems_version
+ "3.3.11"
+ end
+
def required_ruby_version
- if Gem.ruby_version < Gem::Version.new("2.4.a") then "2.3.0"
- elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "2.4.0"
- elsif Gem.ruby_version < Gem::Version.new("2.6.a") then "2.5.0"
- else
- "2.6.0"
- end
+ "3.0.0"
end
def rubocop_version
- if Gem.ruby_version < Gem::Version.new("2.4.a") then "0.81.0"
- elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "1.12"
- else
- "1.21"
- end
+ "1.21"
end
def standard_version
- if Gem.ruby_version < Gem::Version.new("2.4.a") then "0.2.5"
- elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "1.0"
- else
- "1.3"
+ "1.3"
+ end
+
+ def validate_rust_builder_rubygems_version
+ if Gem::Version.new(rust_builder_required_rubygems_version) > Gem.rubygems_version
+ Bundler.ui.error "Your RubyGems version (#{Gem.rubygems_version}) is too old to build Rust extension. Please update your RubyGems using `gem update --system` or any other way and try again."
+ exit 1
end
end
end
diff --git a/lib/bundler/cli/info.rb b/lib/bundler/cli/info.rb
index 76c8cf60c0..8f34956aca 100644
--- a/lib/bundler/cli/info.rb
+++ b/lib/bundler/cli/info.rb
@@ -25,19 +25,8 @@ module Bundler
private
- def spec_for_gem(gem_name)
- spec = Bundler.definition.specs.find {|s| s.name == gem_name }
- spec || default_gem_spec(gem_name) || Bundler::CLI::Common.select_spec(gem_name, :regex_match)
- end
-
- def default_gem_spec(gem_name)
- return unless Gem::Specification.respond_to?(:find_all_by_name)
- gem_spec = Gem::Specification.find_all_by_name(gem_name).last
- return gem_spec if gem_spec && gem_spec.respond_to?(:default_gem?) && gem_spec.default_gem?
- end
-
- def spec_not_found(gem_name)
- raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(gem_name, Bundler.definition.dependencies)
+ def spec_for_gem(name)
+ Bundler::CLI::Common.select_spec(name, :regex_match)
end
def print_gem_version(spec)
@@ -47,7 +36,7 @@ module Bundler
def print_gem_path(spec)
name = spec.name
if name == "bundler"
- path = File.expand_path("../../../..", __FILE__)
+ path = File.expand_path("../../..", __dir__)
else
path = spec.full_gem_path
if spec.deleted_gem?
@@ -73,7 +62,8 @@ module Bundler
gem_info << "\tBug Tracker: #{metadata["bug_tracker_uri"]}\n" if metadata.key?("bug_tracker_uri")
gem_info << "\tMailing List: #{metadata["mailing_list_uri"]}\n" if metadata.key?("mailing_list_uri")
gem_info << "\tPath: #{spec.full_gem_path}\n"
- gem_info << "\tDefault Gem: yes" if spec.respond_to?(:default_gem?) && spec.default_gem?
+ gem_info << "\tDefault Gem: yes\n" if spec.respond_to?(:default_gem?) && spec.default_gem?
+ gem_info << "\tReverse Dependencies: \n\t\t#{gem_dependencies.join("\n\t\t")}" if gem_dependencies.any?
if name != "bundler" && spec.deleted_gem?
return Bundler.ui.warn "The gem #{name} has been deleted. Gemspec information is still available though:\n#{gem_info}"
@@ -81,5 +71,13 @@ module Bundler
Bundler.ui.info gem_info
end
+
+ def gem_dependencies
+ @gem_dependencies ||= Bundler.definition.specs.map do |spec|
+ dependency = spec.dependencies.find {|dep| dep.name == gem_name }
+ next unless dependency
+ "#{spec.name} (#{spec.version}) depends on #{gem_name} (#{dependency.requirements_list.join(", ")})"
+ end.compact.sort
+ end
end
end
diff --git a/lib/bundler/cli/init.rb b/lib/bundler/cli/init.rb
index d851d02d42..246b9d6460 100644
--- a/lib/bundler/cli/init.rb
+++ b/lib/bundler/cli/init.rb
@@ -32,7 +32,11 @@ module Bundler
file << spec.to_gemfile
end
else
- FileUtils.cp(File.expand_path("../../templates/#{gemfile}", __FILE__), gemfile)
+ File.open(File.expand_path("../templates/Gemfile", __dir__), "r") do |template|
+ File.open(gemfile, "wb") do |destination|
+ IO.copy_stream(template, destination)
+ end
+ end
end
puts "Writing new #{gemfile} to #{SharedHelpers.pwd}/#{gemfile}"
@@ -41,7 +45,7 @@ module Bundler
private
def gemfile
- @gemfile ||= Bundler.preferred_gemfile_name
+ @gemfile ||= options[:gemfile] || Bundler.preferred_gemfile_name
end
end
end
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index c3400c3959..6c102d537d 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -28,8 +28,8 @@ module Bundler
flag = "--deployment flag" if options[:deployment]
flag ||= "--frozen flag" if options[:frozen]
flag ||= "deployment setting"
- raise ProductionError, "The #{flag} requires a #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}. Please make " \
- "sure you have checked your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} into version control " \
+ raise ProductionError, "The #{flag} requires a lockfile. Please make " \
+ "sure you have checked your #{SharedHelpers.relative_lockfile_path} into version control " \
"before deploying."
end
@@ -51,7 +51,8 @@ module Bundler
if options["binstubs"]
Bundler::SharedHelpers.major_deprecation 2,
- "The --binstubs option will be removed in favor of `bundle binstubs --all`"
+ "The --binstubs option will be removed in favor of `bundle binstubs --all`",
+ removed_message: "The --binstubs option have been removed in favor of `bundle binstubs --all`"
end
Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins?
@@ -61,7 +62,7 @@ module Bundler
installer = Installer.install(Bundler.root, definition, options)
- Bundler.settings.temporary(:cache_all_platforms => options[:local] ? false : Bundler.settings[:cache_all_platforms]) do
+ Bundler.settings.temporary(cache_all_platforms: options[:local] ? false : Bundler.settings[:cache_all_platforms]) do
Bundler.load.cache(nil, options[:local]) if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle?
end
@@ -94,9 +95,8 @@ module Bundler
def warn_if_root
return if Bundler.settings[:silence_root_warning] || Gem.win_platform? || !Process.uid.zero?
- Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \
- "if it is needed, and installing your bundle as root will break this " \
- "application for all non-root users on this machine.", :wrap => true
+ Bundler.ui.warn "Don't run Bundler as root. Installing your bundle as root " \
+ "will break this application for all non-root users on this machine.", wrap: true
end
def dependencies_count_for(definition)
@@ -135,43 +135,27 @@ module Bundler
end
def normalize_groups
- options[:with] &&= options[:with].join(":").tr(" ", ":").split(":")
- options[:without] &&= options[:without].join(":").tr(" ", ":").split(":")
-
check_for_group_conflicts_in_cli_options
- Bundler.settings.set_command_option :with, nil if options[:with] == []
- Bundler.settings.set_command_option :without, nil if options[:without] == []
-
- with = options.fetch(:with, [])
- with |= Bundler.settings[:with].map(&:to_s)
- with -= options[:without] if options[:without]
-
- without = options.fetch(:without, [])
- without |= Bundler.settings[:without].map(&:to_s)
- without -= options[:with] if options[:with]
-
- options[:with] = with
- options[:without] = without
-
- unless Bundler.settings[:without] == options[:without] && Bundler.settings[:with] == options[:with]
- # need to nil them out first to get around validation for backwards compatibility
- Bundler.settings.set_command_option :without, nil
- Bundler.settings.set_command_option :with, nil
- Bundler.settings.set_command_option :without, options[:without] - options[:with]
- Bundler.settings.set_command_option :with, options[:with]
- end
+ # need to nil them out first to get around validation for backwards compatibility
+ Bundler.settings.set_command_option :without, nil
+ Bundler.settings.set_command_option :with, nil
+ Bundler.settings.set_command_option :without, options[:without]
+ Bundler.settings.set_command_option :with, options[:with]
end
def normalize_settings
Bundler.settings.set_command_option :path, nil if options[:system]
Bundler.settings.set_command_option_if_given :path, options[:path]
- Bundler.settings.temporary(:path_relative_to_cwd => false) do
- Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil?
+
+ if options["standalone"] && Bundler.settings[:path].nil? && !options["local"]
+ Bundler.settings.temporary(path_relative_to_cwd: false) do
+ Bundler.settings.set_command_option :path, "bundle"
+ end
end
bin_option = options["binstubs"]
- bin_option = nil if bin_option && bin_option.empty?
+ bin_option = nil if bin_option&.empty?
Bundler.settings.set_command_option :bin, bin_option if options["binstubs"]
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
@@ -184,7 +168,7 @@ module Bundler
Bundler.settings.set_command_option_if_given :clean, options["clean"]
- normalize_groups
+ normalize_groups if options[:without] || options[:with]
options[:force] = options[:redownload]
end
diff --git a/lib/bundler/cli/issue.rb b/lib/bundler/cli/issue.rb
index b891ecb1d2..5f2924c4bd 100644
--- a/lib/bundler/cli/issue.rb
+++ b/lib/bundler/cli/issue.rb
@@ -5,7 +5,7 @@ require "rbconfig"
module Bundler
class CLI::Issue
def run
- Bundler.ui.info <<-EOS.gsub(/^ {8}/, "")
+ Bundler.ui.info <<~EOS
Did you find an issue with Bundler? Before filing a new issue,
be sure to check out these resources:
diff --git a/lib/bundler/cli/lock.rb b/lib/bundler/cli/lock.rb
index 7d613a6644..dac3d2a09a 100644
--- a/lib/bundler/cli/lock.rb
+++ b/lib/bundler/cli/lock.rb
@@ -15,53 +15,60 @@ module Bundler
end
print = options[:print]
- ui = Bundler.ui
- Bundler.ui = UI::Silent.new if print
+ previous_ui_level = Bundler.ui.level
+ Bundler.ui.level = "silent" if print
Bundler::Fetcher.disable_endpoint = options["full-index"]
update = options[:update]
conservative = options[:conservative]
+ bundler = options[:bundler]
if update.is_a?(Array) # unlocking specific gems
Bundler::CLI::Common.ensure_all_gems_in_lockfile!(update)
- update = { :gems => update, :conservative => conservative }
- elsif update
- update = { :conservative => conservative } if conservative
+ update = { gems: update, conservative: conservative }
+ elsif update && conservative
+ update = { conservative: conservative }
+ elsif update && bundler
+ update = { bundler: bundler }
end
- definition = Bundler.definition(update)
- Bundler::CLI::Common.configure_gem_version_promoter(Bundler.definition, options) if options[:update]
+ file = options[:lockfile]
+ file = file ? Pathname.new(file).expand_path : Bundler.default_lockfile
- options["remove-platform"].each do |platform|
- definition.remove_platform(platform)
- end
+ Bundler.settings.temporary(frozen: false) do
+ definition = Bundler.definition(update, file)
+
+ Bundler::CLI::Common.configure_gem_version_promoter(definition, options) if options[:update]
- options["add-platform"].each do |platform_string|
- platform = Gem::Platform.new(platform_string)
- if platform.to_s == "unknown"
- Bundler.ui.warn "The platform `#{platform_string}` is unknown to RubyGems " \
- "and adding it will likely lead to resolution errors"
+ options["remove-platform"].each do |platform|
+ definition.remove_platform(platform)
end
- definition.add_platform(platform)
- end
- if definition.platforms.empty?
- raise InvalidOption, "Removing all platforms from the bundle is not allowed"
- end
+ options["add-platform"].each do |platform_string|
+ platform = Gem::Platform.new(platform_string)
+ if platform.to_s == "unknown"
+ Bundler.ui.warn "The platform `#{platform_string}` is unknown to RubyGems " \
+ "and adding it will likely lead to resolution errors"
+ end
+ definition.add_platform(platform)
+ end
+
+ if definition.platforms.empty?
+ raise InvalidOption, "Removing all platforms from the bundle is not allowed"
+ end
- definition.resolve_remotely! unless options[:local]
+ definition.resolve_remotely! unless options[:local]
- if print
- puts definition.to_lock
- else
- file = options[:lockfile]
- file = file ? File.expand_path(file) : Bundler.default_lockfile
- puts "Writing lockfile to #{file}"
- definition.lock(file)
+ if print
+ puts definition.to_lock
+ else
+ puts "Writing lockfile to #{file}"
+ definition.lock
+ end
end
- Bundler.ui = ui
+ Bundler.ui.level = previous_ui_level
end
end
end
diff --git a/lib/bundler/cli/open.rb b/lib/bundler/cli/open.rb
index ea504344f3..f24693b843 100644
--- a/lib/bundler/cli/open.rb
+++ b/lib/bundler/cli/open.rb
@@ -2,27 +2,27 @@
module Bundler
class CLI::Open
- attr_reader :options, :name
+ attr_reader :options, :name, :path
def initialize(options, name)
@options = options
@name = name
+ @path = options[:path] unless options[:path].nil?
end
def run
+ raise InvalidOption, "Cannot specify `--path` option without a value" if !@path.nil? && @path.empty?
editor = [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }
return Bundler.ui.info("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR") unless editor
return unless spec = Bundler::CLI::Common.select_spec(name, :regex_match)
if spec.default_gem?
Bundler.ui.info "Unable to open #{name} because it's a default gem, so the directory it would normally be installed to does not exist."
else
- path = spec.full_gem_path
- Dir.chdir(path) do
- require "shellwords"
- command = Shellwords.split(editor) + [path]
- Bundler.with_original_env do
- system(*command)
- end || Bundler.ui.info("Could not run '#{command.join(" ")}'")
- end
+ root_path = spec.full_gem_path
+ require "shellwords"
+ command = Shellwords.split(editor) << File.join([root_path, path].compact)
+ Bundler.with_original_env do
+ system(*command, { chdir: root_path })
+ end || Bundler.ui.info("Could not run '#{command.join(" ")}'")
end
end
end
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index d5183b060b..ec42e631bb 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -41,12 +41,12 @@ module Bundler
# We're doing a full update
Bundler.definition(true)
else
- Bundler.definition(:gems => gems, :sources => sources)
+ Bundler.definition(gems: gems, sources: sources)
end
Bundler::CLI::Common.configure_gem_version_promoter(
Bundler.definition,
- options
+ options.merge(strict: @strict)
)
definition_resolution = proc do
@@ -90,10 +90,10 @@ module Bundler
end
outdated_gems << {
- :active_spec => active_spec,
- :current_spec => current_spec,
- :dependency => dependency,
- :groups => groups,
+ active_spec: active_spec,
+ current_spec: current_spec,
+ dependency: dependency,
+ groups: groups,
}
end
@@ -111,9 +111,7 @@ module Bundler
end.compact
if options[:parseable]
- relevant_outdated_gems.each do |gems|
- print_gems(gems)
- end
+ print_gems(relevant_outdated_gems)
else
print_gems_table(relevant_outdated_gems)
end
@@ -129,6 +127,12 @@ module Bundler
private
+ def loaded_from_for(spec)
+ return unless spec.respond_to?(:loaded_from)
+
+ spec.loaded_from
+ end
+
def groups_text(group_text, groups)
"#{group_text}#{groups.split(",").size > 1 ? "s" : ""} \"#{groups}\""
end
@@ -184,10 +188,13 @@ module Bundler
def print_gem(current_spec, active_spec, dependency, groups)
spec_version = "#{active_spec.version}#{active_spec.git_version}"
- spec_version += " (from #{active_spec.loaded_from})" if Bundler.ui.debug? && active_spec.loaded_from
+ if Bundler.ui.debug?
+ loaded_from = loaded_from_for(active_spec)
+ spec_version += " (from #{loaded_from})" if loaded_from
+ end
current_version = "#{current_spec.version}#{current_spec.git_version}"
- if dependency && dependency.specific?
+ if dependency&.specific?
dependency_version = %(, requested #{dependency.requirement})
end
@@ -211,7 +218,7 @@ module Bundler
dependency = dependency.requirement if dependency
ret_val = [active_spec.name, current_version, spec_version, dependency.to_s, groups.to_s]
- ret_val << active_spec.loaded_from.to_s if Bundler.ui.debug?
+ ret_val << loaded_from_for(active_spec).to_s if Bundler.ui.debug?
ret_val
end
diff --git a/lib/bundler/cli/platform.rb b/lib/bundler/cli/platform.rb
index e97cad49a4..32d68abbb1 100644
--- a/lib/bundler/cli/platform.rb
+++ b/lib/bundler/cli/platform.rb
@@ -8,12 +8,12 @@ module Bundler
end
def run
- platforms, ruby_version = Bundler.ui.silence do
- locked_ruby_version = Bundler.locked_gems && Bundler.locked_gems.ruby_version
- gemfile_ruby_version = Bundler.definition.ruby_version && Bundler.definition.ruby_version.single_version_string
- [Bundler.definition.platforms.map {|p| "* #{p}" },
- locked_ruby_version || gemfile_ruby_version]
+ ruby_version = if Bundler.locked_gems
+ Bundler.locked_gems.ruby_version&.gsub(/p\d+\Z/, "")
+ else
+ Bundler.definition.ruby_version&.single_version_string
end
+
output = []
if options[:ruby]
@@ -23,7 +23,9 @@ module Bundler
output << "No ruby version specified"
end
else
- output << "Your platform is: #{RUBY_PLATFORM}"
+ platforms = Bundler.definition.platforms.map {|p| "* #{p}" }
+
+ output << "Your platform is: #{Gem::Platform.local}"
output << "Your app has gems that work on these platforms:\n#{platforms.join("\n")}"
if ruby_version
diff --git a/lib/bundler/cli/plugin.rb b/lib/bundler/cli/plugin.rb
index fe3f4412fa..fd61ef0d95 100644
--- a/lib/bundler/cli/plugin.rb
+++ b/lib/bundler/cli/plugin.rb
@@ -5,20 +5,15 @@ module Bundler
class CLI::Plugin < Thor
desc "install PLUGINS", "Install the plugin from the source"
long_desc <<-D
- Install plugins either from the rubygems source provided (with --source option) or from a git source provided with --git (for remote repos) or --local_git (for local repos). If no sources are provided, it uses Gem.sources
+ Install plugins either from the rubygems source provided (with --source option), from a git source provided with --git, or a local path provided with --path. If no sources are provided, it uses Gem.sources
D
- method_option "source", :type => :string, :default => nil, :banner =>
- "URL of the RubyGems source to fetch the plugin from"
- method_option "version", :type => :string, :default => nil, :banner =>
- "The version of the plugin to fetch"
- method_option "git", :type => :string, :default => nil, :banner =>
- "URL of the git repo to fetch from"
- method_option "local_git", :type => :string, :default => nil, :banner =>
- "Path of the local git repo to fetch from"
- method_option "branch", :type => :string, :default => nil, :banner =>
- "The git branch to checkout"
- method_option "ref", :type => :string, :default => nil, :banner =>
- "The git revision to check out"
+ method_option "source", type: :string, default: nil, banner: "URL of the RubyGems source to fetch the plugin from"
+ method_option "version", type: :string, default: nil, banner: "The version of the plugin to fetch"
+ method_option "git", type: :string, default: nil, banner: "URL of the git repo to fetch from"
+ method_option "local_git", type: :string, default: nil, banner: "Path of the local git repo to fetch from (deprecated)"
+ method_option "branch", type: :string, default: nil, banner: "The git branch to checkout"
+ method_option "ref", type: :string, default: nil, banner: "The git revision to check out"
+ method_option "path", type: :string, default: nil, banner: "Path of a local gem to directly use"
def install(*plugins)
Bundler::Plugin.install(plugins, options)
end
@@ -27,8 +22,7 @@ module Bundler
long_desc <<-D
Uninstall given list of plugins. To uninstall all the plugins, use -all option.
D
- method_option "all", :type => :boolean, :default => nil, :banner =>
- "Uninstall all the installed plugins. If no plugin is installed, then it does nothing."
+ method_option "all", type: :boolean, default: nil, banner: "Uninstall all the installed plugins. If no plugin is installed, then it does nothing."
def uninstall(*plugins)
Bundler::Plugin.uninstall(plugins, options)
end
diff --git a/lib/bundler/cli/pristine.rb b/lib/bundler/cli/pristine.rb
index d6654f8053..e0d7452c44 100644
--- a/lib/bundler/cli/pristine.rb
+++ b/lib/bundler/cli/pristine.rb
@@ -12,40 +12,48 @@ module Bundler
definition.validate_runtime!
installer = Bundler::Installer.new(Bundler.root, definition)
- Bundler.load.specs.each do |spec|
- next if spec.name == "bundler" # Source::Rubygems doesn't install bundler
- next if !@gems.empty? && !@gems.include?(spec.name)
-
- gem_name = "#{spec.name} (#{spec.version}#{spec.git_version})"
- gem_name += " (#{spec.platform})" if !spec.platform.nil? && spec.platform != Gem::Platform::RUBY
-
- case source = spec.source
- when Source::Rubygems
- cached_gem = spec.cache_file
- unless File.exist?(cached_gem)
- Bundler.ui.error("Failed to pristine #{gem_name}. Cached gem #{cached_gem} does not exist.")
+ ProcessLock.lock do
+ installed_specs = definition.specs.reject do |spec|
+ next if spec.name == "bundler" # Source::Rubygems doesn't install bundler
+ next if !@gems.empty? && !@gems.include?(spec.name)
+
+ gem_name = "#{spec.name} (#{spec.version}#{spec.git_version})"
+ gem_name += " (#{spec.platform})" if !spec.platform.nil? && spec.platform != Gem::Platform::RUBY
+
+ case source = spec.source
+ when Source::Rubygems
+ cached_gem = spec.cache_file
+ unless File.exist?(cached_gem)
+ Bundler.ui.error("Failed to pristine #{gem_name}. Cached gem #{cached_gem} does not exist.")
+ next
+ end
+
+ FileUtils.rm_rf spec.full_gem_path
+ when Source::Git
+ if source.local?
+ Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is locally overridden.")
+ next
+ end
+
+ source.remote!
+ if extension_cache_path = source.extension_cache_path(spec)
+ FileUtils.rm_rf extension_cache_path
+ end
+ FileUtils.rm_rf spec.extension_dir
+ FileUtils.rm_rf spec.full_gem_path
+ else
+ Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")
next
end
- FileUtils.rm_rf spec.full_gem_path
- when Source::Git
- if source.local?
- Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is locally overridden.")
- next
- end
+ true
+ end.map(&:name)
- source.remote!
- if extension_cache_path = source.extension_cache_path(spec)
- FileUtils.rm_rf extension_cache_path
- end
- FileUtils.rm_rf spec.extension_dir
- FileUtils.rm_rf spec.full_gem_path
- else
- Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")
- next
- end
-
- Bundler::GemInstaller.new(spec, installer, false, 0, true).install_from_spec
+ jobs = installer.send(:installation_parallelization, {})
+ pristine_count = definition.specs.count - installed_specs.count
+ # allow a pristining a single gem to skip the parallel worker
+ jobs = [jobs, pristine_count].min
+ ParallelInstaller.call(installer, definition.specs, jobs, false, true, skip: installed_specs)
end
end
end
diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb
index 5eaaba1ef7..59b0af42e1 100644
--- a/lib/bundler/cli/show.rb
+++ b/lib/bundler/cli/show.rb
@@ -18,7 +18,7 @@ module Bundler
if gem_name
if gem_name == "bundler"
- path = File.expand_path("../../../..", __FILE__)
+ path = File.expand_path("../../..", __dir__)
else
spec = Bundler::CLI::Common.select_spec(gem_name, :regex_match)
return unless spec
@@ -40,8 +40,8 @@ module Bundler
desc = " * #{s.name} (#{s.version}#{s.git_version})"
if @verbose
latest = latest_specs.find {|l| l.name == s.name }
- Bundler.ui.info <<-END.gsub(/^ +/, "")
- #{desc}
+ Bundler.ui.info <<~END
+ #{desc.lstrip}
\tSummary: #{s.summary || "No description available."}
\tHomepage: #{s.homepage || "No website available."}
\tStatus: #{outdated?(s, latest) ? "Outdated - #{s.version} < #{latest.version}" : "Up to date"}
diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb
index b49182655b..985e8db051 100644
--- a/lib/bundler/cli/update.rb
+++ b/lib/bundler/cli/update.rb
@@ -35,7 +35,7 @@ module Bundler
if full_update
if conservative
- Bundler.definition(:conservative => conservative)
+ Bundler.definition(conservative: conservative)
else
Bundler.definition(true)
end
@@ -51,9 +51,9 @@ module Bundler
gems.concat(deps.map(&:name))
end
- Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby],
- :conservative => conservative,
- :bundler => update_bundler)
+ Bundler.definition(gems: gems, sources: sources, ruby: options[:ruby],
+ conservative: conservative,
+ bundler: update_bundler)
end
Bundler::CLI::Common.configure_gem_version_promoter(Bundler.definition, options)
@@ -63,6 +63,7 @@ module Bundler
opts = options.dup
opts["update"] = true
opts["local"] = options[:local]
+ opts["force"] = options[:redownload]
Bundler.settings.set_command_option_if_given :jobs, opts["jobs"]
@@ -70,7 +71,7 @@ module Bundler
if locked_gems = Bundler.definition.locked_gems
previous_locked_info = locked_gems.specs.reduce({}) do |h, s|
- h[s.name] = { :spec => s, :version => s.version, :source => s.source.identifier }
+ h[s.name] = { spec: s, version: s.version, source: s.source.identifier }
h
end
end
diff --git a/lib/bundler/cli/viz.rb b/lib/bundler/cli/viz.rb
index 644f9b25cf..5c09e00995 100644
--- a/lib/bundler/cli/viz.rb
+++ b/lib/bundler/cli/viz.rb
@@ -23,7 +23,7 @@ module Bundler
Bundler.ui.warn "Make sure you have the graphviz ruby gem. You can install it with:"
Bundler.ui.warn "`gem install ruby-graphviz`"
rescue StandardError => e
- raise unless e.message =~ /GraphViz not installed or dot not in PATH/
+ raise unless e.message.to_s.include?("GraphViz not installed or dot not in PATH")
Bundler.ui.error e.message
Bundler.ui.warn "Please install GraphViz. On a Mac with Homebrew, you can run `brew install graphviz`."
end