diff options
Diffstat (limited to 'lib/bundler/cli')
| -rw-r--r-- | lib/bundler/cli/add.rb | 17 | ||||
| -rw-r--r-- | lib/bundler/cli/cache.rb | 12 | ||||
| -rw-r--r-- | lib/bundler/cli/common.rb | 29 | ||||
| -rw-r--r-- | lib/bundler/cli/config.rb | 14 | ||||
| -rw-r--r-- | lib/bundler/cli/console.rb | 5 | ||||
| -rw-r--r-- | lib/bundler/cli/exec.rb | 33 | ||||
| -rw-r--r-- | lib/bundler/cli/gem.rb | 77 | ||||
| -rw-r--r-- | lib/bundler/cli/inject.rb | 60 | ||||
| -rw-r--r-- | lib/bundler/cli/install.rb | 98 | ||||
| -rw-r--r-- | lib/bundler/cli/issue.rb | 4 | ||||
| -rw-r--r-- | lib/bundler/cli/lock.rb | 10 | ||||
| -rw-r--r-- | lib/bundler/cli/outdated.rb | 44 | ||||
| -rw-r--r-- | lib/bundler/cli/plugin.rb | 6 | ||||
| -rw-r--r-- | lib/bundler/cli/pristine.rb | 6 | ||||
| -rw-r--r-- | lib/bundler/cli/show.rb | 2 | ||||
| -rw-r--r-- | lib/bundler/cli/update.rb | 8 | ||||
| -rw-r--r-- | lib/bundler/cli/viz.rb | 31 |
17 files changed, 190 insertions, 266 deletions
diff --git a/lib/bundler/cli/add.rb b/lib/bundler/cli/add.rb index 12a681a816..20f76b59d1 100644 --- a/lib/bundler/cli/add.rb +++ b/lib/bundler/cli/add.rb @@ -14,6 +14,9 @@ module Bundler def run Bundler.ui.level = "warn" if options[:quiet] + Bundler::CLI::Common.validate_cooldown!(options[:cooldown]) + Bundler.settings.set_command_option_if_given :cooldown, options[:cooldown] + validate_options! inject_dependencies perform_bundle_install unless options["skip-install"] @@ -31,12 +34,22 @@ module Bundler Injector.inject(dependencies, conservative_versioning: options[:version].nil?, # Perform conservative versioning only when version is not specified - optimistic: options[:optimistic], + pessimistic: options[:pessimistic], strict: options[:strict]) end def validate_options! - raise InvalidOption, "You cannot specify `--strict` and `--optimistic` at the same time." if options[:strict] && options[:optimistic] + raise InvalidOption, "You cannot specify `--git` and `--github` at the same time." if options["git"] && options["github"] + + unless options["git"] || options["github"] + raise InvalidOption, "You cannot specify `--branch` unless `--git` or `--github` is specified." if options["branch"] + + raise InvalidOption, "You cannot specify `--ref` unless `--git` or `--github` is specified." if options["ref"] + end + + raise InvalidOption, "You cannot specify `--branch` and `--ref` at the same time." if options["branch"] && options["ref"] + + raise InvalidOption, "You cannot specify `--strict` and `--pessimistic` at the same time." if options[:strict] && options[:pessimistic] # raise error when no gems are specified raise InvalidOption, "Please specify gems to add." if gems.empty? diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb index 92d7a1c519..59605df847 100644 --- a/lib/bundler/cli/cache.rb +++ b/lib/bundler/cli/cache.rb @@ -10,16 +10,12 @@ module Bundler def run Bundler.ui.level = "warn" if options[:quiet] - Bundler.settings.set_command_option_if_given :path, options[:path] Bundler.settings.set_command_option_if_given :cache_path, options["cache-path"] - setup_cache_all install - custom_path = Bundler.settings[:path] if options[:path] - Bundler.settings.temporary(cache_all_platforms: options["all-platforms"]) do - Bundler.load.cache(custom_path) + Bundler.load.cache end end @@ -32,11 +28,5 @@ module Bundler options["no-cache"] = true Bundler::CLI::Install.new(options).run end - - def setup_cache_all - all = options.fetch(:all, Bundler.feature_flag.cache_all? || nil) - - Bundler.settings.set_command_option_if_given :cache_all, all - end end end diff --git a/lib/bundler/cli/common.rb b/lib/bundler/cli/common.rb index 7608adf2ef..b44fbc3096 100644 --- a/lib/bundler/cli/common.rb +++ b/lib/bundler/cli/common.rb @@ -2,6 +2,12 @@ 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| @@ -94,11 +100,14 @@ module Bundler end def self.gem_not_found_message(missing_gem_name, alternatives) - require_relative "../similarity_detector" message = "Could not find gem '#{missing_gem_name}'." alternate_names = alternatives.map {|a| a.respond_to?(:name) ? a.name : a } - suggestions = SimilarityDetector.new(alternate_names).similar_word_list(missing_gem_name) - message += "\nDid you mean #{suggestions}?" if suggestions + 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 @@ -134,5 +143,19 @@ module Bundler 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 diff --git a/lib/bundler/cli/config.rb b/lib/bundler/cli/config.rb index d963679085..976cda7484 100644 --- a/lib/bundler/cli/config.rb +++ b/lib/bundler/cli/config.rb @@ -26,8 +26,7 @@ module Bundler end 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] has been removed. Use `bundle #{new_args.join(" ")}` instead." - SharedHelpers.major_deprecation 4, message, removed_message: removed_message + SharedHelpers.feature_deprecated! message Base.new(options, name, value, self).run end @@ -88,16 +87,21 @@ module Bundler if value.nil? warn_unused_scope "Ignoring --#{scope} since no value to set was given" + current_value = Bundler.settings[name] if options[:parseable] if value = Bundler.settings[name] Bundler.ui.info("#{name}=#{value}") end - return + else + confirm(name) end - confirm(name) - return + if current_value.nil? + exit 1 + else + return + end end Bundler.ui.info(message) if message diff --git a/lib/bundler/cli/console.rb b/lib/bundler/cli/console.rb index f6389e8ea0..2d1a2ce458 100644 --- a/lib/bundler/cli/console.rb +++ b/lib/bundler/cli/console.rb @@ -21,6 +21,11 @@ module Bundler get_constant(name) rescue LoadError if name == "irb" + if defined?(Gem::BUNDLED_GEMS) && Gem::BUNDLED_GEMS.respond_to?(:force_activate) + Gem::BUNDLED_GEMS.force_activate "irb" + require name + return get_constant(name) + end Bundler.ui.error "#{name} is not available" exit 1 else diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb index 9428e9db3b..2fdc416286 100644 --- a/lib/bundler/cli/exec.rb +++ b/lib/bundler/cli/exec.rb @@ -19,11 +19,13 @@ module Bundler validate_cmd! SharedHelpers.set_bundle_environment if bin_path = Bundler.which(cmd) - if !Bundler.settings[:disable_exec_load] && ruby_shebang?(bin_path) - return kernel_load(bin_path, *args) + if !Bundler.settings[:disable_exec_load] && directly_loadable?(bin_path) + bin_path.delete_suffix!(".bat") if Gem.win_platform? + kernel_load(bin_path, *args) + else + bin_path = "./" + bin_path unless File.absolute_path?(bin_path) + kernel_exec(bin_path, *args) end - bin_path = "./" + bin_path unless File.absolute_path?(bin_path) - kernel_exec(bin_path, *args) else # exec using the given command kernel_exec(cmd, *args) @@ -69,6 +71,29 @@ module Bundler "#{file} #{args.join(" ")}".strip end + def directly_loadable?(file) + if Gem.win_platform? + script_wrapper?(file) + else + ruby_shebang?(file) + end + end + + def script_wrapper?(file) + script_file = file.delete_suffix(".bat") + return false unless File.exist?(script_file) + + if File.zero?(script_file) + Bundler.ui.warn "#{script_file} is empty" + return false + end + + header = File.open(file, "r") {|f| f.read(32) } + ruby_exe = "#{RbConfig::CONFIG["RUBY_INSTALL_NAME"]}#{RbConfig::CONFIG["EXEEXT"]}" + ruby_exe = "ruby.exe" if ruby_exe.empty? + header.include?(ruby_exe) + end + def ruby_shebang?(file) possibilities = [ "#!/usr/bin/env ruby\n", diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb index 5b71d71c67..c8c24c8e66 100644 --- a/lib/bundler/cli/gem.rb +++ b/lib/bundler/cli/gem.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "pathname" - module Bundler class CLI Bundler.require_thor_actions @@ -9,11 +7,7 @@ module Bundler end class CLI::Gem - TEST_FRAMEWORK_VERSIONS = { - "rspec" => "3.0", - "minitest" => "5.16", - "test-unit" => "3.0", - }.freeze + DEFAULT_GITHUB_USERNAME = "[USERNAME]" attr_reader :options, :gem_name, :thor, :name, :target, :extension @@ -26,7 +20,7 @@ module Bundler thor.destination_root = nil @name = @gem_name - @target = SharedHelpers.pwd.join(gem_name) + @target = Pathname.new(SharedHelpers.pwd).join(gem_name) @extension = options[:ext] @@ -74,7 +68,7 @@ module Bundler bundle: options[:bundle], bundler_version: bundler_dependency_version, git: use_git, - github_username: github_username.empty? ? "[USERNAME]" : github_username, + github_username: github_username.empty? ? DEFAULT_GITHUB_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, @@ -117,7 +111,6 @@ module Bundler if test_framework = ask_and_set_test_framework config[:test] = test_framework - config[:test_framework_version] = TEST_FRAMEWORK_VERSIONS[test_framework] case test_framework when "rspec" @@ -158,6 +151,9 @@ module Bundler case config[:ci] when "github" templates.merge!("github/workflows/main.yml.tt" => ".github/workflows/main.yml") + if extension == "rust" + templates.merge!("github/workflows/build-gems.yml.tt" => ".github/workflows/build-gems.yml") + end config[:ignore_paths] << ".github/" when "gitlab" templates.merge!("gitlab-ci.yml.tt" => ".gitlab-ci.yml") @@ -178,12 +174,8 @@ module Bundler if ask_and_set(:coc, "Do you want to include a code of conduct in gems you generate?", "Codes of conduct can increase contributions to your project by contributors who " \ - "prefer collaborative, safe spaces. You can read more about the code of conduct at " \ - "contributor-covenant.org. Having a code of conduct means agreeing to the responsibility " \ - "of enforcing it, so be sure that you are prepared to do that. Be sure that your email " \ - "address is specified as a contact in the generated code of conduct so that people know " \ - "who to contact in case of a violation. For suggestions about " \ - "how to enforce codes of conduct, see https://bit.ly/coc-enforcement.") + "prefer safe, respectful, productive, and collaborative spaces. \n" \ + "See https://github.com/ruby/rubygems/blob/master/CODE_OF_CONDUCT.md") config[:coc] = true Bundler.ui.info "Code of conduct enabled in config" templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md") @@ -204,12 +196,10 @@ module Bundler config[:linter] = ask_and_set_linter case config[:linter] when "rubocop" - config[:linter_version] = rubocop_version Bundler.ui.info "RuboCop enabled in config" templates.merge!("rubocop.yml.tt" => ".rubocop.yml") config[:ignore_paths] << ".rubocop.yml" when "standard" - config[:linter_version] = standard_version Bundler.ui.info "Standard enabled in config" templates.merge!("standard.yml.tt" => ".standard.yml") config[:ignore_paths] << ".standard.yml" @@ -232,11 +222,24 @@ module Bundler templates.merge!( "Cargo.toml.tt" => "Cargo.toml", "ext/newgem/Cargo.toml.tt" => "ext/#{name}/Cargo.toml", + "ext/newgem/build.rs.tt" => "ext/#{name}/build.rs", "ext/newgem/extconf-rust.rb.tt" => "ext/#{name}/extconf.rb", "ext/newgem/src/lib.rs.tt" => "ext/#{name}/src/lib.rs", ) end + if extension == "go" + templates.merge!( + "ext/newgem/go.mod.tt" => "ext/#{name}/go.mod", + "ext/newgem/extconf-go.rb.tt" => "ext/#{name}/extconf.rb", + "ext/newgem/newgem.h.tt" => "ext/#{name}/#{underscored_name}.h", + "ext/newgem/newgem.go.tt" => "ext/#{name}/#{underscored_name}.go", + "ext/newgem/newgem-go.c.tt" => "ext/#{name}/#{underscored_name}.c", + ) + + config[:go_module_username] = config[:github_username] == DEFAULT_GITHUB_USERNAME ? "username" : config[:github_username] + 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] @@ -276,13 +279,13 @@ module Bundler open_editor(options["edit"], target.join("#{name}.gemspec")) if options[:edit] Bundler.ui.info "\nGem '#{name}' was successfully created. " \ - "For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html" + "For more information on making a RubyGem visit https://guides.rubygems.org/make-your-own-gem/" end private def resolve_name(name) - SharedHelpers.pwd.join(name).basename.to_s + Pathname.new(SharedHelpers.pwd).join(name).basename.to_s end def ask_and_set(key, prompt, explanation) @@ -382,7 +385,6 @@ module Bundler def ask_and_set_linter return if skip?(:linter) linter_template = options[:linter] || Bundler.settings["gem.linter"] - linter_template = deprecated_rubocop_option if linter_template.nil? if linter_template.to_s.empty? Bundler.ui.info "\nDo you want to add a code linter and formatter to your gem? " \ @@ -415,27 +417,6 @@ module Bundler linter_template end - def deprecated_rubocop_option - if !options[:rubocop].nil? - if options[: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", - 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", - 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 - def bundler_dependency_version v = Gem::Version.new(Bundler::VERSION) req = v.segments[0..1] @@ -449,6 +430,10 @@ module Bundler exit 1 end + if /[A-Z]/.match?(name) + Bundler.ui.warn "Gem names with capital letters are not recommended. Please use only lowercase letters, numbers, and hyphens." + end + constant_name = constant_array.join("::") existing_constant = constant_array.inject(Object) do |c, s| @@ -478,14 +463,6 @@ module Bundler "3.2.0" end - def rubocop_version - "1.21" - end - - def standard_version - "1.3" - end - def github_username(git_username) if options[:github_username].nil? git_username diff --git a/lib/bundler/cli/inject.rb b/lib/bundler/cli/inject.rb deleted file mode 100644 index a09d5c6bda..0000000000 --- a/lib/bundler/cli/inject.rb +++ /dev/null @@ -1,60 +0,0 @@ -# frozen_string_literal: true - -module Bundler - class CLI::Inject - attr_reader :options, :name, :version, :group, :source, :gems - def initialize(options, name, version) - @options = options - @name = name - @version = version || last_version_number - @group = options[:group].split(",") unless options[:group].nil? - @source = options[:source] - @gems = [] - end - - def run - # The required arguments allow Thor to give useful feedback when the arguments - # are incorrect. This adds those first two arguments onto the list as a whole. - gems.unshift(source).unshift(group).unshift(version).unshift(name) - - # Build an array of Dependency objects out of the arguments - deps = [] - # when `inject` support addition of more than one gem, then this loop will - # help. Currently this loop is running once. - gems.each_slice(4) do |gem_name, gem_version, gem_group, gem_source| - ops = Gem::Requirement::OPS.map {|key, _val| key } - has_op = ops.any? {|op| gem_version.start_with? op } - gem_version = "~> #{gem_version}" unless has_op - deps << Bundler::Dependency.new(gem_name, gem_version, "group" => gem_group, "source" => gem_source) - end - - added = Injector.inject(deps, options) - - if added.any? - Bundler.ui.confirm "Added to Gemfile:" - Bundler.ui.confirm(added.map do |d| - name = "'#{d.name}'" - requirement = ", '#{d.requirement}'" - group = ", group: #{d.groups.inspect}" if d.groups != Array(:default) - source = ", source: '#{d.source}'" unless d.source.nil? - %(gem #{name}#{requirement}#{group}#{source}) - end.join("\n")) - else - Bundler.ui.confirm "All gems were already present in the Gemfile" - end - end - - private - - def last_version_number - definition = Bundler.definition(true) - definition.remotely! - specs = definition.index[name].sort_by(&:version) - unless options[:pre] - specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? } - end - spec = specs.last - spec.version.to_s - end - end -end diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb index 074afd64eb..69affd1a10 100644 --- a/lib/bundler/cli/install.rb +++ b/lib/bundler/cli/install.rb @@ -20,56 +20,32 @@ module Bundler Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Gem.freebsd_platform? - # Disable color in deployment mode - Bundler.ui.shell = Thor::Shell::Basic.new if options[:deployment] - if target_rbconfig_path = options[:"target-rbconfig"] Bundler.rubygems.set_target_rbconfig(target_rbconfig_path) end - check_for_options_conflicts - check_trust_policy - if options[:deployment] || options[:frozen] || Bundler.frozen_bundle? - unless Bundler.default_lockfile.exist? - flag = "--deployment flag" if options[:deployment] - flag ||= "--frozen flag" if options[:frozen] - flag ||= "deployment setting" if Bundler.settings[:deployment] - flag ||= "frozen setting" if Bundler.settings[:frozen] - raise ProductionError, "The #{flag} requires a lockfile. Please make " \ - "sure you have checked your #{SharedHelpers.relative_lockfile_path} into version control " \ - "before deploying." - end - - options[:local] = true if Bundler.app_cache.exist? - - Bundler.settings.set_command_option :deployment, true if options[:deployment] - Bundler.settings.set_command_option :frozen, true if options[:frozen] - end - - # When install is called with --no-deployment, disable deployment mode - if options[:deployment] == false - Bundler.settings.set_command_option :frozen, nil - options[:system] = true + if Bundler.frozen_bundle? && !Bundler.default_lockfile.exist? + flag = "deployment setting" if Bundler.settings[:deployment] + flag = "frozen setting" if Bundler.settings[:frozen] + raise ProductionError, "The #{flag} requires a lockfile. Please make " \ + "sure you have checked your #{SharedHelpers.relative_lockfile_path} into version control " \ + "before deploying." end normalize_settings Bundler::Fetcher.disable_endpoint = options["full-index"] - if options["binstubs"] - Bundler::SharedHelpers.major_deprecation 2, - "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? + Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.settings[:plugins] # For install we want to enable strict validation # (rather than some optimizations we perform at app runtime). definition = Bundler.definition(strict: true) definition.validate_runtime! + definition.lockfile = options["lockfile"] if options["lockfile"] + definition.lockfile = false if options["no-lock"] installer = Installer.install(Bundler.root, definition, options) @@ -89,8 +65,6 @@ module Bundler Bundler::CLI::Common.output_post_install_messages installer.post_install_messages - warn_ambiguous_gems - if CLI::Common.clean_after_install? require_relative "clean" Bundler::CLI::Clean.new(options).run @@ -116,26 +90,10 @@ module Bundler end def gems_installed_for(definition) - count = definition.specs.count + count = definition.specs.count {|spec| spec.name != "bundler" } "#{count} #{count == 1 ? "gem" : "gems"} now installed" end - def check_for_group_conflicts_in_cli_options - conflicting_groups = Array(options[:without]) & Array(options[:with]) - return if conflicting_groups.empty? - raise InvalidOption, "You can't list a group in both with and without." \ - " The offending groups are: #{conflicting_groups.join(", ")}." - end - - def check_for_options_conflicts - if (options[:path] || options[:deployment]) && options[:system] - error_message = String.new - error_message << "You have specified both --path as well as --system. Please choose only one option.\n" if options[:path] - error_message << "You have specified both --deployment as well as --system. Please choose only one option.\n" if options[:deployment] - raise InvalidOption.new(error_message) - end - end - def check_trust_policy trust_policy = options["trust-policy"] unless Bundler.rubygems.security_policies.keys.unshift(nil).include?(trust_policy) @@ -145,55 +103,25 @@ module Bundler Bundler.settings.set_command_option_if_given :"trust-policy", trust_policy end - def normalize_groups - check_for_group_conflicts_in_cli_options - - # 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] - if options["standalone"] && Bundler.settings[:path].nil? && !options["local"] Bundler.settings.set_command_option :path, "bundle" end - bin_option = options["binstubs"] - 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"] Bundler.settings.set_command_option_if_given :jobs, options["jobs"] + Bundler::CLI::Common.validate_cooldown!(options["cooldown"]) + Bundler.settings.set_command_option_if_given :cooldown, options["cooldown"] + Bundler.settings.set_command_option_if_given :no_prune, options["no-prune"] Bundler.settings.set_command_option_if_given :no_install, options["no-install"] Bundler.settings.set_command_option_if_given :clean, options["clean"] - normalize_groups if options[:without] || options[:with] - options[:force] = options[:redownload] if options[:redownload] end - - def warn_ambiguous_gems - # TODO: remove this when we drop Bundler 1.x support - Installer.ambiguous_gems.to_a.each do |name, installed_from_uri, *also_found_in_uris| - Bundler.ui.warn "Warning: the gem '#{name}' was found in multiple sources." - Bundler.ui.warn "Installed from: #{installed_from_uri}" - Bundler.ui.warn "Also found in:" - also_found_in_uris.each {|uri| Bundler.ui.warn " * #{uri}" } - Bundler.ui.warn "You should add a source requirement to restrict this gem to your preferred source." - Bundler.ui.warn "For example:" - Bundler.ui.warn " gem '#{name}', :source => '#{installed_from_uri}'" - Bundler.ui.warn "Then uninstall the gem '#{name}' (or delete all bundled gems) and then install again." - end - end end end diff --git a/lib/bundler/cli/issue.rb b/lib/bundler/cli/issue.rb index fbe9184d12..cbfb7da2d8 100644 --- a/lib/bundler/cli/issue.rb +++ b/lib/bundler/cli/issue.rb @@ -10,7 +10,7 @@ module Bundler be sure to check out these resources: 1. Check out our troubleshooting guide for quick fixes to common issues: - https://github.com/rubygems/rubygems/blob/master/doc/bundler/TROUBLESHOOTING.md + https://github.com/ruby/rubygems/blob/master/doc/bundler/TROUBLESHOOTING.md 2. Instructions for common Bundler uses can be found on the documentation site: https://bundler.io/ @@ -22,7 +22,7 @@ module Bundler still aren't working the way you expect them to, please let us know so that we can diagnose and help fix the problem you're having, by filling in the new issue form located at - https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md, + https://github.com/ruby/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md, and copy and pasting the information below. EOS diff --git a/lib/bundler/cli/lock.rb b/lib/bundler/cli/lock.rb index b60c82e3a1..2f78868936 100644 --- a/lib/bundler/cli/lock.rb +++ b/lib/bundler/cli/lock.rb @@ -35,11 +35,8 @@ module Bundler update = { bundler: bundler } end - file = options[:lockfile] - file = file ? Pathname.new(file).expand_path : Bundler.default_lockfile - Bundler.settings.temporary(frozen: false) do - definition = Bundler.definition(update, file) + definition = Bundler.definition(update, Bundler.default_lockfile) definition.add_checksums if options["add-checksums"] Bundler::CLI::Common.configure_gem_version_promoter(definition, options) if options[:update] @@ -71,8 +68,11 @@ module Bundler if print puts definition.to_lock else + file = options[:lockfile] + file = file ? Pathname.new(file).expand_path : Bundler.default_lockfile + puts "Writing lockfile to #{file}" - definition.lock + definition.write_lock(file, false) end end diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb index 0c8ba3ebf7..465e56ada2 100644 --- a/lib/bundler/cli/outdated.rb +++ b/lib/bundler/cli/outdated.rb @@ -26,6 +26,9 @@ module Bundler def run check_for_deployment_mode! + Bundler::CLI::Common.validate_cooldown!(options[:cooldown]) + Bundler.settings.set_command_option_if_given :cooldown, options[:cooldown] + Bundler.definition.validate_runtime! current_specs = Bundler.ui.silence { Bundler.definition.resolve } @@ -199,7 +202,15 @@ module Bundler end spec_outdated_info = "#{active_spec.name} (newest #{spec_version}, " \ - "installed #{current_version}#{dependency_version})" + "installed #{current_version}#{dependency_version}" + + release_date = release_date_for(active_spec) + spec_outdated_info += ", released #{release_date}" unless release_date.empty? + + remaining = cooldown_days_remaining(active_spec) + spec_outdated_info += ", in cooldown for #{remaining} more day#{"s" if remaining > 1}" if remaining + + spec_outdated_info += ")" output_message = if options[:parseable] spec_outdated_info.to_s @@ -215,13 +226,25 @@ module Bundler def gem_column_for(current_spec, active_spec, dependency, groups) current_version = "#{current_spec.version}#{current_spec.git_version}" spec_version = "#{active_spec.version}#{active_spec.git_version}" + remaining = cooldown_days_remaining(active_spec) + spec_version += " (cooldown #{remaining}d)" if remaining dependency = dependency.requirement if dependency ret_val = [active_spec.name, current_version, spec_version, dependency.to_s, groups.to_s] + ret_val << release_date_for(active_spec) ret_val << loaded_from_for(active_spec).to_s if Bundler.ui.debug? ret_val end + def cooldown_days_remaining(spec, now = Time.now) + return nil unless spec.respond_to?(:created_at) && spec.created_at + return nil unless spec.respond_to?(:remote) && spec.remote + days = spec.remote.effective_cooldown + return nil if days.nil? || days <= 0 + remaining = days - ((now - spec.created_at) / 86_400.0) + remaining > 0 ? remaining.ceil : nil + end + def check_for_deployment_mode! return unless Bundler.frozen_bundle? suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any? @@ -283,11 +306,28 @@ module Bundler end def table_header - header = ["Gem", "Current", "Latest", "Requested", "Groups"] + header = ["Gem", "Current", "Latest", "Requested", "Groups", "Release Date"] header << "Path" if Bundler.ui.debug? header end + def release_date_for(spec) + return "" unless spec.respond_to?(:date) + + date = spec.date + return "" unless date + + return "" unless Gem.const_defined?(:DEFAULT_SOURCE_DATE_EPOCH) + default_date = Time.at(Gem::DEFAULT_SOURCE_DATE_EPOCH).utc + default_date = Time.utc(default_date.year, default_date.month, default_date.day) + + date = date.utc if date.respond_to?(:utc) + + return "" if date == default_date + + date.strftime("%Y-%m-%d") + end + def justify(row, sizes) row.each_with_index.map do |element, index| element.ljust(sizes[index]) diff --git a/lib/bundler/cli/plugin.rb b/lib/bundler/cli/plugin.rb index fd61ef0d95..32fa660fe0 100644 --- a/lib/bundler/cli/plugin.rb +++ b/lib/bundler/cli/plugin.rb @@ -10,11 +10,15 @@ module Bundler 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 "local_git", type: :string, default: nil, banner: "Path of the local git repo to fetch from (removed)" 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) + if options.key?(:local_git) + raise InvalidOption, "--local_git has been removed, use --git" + end + Bundler::Plugin.install(plugins, options) end diff --git a/lib/bundler/cli/pristine.rb b/lib/bundler/cli/pristine.rb index cfd4a995a3..f463f0bce8 100644 --- a/lib/bundler/cli/pristine.rb +++ b/lib/bundler/cli/pristine.rb @@ -11,6 +11,7 @@ module Bundler definition = Bundler.definition definition.validate_runtime! installer = Bundler::Installer.new(Bundler.root, definition) + git_sources = [] ProcessLock.lock do installed_specs = definition.specs.reject do |spec| @@ -41,6 +42,9 @@ module Bundler end FileUtils.rm_rf spec.extension_dir FileUtils.rm_rf spec.full_gem_path + + next if git_sources.include?(source) + git_sources << source else Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.") next @@ -49,7 +53,7 @@ module Bundler true end.map(&:name) - jobs = installer.send(:installation_parallelization) + jobs = Bundler.settings.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 diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb index b55eb7bad5..67fdcc797e 100644 --- a/lib/bundler/cli/show.rb +++ b/lib/bundler/cli/show.rb @@ -6,7 +6,7 @@ module Bundler def initialize(options, gem_name) @options = options @gem_name = gem_name - @verbose = options[:verbose] || options[:outdated] + @verbose = options[:verbose] @latest_specs = fetch_latest_specs if @verbose end diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb index 13f576cfa7..d92ffd995f 100644 --- a/lib/bundler/cli/update.rb +++ b/lib/bundler/cli/update.rb @@ -15,7 +15,7 @@ module Bundler Bundler.self_manager.update_bundler_and_restart_with_it_if_needed(update_bundler) if update_bundler - Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins? + Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.settings[:plugins] sources = Array(options[:source]) groups = Array(options[:group]).map(&:to_sym) @@ -23,10 +23,10 @@ module Bundler full_update = gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !update_bundler if full_update && !options[:all] - if Bundler.feature_flag.update_requires_all_flag? + if Bundler.settings[:update_requires_all_flag] raise InvalidOption, "To update everything, pass the `--all` flag." end - SharedHelpers.major_deprecation 4, "Pass --all to `bundle update` to update everything" + SharedHelpers.feature_deprecated! "Pass --all to `bundle update` to update everything" elsif !full_update && options[:all] raise InvalidOption, "Cannot specify --all along with specific options." end @@ -66,6 +66,8 @@ module Bundler opts["force"] = options[:redownload] if options[:redownload] Bundler.settings.set_command_option_if_given :jobs, opts["jobs"] + Bundler::CLI::Common.validate_cooldown!(options[:cooldown]) + Bundler.settings.set_command_option_if_given :cooldown, options[:cooldown] Bundler.definition.validate_runtime! diff --git a/lib/bundler/cli/viz.rb b/lib/bundler/cli/viz.rb deleted file mode 100644 index 5c09e00995..0000000000 --- a/lib/bundler/cli/viz.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -module Bundler - class CLI::Viz - attr_reader :options, :gem_name - def initialize(options) - @options = options - end - - def run - # make sure we get the right `graphviz`. There is also a `graphviz` - # gem we're not built to support - gem "ruby-graphviz" - require "graphviz" - - options[:without] = options[:without].join(":").tr(" ", ":").split(":") - output_file = File.expand_path(options[:file]) - - graph = Graph.new(Bundler.load, output_file, options[:version], options[:requirements], options[:format], options[:without]) - graph.viz - rescue LoadError => e - Bundler.ui.error e.inspect - 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.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 - end -end |
