# frozen_string_literal: truerequire"bundler/cli/common"moduleBundlerclassCLI::Outdatedattr_reader:options,:gemsdefinitialize(options,gems)@options=options@gems=gemsenddefruncheck_for_deployment_modesources=Array(options[:source])gems.eachdo|gem_name|Bundler::CLI::Common.select_spec(gem_name)endBundler.definition.validate_runtime!current_specs=Bundler.ui.silence{Bundler.definition.resolve}current_dependencies={}Bundler.ui.silencedoBundler.load.dependencies.eachdo|dep|current_dependencies[dep.name]=dependenddefinition=ifgems.empty?&&sources.empty?# We're doing a full updateBundler.definition(true)elseBundler.definition(:gems=>gems,:sources=>sources)endBundler::CLI::Common.configure_gem_version_promoter(Bundler.definition,options)# the patch level options imply strict is also true. It wouldn't make# sense otherwise.strict=options[:strict]||Bundler::CLI::Common.patch_level_options(options).any?filter_options_patch=options.keys&%w(filter-major filter-minor filter-patch)definition_resolution=procdooptions[:local]?definition.resolve_with_cache!:definition.resolve_remotely!endifoptions[:parseable]Bundler.ui.silence(&definition_resolution)elsedefinition_resolution.callendBundler.ui.info""outdated_gems_by_groups={}outdated_gems_list=[]# Loop through the current specsgemfile_specs,dependency_specs=current_specs.partitiondo|spec|current_dependencies.key?spec.nameend(gemfile_specs+dependency_specs).sort_by(&:name).eachdo|current_spec|nextif!gems.empty?&&!gems.include?(current_spec.name)dependency=current_dependencies[current_spec.name]active_spec=retrieve_active_spec(strict,definition,current_spec)nextifactive_spec.nil?iffilter_options_patch.any?update_present=update_present_via_semver_portions(current_spec,active_spec,options)nextunlessupdate_presentendgem_outdated=Gem::Version.new(active_spec.version)>Gem::Version.new(current_spec.version)nextunlessgem_outdated||(current_spec.git_version!=active_spec.git_version)groups=nilifdependency&&!options[:parseable]groups=dependency.groups.join(", ")endoutdated_gems_list<<{:active_spec=>active_spec,:current_spec=>current_spec,:dependency=>dependency,:groups=>groups}outdated_gems_by_groups[groups]||=[]outdated_gems_by_groups[groups]<<{:active_spec=>active_spec,:current_spec=>current_spec,:dependency=>dependency,:groups=>groups}endifoutdated_gems_list.empty?display_nothing_outdated_message(filter_options_patch)elseunlessoptions[:parseable]ifoptions[:pre]Bundler.ui.info"Outdated gems included in the bundle (including "\"pre-releases):"elseBundler.ui.info"Outdated gems included in the bundle:"endendoptions_include_groups=[:group,:groups].selectdo|v|options.keys.include?(v.to_s)endifoptions_include_groups.any?ordered_groups=outdated_gems_by_groups.keys.compact.sort[nil,ordered_groups].flatten.eachdo|groups|gems=outdated_gems_by_groups[groups]contains_group=ifgroupsgroups.split(",").include?(options[:group])elseoptions[:group]=="group"endnextif(!options[:groups]&&!contains_group)||gems.nil?unlessoptions[:parseable]ifgroupsBundler.ui.info"===== Group #{groups} ====="elseBundler.ui.info"===== Without group ====="endendgems.eachdo|gem|print_gem(gem[:current_spec],gem[:active_spec],gem[:dependency],groups,options_include_groups.any?)endendelseoutdated_gems_list.eachdo|gem|print_gem(gem[:current_spec],gem[:active_spec],gem[:dependency],gem[:groups],options_include_groups.any?)endendexit1endendprivatedefretrieve_active_spec(strict,definition,current_spec)ifstrictactive_spec=definition.find_resolved_spec(current_spec)elseactive_specs=definition.find_indexed_specs(current_spec)if!current_spec.version.prerelease?&&!options[:pre]&&active_specs.size>1active_specs.delete_if{|b|b.respond_to?(:version)&&b.version.prerelease?}endactive_spec=active_specs.lastendactive_specenddefdisplay_nothing_outdated_message(filter_options_patch)unlessoptions[:parseable]iffilter_options_patch.any?display=filter_options_patch.mapdo|o|o.sub("filter-","")end.join(" or ")Bundler.ui.info"No #{display} updates to display.\n"elseBundler.ui.info"Bundle up to date!\n"endendenddefprint_gem(current_spec,active_spec,dependency,groups,options_include_groups)spec_version="#{active_spec.version}#{active_spec.git_version}"spec_version+=" (from #{active_spec.loaded_from})"ifBundler.ui.debug?&&active_spec.loaded_fromcurrent_version="#{current_spec.version}#{current_spec.git_version}"ifdependency&&dependency.specific?dependency_version=%(, requested #{dependency.requirement})endspec_outdated_info="#{active_spec.name} (newest #{spec_version}, "\"installed #{current_version}#{dependency_version})"output_message=ifoptions[:parseable]spec_outdated_info.to_selsifoptions_include_groups||!groups" * #{spec_outdated_info}"else" * #{spec_outdated_info} in groups \"#{groups}\""endBundler.ui.infooutput_message.rstripenddefcheck_for_deployment_modeifBundler.settings[:frozen]raiseProductionError,"You are trying to check outdated gems in "\"deployment mode. Run `bundle outdated` elsewhere.\n"\"\nIf this is a development machine, remove the "\"#{Bundler.default_gemfile} freeze"\"\nby running `bundle install --no-deployment`."endenddefupdate_present_via_semver_portions(current_spec,active_spec,options)current_major=current_spec.version.segments.firstactive_major=active_spec.version.segments.firstupdate_present=falseupdate_present=active_major>current_majorifoptions["filter-major"]if!update_present&&(options["filter-minor"]||options["filter-patch"])&¤t_major==active_majorcurrent_minor=get_version_semver_portion_value(current_spec,1)active_minor=get_version_semver_portion_value(active_spec,1)update_present=active_minor>current_minorifoptions["filter-minor"]if!update_present&&options["filter-patch"]&¤t_minor==active_minorcurrent_patch=get_version_semver_portion_value(current_spec,2)active_patch=get_version_semver_portion_value(active_spec,2)update_present=active_patch>current_patchendendupdate_presentenddefget_version_semver_portion_value(spec,version_portion_index)version_section=spec.version.segments[version_portion_index,1]version_section.nil??0:(version_section.first||0)endendend