ruby-libversion 1.0.0 → 1.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: c2aaf113a6cb56ae52674d46944ae80b6f563ff7c4652a510c1c0f32bccd6ada
4
- data.tar.gz: d7601cfdbf8412d5a8e59177881b1b985a077ddd537eda12e980ec8a93dc8fbc
3
+ metadata.gz: 8aed1ad2e15370a06bc24ac5669f418ea96964c6bc6cdd65398281fc25c10cd5
4
+ data.tar.gz: 8f2df4487bce8cad0191339051a9ffb22812043ba3ace992470370521c5b5887
5
5
  SHA512:
6
- metadata.gz: 4cbc1439eff77ecda561b19e5eba5d3dc5729f813fba77794f3d24e3a351ac0c98f26d56b6b26bd3e2c9453dd0b3b133e05897e7ac15628833c9e8f2bfa36b0c
7
- data.tar.gz: 3a83fdde12a0e61efddd341b181c8d33465cb869594df76d382aa0040f5b5a790b947f180bc387d15ed74f25092f31b4a902b076cbe3e79aef6e34928bb33244
6
+ metadata.gz: 03670010cfb23c20b9d863b7af8820471761ae93a5226451ade2970197a2fdbff803489ce849c5a2adfadddd48618c71dd039ddd55a81a6fd9f848810c206dca
7
+ data.tar.gz: 93fa1af30f55b561e3aaad4c42f383fe40aeabad965535bce6b87ac862c270719e1ca39d3b2b34d17f165529a56bf0e36081db8a0f8de5369feaac6e8ebba0dd
@@ -0,0 +1,16 @@
1
+ name: Rubocop
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - name: Download source
8
+ uses: actions/checkout@v5
9
+ - name: Install Ruby
10
+ uses: ruby/setup-ruby@v1
11
+ with:
12
+ ruby-version: '3.4'
13
+ - name: Install rubocop
14
+ run: gem install rubocop
15
+ - name: Run rubocop
16
+ run: rubocop
@@ -0,0 +1,36 @@
1
+ name: Test
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - name: Download source
8
+ uses: actions/checkout@v5
9
+ - name: Install Ruby
10
+ uses: ruby/setup-ruby@v1
11
+ with:
12
+ ruby-version: '3.4'
13
+ - name: Install dependencies
14
+ run: gem install rake-compiler
15
+ - name: Build and install ruby-libversion (Ruby fallback)
16
+ run: |
17
+ gem build ruby-libversion
18
+ gem install -l ruby-libversion
19
+ - name: Run tests (Ruby fallback)
20
+ run: rake test
21
+ - name: Install libversion # Hopefully this will get added as an Ubuntu/Debian package.
22
+ working-directory: ${{ runner.temp }}
23
+ run: |
24
+ git clone --depth 1 -b 3.0.3 https://github.com/repology/libversion
25
+ cd libversion
26
+ mkdir build
27
+ cd build
28
+ cmake .. -DCMAKE_INSTALL_PREFIX=/usr
29
+ make -j "$(nproc)"
30
+ sudo make install
31
+ - name: Build and install ruby-libversion (native extension)
32
+ run: |
33
+ gem build ruby-libversion
34
+ gem install -l ruby-libversion
35
+ - name: Run tests (native extension)
36
+ run: rake test
data/.rubocop.yml ADDED
@@ -0,0 +1,39 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
4
+ Gemspec/RequireMFA:
5
+ Enabled: false
6
+
7
+ # TODO: Find out what ruby version we actually require and then remove this.
8
+ Gemspec/RequiredRubyVersion:
9
+ Enabled: false
10
+
11
+ Layout/LineLength:
12
+ Enabled: false
13
+
14
+ Metrics:
15
+ Enabled: false
16
+
17
+ Naming/FileName:
18
+ Enabled: false
19
+
20
+ Naming/HeredocDelimiterNaming:
21
+ Enabled: false
22
+
23
+ Naming/MethodParameterName:
24
+ Enabled: False
25
+
26
+ Style/Documentation:
27
+ Enabled: False
28
+
29
+ Style/FrozenStringLiteralComment:
30
+ Enabled: False
31
+
32
+ Style/MutableConstant:
33
+ Enabled: False
34
+
35
+ Style/RedundantReturn:
36
+ Enabled: False
37
+
38
+ Style/RedundantSelf:
39
+ Enabled: False
@@ -2,4 +2,14 @@ require 'mkmf'
2
2
 
3
3
  pkg_config('libversion')
4
4
 
