# frozen_string_literal: truemoduleBundlerclassCLI::Outdatedattr_reader:options,:gems,:options_include_groups,:filter_options_patch,:sources,:strictattr_accessor:outdated_gems_by_groups,:outdated_gems_listdefinitialize(options,gems)@options=options@gems=gems@sources=Array(options[:source])@filter_options_patch=options.keys&%w[filter-major filter-minor filter-patch]@outdated_gems_by_groups={}@outdated_gems_list=[]@options_include_groups=[:group,:groups].any?do|v|options.keys.include?(v.to_s)end# the patch level options imply strict is also true. It wouldn't make# sense otherwise.@strict=options["filter-strict"]||Bundler::CLI::Common.patch_level_options(options).any?enddefruncheck_for_deployment_mode!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.map{|dep|[dep.name,dep]}.to_henddefinition=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)definition_resolution=procdooptions[:local]?definition.resolve_with_cache!:definition.resolve_remotely!endifoptions[:parseable]Bundler.ui.silence(&definition_resolution)elsedefinition_resolution.callendBundler.ui.info""# Loop through the current specsgemfile_specs,dependency_specs=current_specs.partitiondo|spec|current_dependencies.key?spec.nameendspecs=ifoptions["only-explicit"]gemfile_specselsegemfile_specs+dependency_specsendspecs.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(definition,current_spec)nextifactive_spec.nil?nextiffilter_options_patch.any?&&!update_present_via_semver_portions(current_spec,active_spec,options)gem_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]<<outdated_gems_list[-1]endifoutdated_gems_list.empty?display_nothing_outdated_messageelseunlessoptions[:parseable]Bundler.ui.info(header_outdated_message)endifoptions_include_groupsordered_groups=outdated_gems_by_groups.keys.compact.sortordered_groups.insert(0,nil).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]Bundler.ui.info(header_group_message(groups))endprint_gems(gems)endelseprint_gems(outdated_gems_list)endexit1endendprivatedefgroups_text(group_text,groups)"#{group_text}#{groups.split(",").size>1?"s":""}\"#{groups}\""enddefheader_outdated_messageifoptions[:pre]"Outdated gems included in the bundle (including pre-releases):"else"Outdated gems included in the bundle:"endenddefheader_group_message(groups)ifgroups"===== #{groups_text("Group",groups)} ====="else"===== Without group ====="endenddefnothing_outdated_messageiffilter_options_patch.any?display=filter_options_patch.mapdo|o|o.sub("filter-","")end.join(" or ")"No #{display} updates to display.\n"else"Bundle up to date!\n"endenddefretrieve_active_spec(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_messageunlessoptions[:parseable]Bundler.ui.info(nothing_outdated_message)endenddefprint_gems(gems_list)gems_list.eachdo|gem|print_gem(gem[:current_spec],gem[:active_spec],gem[:dependency],gem[:groups],)endenddefprint_gem(current_spec,active_spec,dependency,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_text("group",groups)}"endBundler.ui.infooutput_message.rstripenddefcheck_for_deployment_mode!returnunlessBundler.frozen_bundle?suggested_command=ifBundler.settings.locations("frozen")[:global]"bundle config unset frozen"elsifBundler.settings.locations("deployment").keys.&([:global,:local]).any?"bundle config unset deployment"else"bundle install --no-deployment"endraiseProductionError,"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 `#{suggested_command}`."enddefupdate_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.to_a[0].to_iendendend