Module: Vers::DebianVersion

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

Constant Summary collapse

UPSTREAM_PATTERN =
/\A[0-9][0-9A-Za-z.+~]*\z/
REVISION_PATTERN =
/\A[0-9A-Za-z.+~]+\z/

Instance Method Summary collapse

Instance Method Details

#alpha?(byte) ⇒ Boolean

Returns:

  • (Boolean)


123
124
125
# File 'lib/vers/distribution_version.rb', line 123

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

#character_order(byte) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/vers/distribution_version.rb', line 111

def character_order(byte)
  return -1 if byte == 126
  return 0 if byte.zero?
  return byte if alpha?(byte)

  byte + 256
end

#compare(left, right) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/vers/distribution_version.rb', line 12

def compare(left, right)
  left_epoch, left_upstream, left_revision = split(left)
  right_epoch, right_upstream, right_revision = split(right)

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

  comparison = compare_part(left_upstream, right_upstream)
  return comparison unless comparison.zero?

  compare_part(left_revision, right_revision)
end

#compare_part(left, right) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/vers/distribution_version.rb', line 64

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

  while left_index < left.length || right_index < right.length
    while non_digit_at?(left, left_index) || non_digit_at?(right, right_index)
      left_byte = non_digit_at?(left, left_index) ? left.getbyte(left_index) : 0
      right_byte = non_digit_at?(right, right_index) ? right.getbyte(right_index) : 0
      comparison = character_order(left_byte) <=> character_order(right_byte)
      return comparison unless comparison.zero?

      left_index += 1 unless left_byte.zero?
      right_index += 1 unless right_byte.zero?
    end

    left_zero_end = skip_zeroes(left, left_index)
    right_zero_end = skip_zeroes(right, right_index)
    left_digit_end = scan_digits(left, left_zero_end)
    right_digit_end = scan_digits(right, right_zero_end)

    comparison = (left_digit_end - left_zero_end) <=> (right_digit_end - right_zero_end)
    return comparison unless comparison.zero?

    comparison = left[left_zero_end...left_digit_end] <=> right[right_zero_end...right_digit_end]
    return comparison unless comparison.zero?

    left_index = left_digit_end
    right_index = right_digit_end
  end

  0
end

#digit?(byte) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
# File 'lib/vers/distribution_version.rb', line 119

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

#non_digit_at?(value, index) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/vers/distribution_version.rb', line 97

def non_digit_at?(value, index)
  index < value.length && !digit?(value.getbyte(index))
end

#normalize(value) ⇒ Object



55
56
57
# File 'lib/vers/distribution_version.rb', line 55

def normalize(value)
  value.to_s.strip
end

#prerelease?(value) ⇒ Boolean

Returns:

  • (Boolean)


59
60
61
62
# File 'lib/vers/distribution_version.rb', line 59

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

#scan_digits(value, index) ⇒ Object



106
107
108
109
# File 'lib/vers/distribution_version.rb', line 106

def scan_digits(value, index)
  index += 1 while index < value.length && digit?(value.getbyte(index))
  index
end

#skip_zeroes(value, index) ⇒ Object



101
102
103
104
# File 'lib/vers/distribution_version.rb', line 101

def skip_zeroes(value, index)
  index += 1 while index < value.length && value.getbyte(index) == 48
  index
end

#split(value) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/vers/distribution_version.rb', line 25

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

  separator = version.rindex("-")
  if separator
    [epoch, version[0...separator], version[(separator + 1)..]]
  else
    [epoch, version, "0"]
  end
end

#valid?(value) ⇒ Boolean

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/vers/distribution_version.rb', line 40

def valid?(value)
  string = value.to_s.strip
  epoch, version = string.split(":", 2)
  if version
    return false unless VersionComparison.numeric?(epoch)
  else
    version = epoch
  end

  separator = version.rindex("-")
  upstream = separator ? version[0...separator] : version
  revision = separator ? version[(separator + 1)..] : nil
  upstream.match?(UPSTREAM_PATTERN) && (revision.nil? || revision.match?(REVISION_PATTERN))
end