5
- create_makefile 'ruby_libversion'
5
+ # If $libs is still empty, we weren't able to find the library, so we don't build the extension.
6
+ if $libs.empty? # rubocop:disable Style/GlobalVars
7
+ # Create a dummy Makefile, to satisfy Gem::Installer#install
8
+ # You would think mkmf's dummy_makefile method would do this, but apparently not.
9
+ File.write 'Makefile', <<~EOF
10
+ .PHONY: install
11
+ install:
12
+ EOF
13
+ else
14
+ create_makefile 'ruby_libversion'
15
+ end
@@ -0,0 +1,121 @@
1
+ # This is a pure Ruby implementation of libversion, used as a fallback when the C extension is not available.
2
+
3
+ class VersionComponent
4
+ attr_accessor :component, :rank
5
+
6
+ # Store the ranks in order, so that we can compare their indexes to determine which is greater.
7
+ RANK_ORDERING = %i[lower_bound pre_release zero post_release nonzero letter_suffix upper_bound]
8
+
9
+ def initialize(components, flags)
10
+ # While we pass in a nil component to let determine_rank know we want padding, we set the actual value to 0 when we store it.
11
+ @component = components[1].nil? ? '0' : components[1]
12
+
13
+ @rank = determine_rank(components, flags)
14
+ end
15
+
16
+ def determine_rank(components, flags)
17
+ # If the current component is nil, it is padding.
18
+ if components[1].nil?
19
+ # When we are passed the lower bound flag, all padding is the lower_bound rank.
20
+ if flags == Libversion::VERSIONFLAG_LOWER_BOUND
21
+ return :lower_bound
22
+ # When we are passed the upper bound flag, all padding is the upper_bound rank.
23
+ elsif flags == Libversion::VERSIONFLAG_UPPER_BOUND
24
+ return :upper_bound
25
+ # If we have not been passed either bound flag, all padding is the zero rank.
26
+ else
27
+ return :zero
28
+ end
29
+ end
30
+
31
+ # If the current component starts with a pre-release keyword (case insensitive), it is the pre_release rank.
32
+ return :pre_release if components[1].downcase.start_with?('alpha', 'beta', 'rc', 'pre')
33
+
34
+ # If the current component is an integer and has a value of zero, it is the zero rank.
35
+ return :zero if Integer(components[1], exception: false)&.zero?
36
+
37
+ # If the current component starts with a post-release keyword (case insensitive), or if the current component
38
+ # starts with 'p' (case insensitive) and we were given the VERSIONFLAG_P_IS_PATCH flag, it is the post_release rank.
39
+ return :post_release if components[1].start_with?('post', 'patch', 'pl', 'errata') || (flags == Libversion::VERSIONFLAG_P_IS_PATCH && components[1][0]&.downcase == 'p')
40
+
41
+ # If the current component is an integer and has a nonzero value, it is the nonzero rank.
42
+ return :nonzero if Integer(components[1], exception: false)&.nonzero?
43
+
44
+ # If the previous component is an integer, the current component is alphabetic, and the next component is not an integer, the current component is the letter_suffix rank.
45
+ return :letter_suffix unless Integer(components[0], exception: false).nil? || components[1].match?(/[^[:alpha:]]/) || !Integer(components[2], exception: false).nil?
46
+
47
+ # If we were given the VERSIONFLAG_ANY_IS_PATCH flag, any remaining alphabetic component is of the post_release rank.
48
+ return :post_release if flags == Libversion::VERSIONFLAG_ANY_IS_PATCH
49
+
50
+ # Otherwise, any remaining alphabetic component is of the pre_release rank.
51
+ return :pre_release
52
+ end
53
+
54
+ def <=>(other)
55
+ # Compare the rank of both components, and return the result unless they have the same rank.
56
+ rank_comparison = RANK_ORDERING.index(self.rank) <=> RANK_ORDERING.index(other.rank)
57
+ return rank_comparison unless rank_comparison.zero?
58
+
59
+ # If both components are alphabetic, return the case-insensitive comparison of their first letters.
60
+ return self.component[0].downcase <=> other.component[0].downcase if [self, other].none? { _1.component.match?(/[^[:alpha:]]/) }
61
+
62
+ # If we are still here, return the integer comparison of both components.
63
+ return self.component.to_i <=> other.component.to_i
64
+ end
65
+
66
+ def empty?
67
+ @component.empty?
68
+ end
69
+ end
70
+
71
+ module Libversion
72
+ VERSIONFLAG_P_IS_PATCH = 1
73
+ VERSIONFLAG_ANY_IS_PATCH = 2
74
+ VERSIONFLAG_LOWER_BOUND = 4
75
+ VERSIONFLAG_UPPER_BOUND = 8
76
+
77
+ def self.version_compare4(v1, v2, v1_flags, v2_flags)
78
+ # Parse the raw version strings into an array of VersionComponents.
79
+ v1_components = parse_version_string(v1, v1_flags)
80
+ v2_components = parse_version_string(v2, v2_flags)
81
+
82
+ # Pad each version so that they are the same length prior to zipping and comparison.
83
+ # We add additional padding to support lower and upper bounds even when the versions have an equal number of components.
84
+ v1_components.fill(VersionComponent.new([nil, nil, nil], v1_flags), v1_components.size, v2_components.size)
85
+ v2_components.fill(VersionComponent.new([nil, nil, nil], v2_flags), v2_components.size, v1_components.size)
86
+
87
+ # Zip the components together for ease of comparison.
88
+ zipped_components = v1_components.zip(v2_components)
89
+
90
+ # Iterate over the zipped components, comparing them and returning the first nonzero result we receive.
91
+ (0...zipped_components.size).each do |i|
92
+ comparison_result = zipped_components[i][0] <=> zipped_components[i][1]
93
+ return comparison_result unless comparison_result.zero?
94
+ end
95
+
96
+ # If we got here, every component was equal, and thus the versions are equal.
97
+ return 0
98
+ end
99
+
100
+ def self.version_compare2(v1, v2)
101
+ version_compare4(v1, v2, 0, 0)
102
+ end
103
+
104
+ private_class_method def self.parse_version_string(version_string, version_flags)
105
+ # Separate the version string into all-alphabetic and all-numeric components, with all other characters treated as separators.
106
+ # Separators are recorded as empty strings, with consecutive separators being squeezed into a single empty string.
107
+ version_raw_components = version_string.scan(/[[:alpha:]]+|[[:digit:]]+|[^[:alnum:]]+/).map { _1.match?(/[^[:alnum:]]/) ? '' : _1 }
108
+ # Pad the raw components with nil values so that every real component gets a turn at the centre of the tuple we pass to VersionComponent.new
109
+ version_raw_components.prepend(nil)
110
+ version_raw_components.append(nil)
111
+
112
+ # Loop over the raw components in groups of 3 (so we have the information for checking letter_suffix), storing the center component
113
+ # and its rank as a VersionComponent in version_components.
114
+ version_components = []
115
+ version_raw_components.each_cons(3) { version_components << VersionComponent.new(_1, version_flags) }
116
+ # Clean up any excess empty version components.
117
+ version_components.reject!(&:empty?)
118
+
119
+ return version_components
120
+ end
121
+ end
@@ -1,10 +1,10 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'ruby-libversion'
3
3
  spec.summary = 'Ruby bindings for libversion'
