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 +4 -4
- data/lib/semver_dialects/rpm.rb +156 -0
- data/lib/semver_dialects/version.rb +1 -1
- data/lib/semver_dialects.rb +13 -4
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f1f8032a4c9d878a2d87171d58bcd60d34d23797e7a190bd4f71983ece8631d4
|
|
4
|
+
data.tar.gz: f14c6e7ffc8782d8c4c3c8a439cb4cf807470157e6cd86b420cf2b8aa32b9322
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/semver_dialects.rb
CHANGED
|
@@ -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
|
|
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
|
-
|
|
94
|
-
|
|
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
|
-
|
|
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
|
|
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-
|
|
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
|