[rubygems/rubygems] Avoid excess Arrays when partitioning Gem::Version.canonical_segments

https://github.com/rubygems/rubygems/commit/338c48f935
This commit is contained in:
Martin Emde 2023-10-10 17:27:34 -07:00 committed by git
parent 8a8b23c0cc
commit 9dcaa83259

View File

@ -388,31 +388,21 @@ class Gem::Version
0 0
end end
# remove trailing zeros segments before first letter or at the end of the version
def canonical_segments def canonical_segments
@canonical_segments ||= begin @canonical_segments ||= begin
numeric_segments, string_segments = _split_segments # remove trailing 0 segments, using dot or letter as anchor
canonical_segments = [] # may leave a trailing dot which will be ignored by partition_segments
canonical_version = @version.sub(/(?<=[a-zA-Z.])[.0]+\z/, "")
seen_non_zero = false # remove 0 segments before the first letter in a prerelease version
string_segments.reverse_each do |segment| canonical_version.sub!(/(?<=\.|\A)[0.]+(?=[a-zA-Z])/, "") if prerelease?
if seen_non_zero || (seen_non_zero = (segment != 0)) partition_segments(canonical_version)
canonical_segments << segment
end
end
seen_non_zero = false
numeric_segments.reverse_each do |segment|
if seen_non_zero || (seen_non_zero = (segment != 0))
canonical_segments << segment
end
end
canonical_segments.reverse!
canonical_segments.freeze
end end
end end
def freeze def freeze
prerelease? prerelease?
_segments
canonical_segments canonical_segments
super super
end end
@ -423,16 +413,12 @@ class Gem::Version
# segments is lazy so it can pick up version values that come from # segments is lazy so it can pick up version values that come from
# old marshaled versions, which don't go through marshal_load. # old marshaled versions, which don't go through marshal_load.
# since this version object is cached in @@all, its @segments should be frozen # since this version object is cached in @@all, its @segments should be frozen
@segments ||= partition_segments(@version)
end
@segments ||= @version.scan(/[0-9]+|[a-z]+/i).map! do |s| def partition_segments(ver)
/^\d+$/.match?(s) ? s.to_i : -s ver.scan(/\d+|[a-z]+/i).map! do |s|
/\A\d/.match?(s) ? s.to_i : -s
end.freeze end.freeze
end end
def _split_segments
string_start = _segments.index {|s| s.is_a?(String) }
string_segments = segments
numeric_segments = string_segments.slice!(0, string_start || string_segments.size)
[numeric_segments, string_segments]
end
end end