# frozen_string_literal: true### The Dependency class holds a Gem name and a Gem::Requirement.classGem::Dependency### Valid dependency types.#--# When this list is updated, be sure to change# Gem::Specification::CURRENT_SPECIFICATION_VERSION as well.## REFACTOR: This type of constant, TYPES, indicates we might want# two classes, used via inheritance or duck typing.TYPES=[:development,:runtime,].freeze### Dependency name or regular expression.attr_accessor:name### Allows you to force this dependency to be a prerelease.attr_writer:prerelease### Constructs a dependency with +name+ and +requirements+. The last# argument can optionally be the dependency type, which defaults to# <tt>:runtime</tt>.definitialize(name,*requirements)casenamewhenStringthen# okwhenRegexpthenmsg=["NOTE: Dependency.new w/ a regexp is deprecated.","Dependency.new called from #{Gem.location_of_caller.join(":")}"]warnmsg.join("\n")unlessGem::Deprecate.skipelseraiseArgumentError,"dependency name must be a String, was #{name.inspect}"endtype=Symbol===requirements.last?requirements.pop::runtimerequirements=requirements.firstifrequirements.length==1# unpackunlessTYPES.include?typeraiseArgumentError,"Valid types are #{TYPES.inspect}, "\"not #{type.inspect}"end@name=name@requirement=Gem::Requirement.createrequirements@type=type@prerelease=false# This is for Marshal backwards compatibility. See the comments in# +requirement+ for the dirty details.@version_requirements=@requirementend### A dependency's hash is the XOR of the hashes of +name+, +type+,# and +requirement+.defhash# :nodoc:name.hash^type.hash^requirement.hashenddefinspect# :nodoc:ifprerelease?format("<%s type=%p name=%p requirements=%p prerelease=ok>",self.class,type,name,requirement.to_s)elseformat("<%s type=%p name=%p requirements=%p>",self.class,type,name,requirement.to_s)endend### Does this dependency require a prerelease?defprerelease?@prerelease||requirement.prerelease?end### Is this dependency simply asking for the latest version# of a gem?deflatest_version?@requirement.none?enddefpretty_print(q)# :nodoc:q.group1,"Gem::Dependency.new(",")"doq.ppnameq.text","q.breakableq.pprequirementq.text","q.breakableq.pptypeendend### What does this dependency require?defrequirementreturn@requirementifdefined?(@requirement)&&@requirement# @version_requirements and @version_requirement are legacy ivar# names, and supported here because older gems need to keep# working and Dependency doesn't implement marshal_dump and# marshal_load. In a happier world, this would be an# attr_accessor. The horrifying instance_variable_get you see# below is also the legacy of some old restructurings.## Note also that because of backwards compatibility (loading new# gems in an old RubyGems installation), we can't add explicit# marshaling to this class until we want to make a big# break. Maybe 2.0.## Children, define explicit marshal and unmarshal behavior for# public classes. Marshal formats are part of your public API.# REFACTOR: See aboveifdefined?(@version_requirement)&&@version_requirementversion=@version_requirement.instance_variable_get:@version@version_requirement=nil@version_requirements=Gem::Requirement.newversionend@requirement=@version_requirementsifdefined?(@version_requirements)enddefrequirements_listrequirement.as_listenddefto_s# :nodoc:iftype!=:runtime"#{name} (#{requirement}, #{type})"else"#{name} (#{requirement})"endend### Dependency type.deftype@type||=:runtimeenddefruntime?@type==:runtime||!@typeenddef==(other)# :nodoc:Gem::Dependency===other&&name==other.name&&type==other.type&&requirement==other.requirementend### Dependencies are ordered by name.def<=>(other)name<=>other.nameend### Uses this dependency as a pattern to compare to +other+. This# dependency will match if the name matches the other's name, and# other has only an equal version requirement that satisfies this# dependency.def=~(other)unlessGem::Dependency===otherreturnunlessother.respond_to?(:name)&&other.respond_to?(:version)other=Gem::Dependency.newother.name,other.versionendreturnfalseunlessname===other.namereqs=other.requirement.requirementsreturnfalseunlessreqs.length==1returnfalseunlessreqs.first.first=="="version=reqs.first.lastrequirement.satisfied_by?versionendalias_method:===,:=~### :call-seq:# dep.match? name => true or false# dep.match? name, version => true or false# dep.match? spec => true or false## Does this dependency match the specification described by +name+ and# +version+ or match +spec+?## NOTE: Unlike #matches_spec? this method does not return true when the# version is a prerelease version unless this is a prerelease dependency.defmatch?(obj,version=nil,allow_prerelease=false)if!versionname=obj.nameversion=obj.versionelsename=objendreturnfalseunlessself.name===nameversion=Gem::Version.newversionreturntrueifrequirement.none?&&!version.prerelease?returnfalseifversion.prerelease?&&!allow_prerelease&&!prerelease?requirement.satisfied_by?versionend### Does this dependency match +spec+?## NOTE: This is not a convenience method. Unlike #match? this method# returns true when +spec+ is a prerelease version even if this dependency# is not a prerelease dependency.defmatches_spec?(spec)returnfalseunlessname===spec.namereturntrueifrequirement.none?requirement.satisfied_by?(spec.version)end### Merges the requirements of +other+ into this dependencydefmerge(other)unlessname==other.nameraiseArgumentError,"#{self} and #{other} have different names"enddefault=Gem::Requirement.defaultself_req=requirementother_req=other.requirementreturnself.class.newname,self_reqifother_req==defaultreturnself.class.newname,other_reqifself_req==defaultself.class.newname,self_req.as_list.concat(other_req.as_list)enddefmatching_specs(platform_only=false)matches=Gem::Specification.find_all_by_name(name,requirement)ifplatform_onlymatches.reject!do|spec|spec.nil?||!Gem::Platform.match_spec?(spec)endendmatches.reject(&:ignored?)end### True if the dependency will not always match the latest version.defspecific?@requirement.specific?enddefto_specsmatches=matching_specstrue# TODO: check Gem.activated_spec[self.name] in case matches falls outsideifmatches.empty?specs=Gem::Specification.stubs_fornameifspecs.empty?raiseGem::MissingSpecError.newname,requirementelseraiseGem::MissingSpecVersionError.newname,requirement,specsendend# TODO: any other resolver validations should go herematchesenddefto_specmatches=to_specs.compactactive=matches.find(&:activated?)returnactiveifactiveunlessprerelease?# Consider prereleases only as a fallbackpre,matches=matches.partition{|spec|spec.version.prerelease?}matches=preifmatches.empty?endmatches.firstenddefidentityifprerelease?ifspecific?:completeelse:abs_latestendelsiflatest_version?:latestelse:releasedendenddefencode_with(coder)# :nodoc:coder.add"name",@namecoder.add"requirement",@requirementcoder.add"type",@typecoder.add"prerelease",@prereleasecoder.add"version_requirements",@version_requirementsendend