semver_dialects 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d29656d2bd4bdc5bb1cd50c3cf3853e192fbb7de944b4495c816f424d710648
4
- data.tar.gz: adbbb1f25f05a91ac195a6e8becb823b4f412a40476a26697547d06556253868
3
+ metadata.gz: f1f8032a4c9d878a2d87171d58bcd60d34d23797e7a190bd4f71983ece8631d4
4
+ data.tar.gz: f14c6e7ffc8782d8c4c3c8a439cb4cf807470157e6cd86b420cf2b8aa32b9322
5
5
  SHA512:
6
- metadata.gz: 585e0ad23e05cbd4bade3aaf925bd38b07af390de78a7a28446cb6dad50b05a99155d8744d497fcbf6377e2013bb5740fc4bb140425f52217f5bb35312af3c53
7
- data.tar.gz: d17f636215c7c9d338819ab56ed8bbdc6f1349bfadb34c15a860d9398d2afb3a41f4c6bc521807e3e23ee36a19f9370c295c12485d9e7de5db95fef5af3b2c22
6
+ metadata.gz: e36e7b55574b064ac14c2a1bbe0e8d2bd9fcf5a22a155b42a1623029f939e54fdac6ac76ef19a6d391de0a0a4fa0801383b72627a583a2520b6cc94de72f55cb
7
+ data.tar.gz: af976bec11fc7bc8eba97c7afa17a207713ed22d386a8ae9701826cfd53c23ad86fb246fbebb84e77dca9c693422939ca639a5859ecabb3e5825fd9137bd8af9
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'strscan'
4
+
5
+ module SemverDialects
6
+ module Rpm
7
+ module TokenPairComparison
8
+ # Token can be either alphabets, integers or tilde.
9
+ # Caret is currently not supported. More details here https://gitlab.com/gitlab-org/gitlab/-/issues/428941#note_1882343489
10
+ # Precedence: numeric token > string token > no token > tilda (~)
11
+ def compare_token_pair(a, b)
12
+ return 1 if a != '~' && b == '~'
13
+ return -1 if a == '~' && b != '~'
14
+
15
+ return 1 if !a.nil? && b.nil?
16
+ return -1 if a.nil? && !b.nil?
17
+
18
+ return 1 if a.is_a?(Integer) && b.is_a?(String)
19
+ return -1 if a.is_a?(String) && b.is_a?(Integer)
20
+
21
+ # Remaining scenario are tokens of the same type ie Integer or String. Use <=> to compare
22
+ a <=> b
23
+ end
24
+ end
25
+
26
+ # This implementation references `go-rpm-version` https://github.com/knqyf263/go-rpm-version
27
+ # Which is based on the official `rpmvercmp` https://github.com/rpm-software-management/rpm/blob/master/rpmio/rpmvercmp.c implementation
28
+ # rpm versioning schema can be found here https://github.com/rpm-software-management/rpm/blob/master/docs/manual/dependencies.md#versioning
29
+ # Details on how the caret and tilde symbols are handled can be found here https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/#_handling_non_sorting_versions_with_tilde_dot_and_caret
30
+ class Version < BaseVersion
31
+ include TokenPairComparison
32
+
33
+ attr_reader :tokens, :addition, :epoch
34
+
35
+ def initialize(tokens, epoch: nil, release_tag: nil)
36
+ @tokens = tokens
37
+ @addition = release_tag
38
+ @epoch = epoch
39
+ end
40
+
41
+ def <=>(other)
42
+ # Compare epoch first
43
+ epoch_cmp = compare_epochs(epoch, other.epoch)
44
+ return epoch_cmp unless epoch_cmp.zero?
45
+
46
+ # Then compare version
47
+ cmp = compare_tokens(tokens, other.tokens)
48
+ return cmp unless cmp.zero?
49
+
50
+ # And finally compare release tags
51
+ compare_additions(addition, other.addition)
52
+ end
53
+
54
+ # Note that to_s does not accurately recreate the version string.
55
+ # More details here https://gitlab.com/gitlab-org/gitlab/-/issues/428941#note_1882343489
56
+ def to_s
57
+ main = if !epoch.nil?
58
+ "#{epoch}:" + tokens.join('.')
59
+ else
60
+ tokens.join('.')
61
+ end
62
+ main += "-#{addition.tokens.join('.')}" unless addition.nil?
63
+
64
+ # Remove . around ~
65
+ main.gsub(/\.~\./, '~')
66
+ end
67
+
68
+ private
69
+
70
+ def compare_epochs(a, b)
71
+ (a || 0) <=> (b || 0)
72
+ end
73
+ end
74
+
75
+ class ReleaseTag < BaseVersion
76
+ include TokenPairComparison
77
+
78
+ def initialize(tokens)
79
+ @tokens = tokens
80
+ end
81
+ end
82
+
83
+ class VersionParser
84
+ DASH = /-/
85
+ ALPHABET = /([a-zA-Z]+)/
86
+ TILDE = /~/
87
+ DIGIT = /([0-9]+)/
88
+ COLON = /:/
89
+ NON_ALPHANUMERIC_DASH_AND_TILDE = /[^a-zA-Z0-9~]+/
90
+
91
+ def self.parse(input)
92
+ new(input).parse
93
+ end
94
+
95
+ def initialize(input)
96
+ @scanner = StringScanner.new(input)
97
+ end
98
+
99
+ # parse splits the input string into epoch, version and release tag Eg: <epoch>:<version>-<release_tag>
100
+ # The version and release tag are split at the first `-` character if present
101
+ # With the segment before the first `-` being version while the other being release tag
102
+ # Subsequent `-` are disregarded
103
+ def parse
104
+ epoch = nil
105
+ if s = scanner.scan(/\d+:/)
106
+ epoch = s[..-2].to_i
107
+ end
108
+
109
+ # parse tokens until we reach the release tag, if any
110
+ tokens = parse_tokens(false)
111
+
112
+ # parse release tag
113
+ release_tag = nil
114
+ if scanner.rest?
115
+ release_tag = ReleaseTag.new(parse_tokens(true))
116
+ end
117
+
118
+ raise IncompleteScanError, scanner.rest if scanner.rest?
119
+
120
+ Version.new(tokens, epoch: epoch, release_tag: release_tag)
121
+ end
122
+
123
+ private
124
+
125
+ attr_reader :scanner
126
+
127
+ def parse_tokens(stop_at_release_tag)
128
+ tokens = []
129
+
130
+ until scanner.eos?
131
+ case
132
+ when (s = scanner.scan(DASH))
133
+ if !stop_at_release_tag
134
+ return tokens
135
+ end
136
+ # If release tag has been encountered, ignore subsequent dashes
137
+ when (s = scanner.scan(ALPHABET))
138
+ tokens << s
139
+ when (s = scanner.scan(TILDE))
140
+ tokens << s
141
+ when (s = scanner.scan(DIGIT))
142
+ tokens << s.to_i
143
+ when (s = scanner.scan(NON_ALPHANUMERIC_DASH_AND_TILDE))
144
+ # Non-ascii characters are considered equal
145
+ # so they are ignored when parsing versions
146
+ # https://github.com/rpm-software-management/rpm/blob/rpm-4.19.1.1-release/tests/rpmvercmp.at#L143
147
+ else
148
+ raise SemverDialects::IncompleteScanError, scanner.rest
149
+ end
150
+ end
151
+ tokens
152
+ end
153
+ end
154
+
155
+ end
156
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SemverDialects
4
- VERSION = '3.0.2'
4
+ VERSION = '3.1.0'
5
5
  end
