# frozen_string_literal: truerequire'rubygems/dependency'require'rubygems/exceptions'require'rubygems/util'require'rubygems/util/list'require'uri'require'net/http'### Given a set of Gem::Dependency objects as +needed+ and a way to query the# set of available specs via +set+, calculates a set of ActivationRequest# objects which indicate all the specs that should be activated to meet the# all the requirements.classGem::Resolverrequire'rubygems/resolver/molinillo'### If the DEBUG_RESOLVER environment variable is set then debugging mode is# enabled for the resolver. This will display information about the state# of the resolver while a set of dependencies is being resolved.DEBUG_RESOLVER=!ENV['DEBUG_RESOLVER'].nil?### Set to true if all development dependencies should be considered.attr_accessor:development### Set to true if immediate development dependencies should be considered.attr_accessor:development_shallow### When true, no dependencies are looked up for requested gems.attr_accessor:ignore_dependencies### List of dependencies that could not be found in the configured sources.attr_reader:missingattr_reader:stats### Hash of gems to skip resolution. Keyed by gem name, with arrays of# gem specifications as values.attr_accessor:skip_gems### When a missing dependency, don't stop. Just go on and record what was# missing.attr_accessor:soft_missing### Combines +sets+ into a ComposedSet that allows specification lookup in a# uniform manner. If one of the +sets+ is itself a ComposedSet its sets are# flattened into the result ComposedSet.defself.compose_sets*setssets.compact!sets=sets.mapdo|set|casesetwhenGem::Resolver::BestSetthensetwhenGem::Resolver::ComposedSetthenset.setselsesetendend.flattencasesets.lengthwhen0thenraiseArgumentError,'one set in the composition must be non-nil'when1thensets.firstelseGem::Resolver::ComposedSet.new(*sets)endend### Creates a Resolver that queries only against the already installed gems# for the +needed+ dependencies.defself.for_current_gemsneedednewneeded,Gem::Resolver::CurrentSet.newend### Create Resolver object which will resolve the tree starting# with +needed+ Dependency objects.## +set+ is an object that provides where to look for specifications to# satisfy the Dependencies. This defaults to IndexSet, which will query# rubygems.org.definitializeneeded,set=nil@set=set||Gem::Resolver::IndexSet.new@needed=needed@development=false@development_shallow=false@ignore_dependencies=false@missing=[]@skip_gems={}@soft_missing=false@stats=Gem::Resolver::Stats.newenddefexplainstage,*data# :nodoc:returnunlessDEBUG_RESOLVERd=data.map{|x|x.pretty_inspect}.join(", ")$stderr.printf"%10s %s\n",stage.to_s.upcase,denddefexplain_liststage# :nodoc:returnunlessDEBUG_RESOLVERdata=yield$stderr.printf"%10s (%d entries)\n",stage.to_s.upcase,data.sizePP.ppdata,$stderrunlessdata.empty?end### Creates an ActivationRequest for the given +dep+ and the last +possible+# specification.## Returns the Specification and the ActivationRequestdefactivation_requestdep,possible# :nodoc:spec=possible.popexplain:activate,[spec.full_name,possible.size]explain:possible,possibleactivation_request=Gem::Resolver::ActivationRequest.newspec,dep,possiblereturnspec,activation_requestenddefrequestss,act,reqs=[]# :nodoc:returnreqsif@ignore_dependenciess.fetch_development_dependenciesif@developments.dependencies.reverse_eachdo|d|nextifd.type==:developmentandnot@developmentnextifd.type==:developmentand@development_shallowandact.development?nextifd.type==:developmentand@development_shallowandact.parentreqs<<Gem::Resolver::DependencyRequest.new(d,act)@stats.requirement!end@set.prefetchreqs@stats.record_requirementsreqsreqsendincludeMolinillo::UIdefoutput@output||=debug??$stdout:File.open(Gem::Util::NULL_DEVICE,'w')enddefdebug?DEBUG_RESOLVERendincludeMolinillo::SpecificationProvider### Proceed with resolution! Returns an array of ActivationRequest objects.defresolvelocking_dg=Molinillo::DependencyGraph.newMolinillo::Resolver.new(self,self).resolve(@needed.map{|d|DependencyRequest.newd,nil},locking_dg).tsort.map(&:payload).compactrescueMolinillo::VersionConflict=>econflict=e.conflicts.values.firstraiseGem::DependencyResolutionError,Conflict.new(conflict.requirement_trees.first.first,conflict.existing,conflict.requirement)ensure@output.closeifdefined?(@output)and!debug?end### Extracts the specifications that may be able to fulfill +dependency+ and# returns those that match the local platform and all those that match.deffind_possibledependency# :nodoc:all=@set.find_alldependencyif(skip_dep_gems=skip_gems[dependency.name])&&!skip_dep_gems.empty?matching=all.selectdo|api_spec|skip_dep_gems.any?{|s|api_spec.version==s.version}endall=matchingunlessmatching.empty?endmatching_platform=select_local_platformsallreturnmatching_platform,allend### Returns the gems in +specs+ that match the local platform.defselect_local_platformsspecs# :nodoc:specs.selectdo|spec|Gem::Platform.installable?specendenddefsearch_for(dependency)possibles,all=find_possible(dependency)if!@soft_missing&&possibles.empty?@missing<<dependencyexc=Gem::UnsatisfiableDependencyError.newdependency,allexc.errors=@set.errorsraiseexcendpossibles.sort_by{|s|[s.source,s.version,Gem::Platform.local=~s.platform?1:0]}.map{|s|ActivationRequest.news,dependency,[]}enddefdependencies_for(specification)return[]if@ignore_dependenciesspec=specification.specrequests(spec,specification)enddefrequirement_satisfied_by?(requirement,activated,spec)requirement.matches_spec?specenddefname_for(dependency)dependency.nameenddefallow_missing?(dependency)@missing<<dependency@soft_missingendend### TODO remove in RubyGems 3Gem::DependencyResolver=Gem::Resolver# :nodoc:require'rubygems/resolver/activation_request'require'rubygems/resolver/conflict'require'rubygems/resolver/dependency_request'require'rubygems/resolver/requirement_list'require'rubygems/resolver/stats'require'rubygems/resolver/set'require'rubygems/resolver/api_set'require'rubygems/resolver/composed_set'require'rubygems/resolver/best_set'require'rubygems/resolver/current_set'require'rubygems/resolver/git_set'require'rubygems/resolver/index_set'require'rubygems/resolver/installer_set'require'rubygems/resolver/lock_set'require'rubygems/resolver/vendor_set'require'rubygems/resolver/source_set'require'rubygems/resolver/specification'require'rubygems/resolver/spec_specification'require'rubygems/resolver/api_specification'require'rubygems/resolver/git_specification'require'rubygems/resolver/index_specification'require'rubygems/resolver/installed_specification'require'rubygems/resolver/local_specification'require'rubygems/resolver/lock_specification'require'rubygems/resolver/vendor_specification'