# frozen_string_literal: true### The Dependency class holds a Gem name and a Gem::Requirement.require"rubygems/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,]### 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>.definitializename,*requirementscasenamewhenStringthen# 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.firstif1==requirements.length# 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?then"<%s type=%p name=%p requirements=%p prerelease=ok>"%[self.class,self.type,self.name,requirement.to_s]else"<%s type=%p name=%p requirements=%p>"%[self.class,self.type,self.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_printq# :nodoc:q.group1,'Gem::Dependency.new(',')'doq.ppnameq.text','q.breakableq.pprequirementq.text','q.breakableq.pptypeendend### What does this dependency require?defrequirementreturn@requirementifdefined?(@requirement)and@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!=:runtimethen"#{name} (#{requirement}, #{type})"else"#{name} (#{requirement})"endend### Dependency type.deftype@type||=:runtimeenddefruntime?@type==:runtime||!@typeenddef==other# :nodoc:Gem::Dependency===other&&self.name==other.name&&self.type==other.type&&self.requirement==other.requirementend### Dependencies are ordered by name.def<=>otherself.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=~otherunlessGem::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====~### :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=falseif!versionname=obj.nameversion=obj.versionelsename=objendreturnfalseunlessself.name===nameversion=Gem::Version.newversionreturntrueifrequirement.none?andnotversion.prerelease?returnfalseifversion.prerelease?andnotallow_prereleaseandnotprerelease?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?specreturnfalseunlessname===spec.namereturntrueifrequirement.none?requirement.satisfied_by?(spec.version)end### Merges the requirements of +other+ into this dependencydefmergeotherunlessname==other.namethenraiseArgumentError,"#{self} and #{other} have different names"enddefault=Gem::Requirement.defaultself_req=self.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_specsplatform_only=falseenv_req=Gem.env_requirement(name)matches=Gem::Specification.stubs_for(name).find_all{|spec|requirement.satisfied_by?(spec.version)&&env_req.satisfied_by?(spec.version)}.map(&:to_spec)ifplatform_onlymatches.reject!{|spec|spec.nil?||!Gem::Platform.match(spec.platform)}endmatchesend### 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?thenspecs=Gem::Specification.stubs_fornameifspecs.empty?raiseGem::MissingSpecError.newname,requirementelseraiseGem::MissingSpecVersionError.newname,requirement,specsendend# TODO: any other resolver validations should go herematchesenddefto_specmatches=self.to_specsactive=matches.find{|spec|spec&&spec.activated?}returnactiveifactivematches.delete_if{|spec|spec.nil?||spec.version.prerelease?}unlessprerelease?matches.firstendend