Class: Dependabot::Swift::Version

Inherits:
Version
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/swift/version.rb

Overview

Swift uses SemVer: strict validation in .correct?, section 11 pre-release precedence in #<=>. #initialize stays tolerant because GitCommitChecker builds unchecked versions (e.g. "0.0.0.0").

Constant Summary collapse

SEMVER_ANCHORED =

SEMVER_REGEX uses ^/$ line anchors; anchor to the whole string to reject multiline.

T.let(/\A#{SEMVER_REGEX.source}\z/x, Regexp)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(version) ⇒ Version

Returns a new instance of Version.



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
# File 'lib/dependabot/swift/version.rb', line 28

def initialize(version)
  @version_string = T.let(version.to_s.dup.freeze, String)

  stripped = version.to_s.delete_prefix("v")
  pre_part, plus, build = stripped.partition("+")
  # Strip only well-formed build metadata (SemVer rule 10 ignores it); a malformed "+…" tail is
  # kept so it stays distinct and sorts below the release instead of canonicalizing to it.
  build_ok = plus.empty? || build.match?(/\A[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*\z/)
  @semver = T.let((build_ok ? pre_part : stripped).freeze, String)

  base, suffix = pre_part.split("-", 2)
  # Split on "-" only when the core before it is numeric (else the hyphen is part of the tail).
  if suffix && !base.to_s.match?(/\A[0-9]+(?:\.[0-9]+)*\z/)
    base = pre_part
    suffix = nil
  end
  release, inferred = normalize_release(T.must(base))
  suffix ||= inferred
  # Fold a malformed build tail into the pre-release suffix so it stays distinct and orderable.
  suffix = [suffix, "+#{build}"].compact.join(".") unless build_ok
  @prerelease_suffix = T.let(suffix, T.nilable(String))
  @release_core = T.let(Gem::Version.new(release), Gem::Version)
  # Seed the superclass with a strict-SemVer form so tolerant tags never raise, while mixed
  # comparisons still see the pre-release state.
  super(semver_seed(release, @prerelease_suffix))
end

Class Method Details

.correct?(version) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
23
24
25
# File 'lib/dependabot/swift/version.rb', line 20

def self.correct?(version)
  return false if version.nil?

  # Strict SemVer only: rejects "1.0.0.alpha", "0.0.0.0", "01.2.3" and multiline input.
  version.to_s.delete_prefix("v").match?(SEMVER_ANCHORED)
end

Instance Method Details

#<=>(other) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/dependabot/swift/version.rb', line 113

def <=>(other)
  return nil if other.nil?

  resolved = coerce_operand(other)
  return nil if resolved.nil?

  # Compare release cores directly (not via super, whose seeded state uses RubyGems
  # pre-release ordering) so section 11 governs the pre-release tiebreak.
  release_cmp = release_core <=> resolved.release_core
  return release_cmp unless release_cmp&.zero?

  compare_semver_prerelease(@prerelease_suffix, resolved.prerelease_suffix)
rescue ArgumentError
  nil
end

#==(other) ⇒ Object



107
108
109
110
# File 'lib/dependabot/swift/version.rb', line 107

def ==(other)
  cmp = self <=> other
  !cmp.nil? && cmp.zero?
end

#bumpObject



66
67
68
69
# File 'lib/dependabot/swift/version.rb', line 66

def bump
  # Bump the full-precision release core so "~>" bounds ignore the padded 3-segment seed.
  @release_core.bump
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


95
96
97
98
99
# File 'lib/dependabot/swift/version.rb', line 95

def eql?(other)
  return false unless other.is_a?(Version)

  to_semver == other.to_semver
end

#hashObject



102
103
104
# File 'lib/dependabot/swift/version.rb', line 102

def hash
  to_semver.hash
end

#ignored_major_versionsObject



89
90
91
92
# File 'lib/dependabot/swift/version.rb', line 89

def ignored_major_versions
  major = T.must(to_semver.split(".").first).to_i
  [">= #{major + 1}.0.0-0"]
end

#ignored_minor_versionsObject



80
81
82
83
84
85
# File 'lib/dependabot/swift/version.rb', line 80

def ignored_minor_versions
  parts = to_semver.split(".")
  major = parts[0].to_i
  minor = parts.fetch(1, 0).to_i
  [">= #{major}.#{minor + 1}.0-0, < #{major + 1}.0.0-0"]
end

#prerelease?Boolean

Returns:

  • (Boolean)


72
73
74
75
76
# File 'lib/dependabot/swift/version.rb', line 72

def prerelease?
  return true unless @prerelease_suffix.nil?

  super
end

#to_sObject



56
57
58
# File 'lib/dependabot/swift/version.rb', line 56

def to_s
  @version_string
end

#to_semverObject



61
62
63
# File 'lib/dependabot/swift/version.rb', line 61

def to_semver
  @semver
end