@@ -3,6 +3,7 @@
3
3
  require 'semver_dialects/version'
4
4
  require 'semver_dialects/base_version'
5
5
  require 'semver_dialects/maven'
6
+ require 'semver_dialects/rpm'
6
7
  require 'semver_dialects/semver2'
7
8
  require 'semver_dialects/semantic_version'
8
9
  require 'semver_dialects/boundary'
@@ -85,15 +86,23 @@ module SemverDialects
85
86
  end
86
87
 
87
88
  def self.os_pkg_version_satisfies?(typ, raw_ver, raw_constraint)
88
- return unless typ == 'deb'
89
+ return unless %w[deb rpm].include?(typ)
89
90
  # we only support the less than operator, because that's the only one currently output
90
91
  # by the advisory exporter for operating system packages.
91
92
  raise SemverDialects::InvalidConstraintError, raw_constraint unless raw_constraint[0] == '<'
92
93
 
93
- v1 = DebVersion.new(raw_ver)
94
- v2 = DebVersion.new(raw_constraint[1..])
94
+ case typ
95
+ when 'deb'
96
+ v1 = DebVersion.new(raw_ver)
97
+ v2 = DebVersion.new(raw_constraint[1..])
98
+
99
+ v1 < v2
100
+ when 'rpm'
101
+ v1 = Rpm::VersionParser.parse(raw_ver)
102
+ v2 = Rpm::VersionParser.parse(raw_constraint[1..])
95
103
 
96
- v1 < v2
104
+ v1 < v2
105
+ end
97
106
  end
98
107
 
99
108
  # Parse a version according to the syntax type.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semver_dialects
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.2
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Thome
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2024-06-17 00:00:00.000000000 Z
13
+ date: 2024-06-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: pastel
@@ -187,6 +187,7 @@ files:
187
187
  - lib/semver_dialects/interval_set.rb
188
188
  - lib/semver_dialects/interval_set_parser.rb
189
189
  - lib/semver_dialects/maven.rb
190
+ - lib/semver_dialects/rpm.rb
190
191
  - lib/semver_dialects/semantic_version.rb
191
192
  - lib/semver_dialects/semver2.rb
192
193
  - lib/semver_dialects/version.rb