summaryrefslogtreecommitdiff
path: root/lib/bundler/cli/common.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bundler/cli/common.rb')
-rw-r--r--lib/bundler/cli/common.rb161
1 files changed, 161 insertions, 0 deletions
diff --git a/lib/bundler/cli/common.rb b/lib/bundler/cli/common.rb
new file mode 100644
index 0000000000..b44fbc3096
--- /dev/null
+++ b/lib/bundler/cli/common.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+module Bundler
+ module CLI::Common
+ def self.validate_cooldown!(value)
+ return if value.nil?
+ return if value.is_a?(Integer) && value >= 0
+ raise InvalidOption, "Expected `--cooldown` to be a non-negative integer, got #{value.inspect}"
+ end
+
+ def self.output_post_install_messages(messages)
+ return if Bundler.settings["ignore_messages"]
+ messages.to_a.each do |name, msg|
+ print_post_install_message(name, msg) unless Bundler.settings["ignore_messages.#{name}"]
+ end
+ end
+
+ def self.print_post_install_message(name, msg)
+ Bundler.ui.confirm "Post-install message from #{name}:"
+ Bundler.ui.info msg
+ 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
+
+ count = current_dependencies.count {|dep| current_specs[dep.name].first.metadata.key?("funding_uri") }
+
+ return if count.zero?
+
+ intro = count > 1 ? "#{count} installed gems you directly depend on are" : "#{count} installed gem you directly depend on is"
+ message = "#{intro} looking for funding.\n Run `bundle fund` for details"
+ Bundler.ui.info message
+ end
+
+ def self.output_without_groups_message(command)
+ return if Bundler.settings[:without].empty?
+ Bundler.ui.confirm without_groups_message(command)
+ end
+
+ def self.without_groups_message(command)
+ command_in_past_tense = command == :install ? "installed" : "updated"
+ groups = Bundler.settings[:without]
+ "Gems in the #{verbalize_groups(groups)} were not #{command_in_past_tense}."
+ end
+
+ def self.verbalize_groups(groups)
+ 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"
+ "#{group_str} #{group_list}"
+ end
+
+ def self.select_spec(name, regex_match = nil)
+ specs = []
+ regexp = Regexp.new(name) if regex_match
+
+ Bundler.definition.specs.each do |spec|
+ return spec if spec.name == name
+ 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 }
+
+ if dep_in_other_group
+ raise GemNotFound, "Could not find gem '#{name}', because it's in the #{verbalize_groups(dep_in_other_group.groups)}, configured to be ignored."
+ else
+ raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
+ end
+ when 1
+ specs.first
+ else
+ ask_for_spec_from(specs)
+ end
+ rescue RegexpError
+ 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
+ end
+ Bundler.ui.info "0 : - exit -", true
+
+ num = Bundler.ui.ask("> ").to_i
+ num > 0 ? specs[num - 1] : nil
+ end
+
+ def self.gem_not_found_message(missing_gem_name, alternatives)
+ message = "Could not find gem '#{missing_gem_name}'."
+ alternate_names = alternatives.map {|a| a.respond_to?(:name) ? a.name : a }
+ if alternate_names.include?(missing_gem_name.downcase)
+ message += "\nDid you mean '#{missing_gem_name.downcase}'?"
+ elsif defined?(DidYouMean::SpellChecker)
+ suggestions = DidYouMean::SpellChecker.new(dictionary: alternate_names).correct(missing_gem_name)
+ message += "\nDid you mean #{word_list(suggestions)}?" unless suggestions.empty?
+ end
+ message
+ end
+
+ def self.ensure_all_gems_in_lockfile!(names, locked_gems = Bundler.locked_gems)
+ return unless locked_gems
+
+ locked_names = locked_gems.specs.map(&:name).uniq
+ names.-(locked_names).each do |g|
+ raise GemNotFound, gem_not_found_message(g, locked_names)
+ end
+ end
+
+ def self.configure_gem_version_promoter(definition, options)
+ patch_level = patch_level_options(options)
+ patch_level << :patch if patch_level.empty? && Bundler.settings[:prefer_patch]
+ raise InvalidOption, "Provide only one of the following options: #{patch_level.join(", ")}" unless patch_level.length <= 1
+
+ definition.gem_version_promoter.tap do |gvp|
+ gvp.level = patch_level.first || :major
+ gvp.strict = options[:strict] || options["filter-strict"]
+ gvp.pre = options[:pre]
+ end
+ end
+
+ def self.patch_level_options(options)
+ [:major, :minor, :patch].select {|v| options.keys.include?(v.to_s) }
+ end
+
+ def self.clean_after_install?
+ clean = Bundler.settings[:clean]
+ return clean unless clean.nil?
+ clean ||= Bundler.feature_flag.bundler_5_mode? && Bundler.settings[:path].nil?
+ clean &&= !Bundler.use_system_gems?
+ clean
+ end
+
+ def self.word_list(words)
+ if words.empty?
+ return ""
+ end
+
+ words = words.map {|word| "'#{word}'" }
+
+ if words.length == 1
+ return words[0]
+ end
+
+ [words[0..-2].join(", "), words[-1]].join(" or ")
+ end
+ end
+end