Module: Vers::RPMVersion

Extended by:
RPMVersion
Included in:
RPMVersion
Defined in:
lib/vers/distribution_version.rb

Constant Summary collapse

PART_PATTERN =
/\A[0-9A-Za-z._+~^]+\z/

Instance Method Summary collapse

Instance Method Details

#alpha?(byte) ⇒ Boolean

Returns:

  • (Boolean)


255
256
257
# File 'lib/vers/distribution_version.rb', line 255

def alpha?(byte)
  byte&.between?(65, 90) || byte&.between?(97, 122)
end

#alphanumeric?(byte) ⇒ Boolean

Returns:

  • (Boolean)


259
260
261
# File 'lib/vers/distribution_version.rb', line 259

def alphanumeric?(byte)
  digit?(byte) || alpha?(byte)
end

#compare(left, right) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/vers/distribution_version.rb', line 133

def compare(left, right)
  left_epoch, left_version, left_release = split(left)
  right_epoch, right_version, right_release = split(right)

  comparison = VersionComparison.compare_numbers(left_epoch, right_epoch)
  return comparison unless comparison.zero?

  comparison = compare_part(left_version, right_version)
  return comparison unless comparison.zero?

  compare_part(left_release, right_release)
end

#compare_part(left, right) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/vers/distribution_version.rb', line 178

def compare_part(left, right)
  left_index = 0
  right_index = 0

  while left_index < left.length || right_index < right.length
    left_index = skip_separators(left, left_index)
    right_index = skip_separators(right, right_index)

    if marker_at?(left, left_index, 126) || marker_at?(right, right_index, 126)
      return 1 unless marker_at?(left, left_index, 126)
      return -1 unless marker_at?(right, right_index, 126)

      left_index += 1
      right_index += 1
      next
    end

    if marker_at?(left, left_index, 94) || marker_at?(right, right_index, 94)
      return -1 if left_index >= left.length
      return 1 if right_index >= right.length
      return 1 unless marker_at?(left, left_index, 94)
      return -1 unless marker_at?(right, right_index, 94)

      left_index += 1
      right_index += 1
      next
    end

    return (left.length - left_index) <=> (right.length - right_index) if left_index >= left.length || right_index >= right.length

    left_numeric = digit?(left.getbyte(left_index))
    right_numeric = digit?(right.getbyte(right_index))
    return left_numeric ? 1 : -1 if left_numeric != right_numeric

    left_end = scan_segment(left, left_index, left_numeric)
    right_end = scan_segment(right, right_index, right_numeric)
    comparison = if left_numeric
                   VersionComparison.compare_numbers(left[left_index...left_end], right[right_index...right_end])
                 else
                   left[left_index...left_end] <=> right[right_index...right_end]
                 end
    return comparison unless comparison.zero?

    left_index = left_end
    right_index = right_end
  end

  0
end

#digit?(byte) ⇒ Boolean

Returns:

  • (Boolean)


251
252
253
# File 'lib/vers/distribution_version.rb', line 251

def digit?(byte)
  byte&.between?(48, 57)
end

#marker_at?(value, index, marker) ⇒ Boolean

Returns:

  • (Boolean)


238
239
240
# File 'lib/vers/distribution_version.rb', line 238

def marker_at?(value, index, marker)
  index < value.length && value.getbyte(index) == marker
end

#normalize(value) ⇒ Object



169
170
171
# File 'lib/vers/distribution_version.rb', line 169

def normalize(value)
  value.to_s.strip
end

#prerelease?(value) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
176
# File 'lib/vers/distribution_version.rb', line 173

def prerelease?(value)
  _, version, release = split(value.to_s.strip)
  version.include?("~") || release.include?("~")
end

#scan_segment(value, index, numeric) ⇒ Object



242
243
244
245
246
247
248
249
# File 'lib/vers/distribution_version.rb', line 242

def scan_segment(value, index, numeric)
  if numeric
    index += 1 while index < value.length && digit?(value.getbyte(index))
  else
    index += 1 while index < value.length && alpha?(value.getbyte(index))
  end
  index
end

#skip_separators(value, index) ⇒ Object



228
229
230
231
232
233
234
235
236
# File 'lib/vers/distribution_version.rb', line 228

def skip_separators(value, index)
  while index < value.length
    byte = value.getbyte(index)
    break if alphanumeric?(byte) || byte == 126 || byte == 94

    index += 1
  end
  index
end

#split(value) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/vers/distribution_version.rb', line 146

def split(value)
  epoch, version = value.to_s.split(":", 2)
  unless version
    version = epoch
    epoch = ""
  end

  separator = version.rindex("-")
  return [epoch, version, ""] unless separator

  [epoch, version[0...separator], version[(separator + 1)..]]
end

#valid?(value) ⇒ Boolean

Returns:

  • (Boolean)


159
160
161
162
163
164
165
166
167
# File 'lib/vers/distribution_version.rb', line 159

def valid?(value)
  string = value.to_s.strip
  return false if string.empty? || string.end_with?("-")

  epoch, version, release = split(string)
  return false unless epoch.empty? || VersionComparison.numeric?(epoch)

  version.match?(PART_PATTERN) && (release.empty? || release.match?(PART_PATTERN))
end