4
- spec.version = '1.0.0'
4
+ spec.version = '1.1.0'
5
5
  spec.license = 'MIT'
6
6
  spec.author = 'Maximilian Downey Twiss'
7
- spec.email = 'creatorsmithmdt@.com'
7
+ spec.email = 'creatorsmithmdt@gmail.com'
8
8
  spec.homepage = 'https://github.com/Zopolis4/ruby-libversion'
9
9
  spec.files = `git ls-files`.split("\n")
10
10
  spec.extensions = 'ext/libversion/extconf.rb'
@@ -4,7 +4,7 @@ require 'ruby_libversion'
4
4
  # These test cases are taken from here:
5
5
  # https://github.com/repology/libversion/blob/master/tests/compare_test.c
6
6
  # The copyright notice from that file is reproduced here:
7
- # Copyright (c)) 2017-2018 Dmitry Marakasov <amdmi3@amdmi3.ru>
7
+ # Copyright (c) 2017-2018 Dmitry Marakasov <amdmi3@amdmi3.ru>
8
8
  class RubyLibversionTest < Minitest::Test
9
9
  def test_equality
10
10
  assert_equal(0, Libversion.version_compare2('0', '0'))
metadata CHANGED
@@ -1,36 +1,37 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-libversion
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maximilian Downey Twiss
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-02-08 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
- description:
14
- email: creatorsmithmdt@.com
12
+ email: creatorsmithmdt@gmail.com
15
13
  executables: []
16
14
  extensions:
17
15
  - ext/libversion/extconf.rb
18
16
  extra_rdoc_files: []
19
17
  files:
18
+ - ".github/workflows/rubocop.yml"
19
+ - ".github/workflows/test.yml"
20
20
  - ".gitignore"
21
+ - ".rubocop.yml"
21
22
  - LICENSE
22
23
  - README.md
23
24
  - Rakefile
24
25
  - ext/libversion/extconf.rb
25
26
  - ext/libversion/libversion.c
26
27
  - lib/libversion.rb
28
+ - lib/ruby_libversion.rb
27
29
  - ruby-libversion.gemspec
28
30
  - test/test_ruby_libversion.rb
29
31
  homepage: https://github.com/Zopolis4/ruby-libversion
30
32
  licenses:
31
33
  - MIT
32
34
  metadata: {}
33
- post_install_message:
34
35
  rdoc_options: []
35
36
  require_paths:
36
37
  - lib
@@ -45,8 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
45
46
  - !ruby/object:Gem::Version
46
47
  version: '0'
47
48
  requirements: []
48
- rubygems_version: 3.4.20
49
- signing_key:
49
+ rubygems_version: 3.6.7
50
50
  specification_version: 4
51
51
  summary: Ruby bindings for libversion
52
52
  test_files: []