File: base_version.rb

package info (click to toggle)
ruby-semver-dialects 3.4.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 156 kB
  • sloc: ruby: 1,537; makefile: 4
file content (79 lines) | stat: -rw-r--r-- 2,161 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# frozen_string_literal: true

# Class that describes a version that can be compared to another version in a generic way.
#
# A version is made of +tokens+ and an optional +addition+.
# Tokens and additions must be comparable using the spaceship operator.
# An addition behaves like a version and must respond to +tokens+.
#
# Tokens are used to represent the dot separated list of segments
# like 1.2.3 (semantic version) or alpha.1 (pre-release tag).
#
# Version 1.2.3-alpha.1-2024.03.25 is made of 3 +Version+ objects
# whose tokens are represented as 1.2.3, alpha.1, 2024.03.25.
# Version alpha.1 is the addition of version 1.2.3,
# and version 2024.03.25 is the addition of version alpha.1.
#
# This class can support of the comparison logic of many syntaxes
# by implementing specific token classes.
#
module SemverDialects
  class BaseVersion
    include Comparable

    attr_reader :tokens, :addition

    def initialize(tokens, addition: nil)
      @tokens = tokens
      @addition = addition
    end

    def to_s
      main = tokens.join('.')
      main += "-#{addition}" if addition
      main
    end

    def <=>(other)
      cmp = compare_tokens(tokens, other.tokens)
      return cmp unless cmp == 0

      compare_additions(addition, other.addition)
    end

    # Returns true if the version tokens are equivalent to zero
    # and the addition is also equivalent to zero.
    def is_zero?
      return false if compare_tokens(tokens, [0]) != 0

      return true if addition.nil?

      addition.is_zero?
    end

    private

    def compare_tokens(a, b) # rubocop:disable Naming/MethodParameterName
      max_idx = [a.size, b.size].max - 1
      (0..max_idx).each do |idx|
        cmp = compare_token_pair(a[idx], b[idx])
        return cmp unless cmp == 0
      end
      0
    end

    def compare_token_pair(a, b) # rubocop:disable Naming/MethodParameterName
      (a || 0) <=> (b || 0)
    end

    def compare_additions(a, b) # rubocop:disable Naming/MethodParameterName
      return 0 if a.nil? && b.nil?

      (a || empty_addition).<=>(b || empty_addition)
    end

    def empty_addition
      self.class.new([])
    end
  end
end