Server IP : 172.67.158.161 / Your IP : 3.139.86.131 Web Server : LiteSpeed System : Linux business53.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64 User : giankuin ( 1871) PHP Version : 7.4.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/ |
Upload File : |
module Puppet::Util::RpmCompare ARCH_LIST = %w( noarch i386 i686 ppc ppc64 armv3l armv4b armv4l armv4tl armv5tel armv5tejl armv6l armv7l m68kmint s390 s390x ia64 x86_64 sh3 sh4 ).freeze ARCH_REGEX = Regexp.new(ARCH_LIST.join('|\.')) # This is an attempt at implementing RPM's # lib/rpmvercmp.c rpmvercmp(a, b) in Ruby. # # Some of the things in here look REALLY # UGLY and/or arbitrary. Our goal is to # match how RPM compares versions, quirks # and all. # # I've kept a lot of C-like string processing # in an effort to keep this as identical to RPM # as possible. # # returns 1 if str1 is newer than str2, # 0 if they are identical # -1 if str1 is older than str2 def rpmvercmp(str1, str2) return 0 if str1 == str2 front_strip_re = /^[^A-Za-z0-9~]+/ while str1.length > 0 or str2.length > 0 # trim anything that's in front_strip_re and != '~' off the beginning of each string str1 = str1.gsub(front_strip_re, '') str2 = str2.gsub(front_strip_re, '') # "handle the tilde separator, it sorts before everything else" if str1 =~ /^~/ && str2 =~ /^~/ # if they both have ~, strip it str1 = str1[1..-1] str2 = str2[1..-1] next elsif str1 =~ /^~/ return -1 elsif str2 =~ /^~/ return 1 end break if str1.length == 0 or str2.length == 0 # "grab first completely alpha or completely numeric segment" isnum = false # if the first char of str1 is a digit, grab the chunk of continuous digits from each string if str1 =~ /^[0-9]+/ if str1 =~ /^[0-9]+/ segment1 = $~.to_s str1 = $~.post_match else segment1 = '' end if str2 =~ /^[0-9]+/ segment2 = $~.to_s str2 = $~.post_match else segment2 = '' end isnum = true # else grab the chunk of continuous alphas from each string (which may be '') else if str1 =~ /^[A-Za-z]+/ segment1 = $~.to_s str1 = $~.post_match else segment1 = '' end if str2 =~ /^[A-Za-z]+/ segment2 = $~.to_s str2 = $~.post_match else segment2 = '' end end # if the segments we just grabbed from the strings are different types (i.e. one numeric one alpha), # where alpha also includes ''; "numeric segments are always newer than alpha segments" if segment2.length == 0 return 1 if isnum return -1 end if isnum # "throw away any leading zeros - it's a number, right?" segment1 = segment1.gsub(/^0+/, '') segment2 = segment2.gsub(/^0+/, '') # "whichever number has more digits wins" return 1 if segment1.length > segment2.length return -1 if segment1.length < segment2.length end # "strcmp will return which one is greater - even if the two segments are alpha # or if they are numeric. don't return if they are equal because there might # be more segments to compare" rc = segment1 <=> segment2 return rc if rc != 0 end #end while loop # if we haven't returned anything yet, "whichever version still has characters left over wins" return 1 if str1.length > str2.length return -1 if str1.length < str2.length 0 end # parse a rpm "version" specification # this re-implements rpm's # rpmUtils.miscutils.stringToVersion() in ruby def rpm_parse_evr(full_version) epoch_index = full_version.index(':') if epoch_index epoch = full_version[0,epoch_index] full_version = full_version[epoch_index+1,full_version.length] else epoch = nil end begin epoch = String(Integer(epoch)) rescue # If there are non-digits in the epoch field, default to nil epoch = nil end release_index = full_version.index('-') if release_index version = full_version[0,release_index] release = full_version[release_index+1,full_version.length] arch = release.scan(ARCH_REGEX)[0] if arch architecture = arch.delete('.') release.gsub!(ARCH_REGEX, '') end else version = full_version release = nil end return { :epoch => epoch, :version => version, :release => release, :arch => architecture } end # this method is a native implementation of the # compare_values function in rpm's python bindings, # found in python/header-py.c, as used by rpm. def compare_values(s1, s2) return 0 if s1.nil? && s2.nil? return 1 if ( not s1.nil? ) && s2.nil? return -1 if s1.nil? && (not s2.nil?) return rpmvercmp(s1, s2) end # how rpm compares two package versions: # rpmUtils.miscutils.compareEVR(), which massages data types and then calls # rpm.labelCompare(), found in rpm.git/python/header-py.c, which # sets epoch to 0 if null, then compares epoch, then ver, then rel # using compare_values() and returns the first non-0 result, else 0. # This function combines the logic of compareEVR() and labelCompare(). # # "version_should" can be v, v-r, or e:v-r. # "version_is" will always be at least v-r, can be e:v-r # # return 1: a is newer than b # 0: a and b are the same version # -1: b is newer than a def rpm_compareEVR(should, is) # pass on to rpm labelCompare should_hash = rpm_parse_evr(should) is_hash = rpm_parse_evr(is) if !should_hash[:epoch].nil? rc = compare_values(should_hash[:epoch], is_hash[:epoch]) return rc unless rc == 0 end rc = compare_values(should_hash[:version], is_hash[:version]) return rc unless rc == 0 # here is our special case, PUP-1244. # if should_hash[:release] is nil (not specified by the user), # and comparisons up to here are equal, return equal. We need to # evaluate to whatever level of detail the user specified, so we # don't end up upgrading or *downgrading* when not intended. # # This should NOT be triggered if we're trying to ensure latest. return 0 if should_hash[:release].nil? rc = compare_values(should_hash[:release], is_hash[:release]) return rc end end