Class: Dependabot::Cargo::Version

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

Constant Summary collapse

VERSION_PATTERN =
'[0-9]+(?>\.[0-9a-zA-Z]+)*' \
'(-[0-9A-Za-z-]+(\.[0-9a-zA-Z-]+)*)?' \
'(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?'
ANCHORED_VERSION_PATTERN =
/\A\s*(#{VERSION_PATTERN})?\s*\z/

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(version) ⇒ Version

Returns a new instance of Version.



23
24
25
26
27
28
# File 'lib/dependabot/cargo/version.rb', line 23

def initialize(version)
  @version_string = T.let(version.to_s, String)
  version = version.to_s.split("+").first if version.to_s.include?("+")

  super
end

Class Method Details

.cargo_pre_1_0_type(from_major, from_minor, from_patch, to_major, to_minor, to_patch) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/dependabot/cargo/version.rb', line 173

def self.cargo_pre_1_0_type(from_major, from_minor, from_patch, to_major, to_minor, to_patch)
  # Any major version increase is always major
  return "major" if to_major > from_major

  # For 0.0.z versions, any change is breaking
  return "major" if from_minor.zero? && (to_minor > from_minor || to_patch > from_patch)

  # For 0.y.z versions, minor changes are breaking
  return "major" if to_minor > from_minor

  # Only patch changes remain
  "patch"
end

.correct?(version) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
44
45
# File 'lib/dependabot/cargo/version.rb', line 41

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

  version.to_s.match?(ANCHORED_VERSION_PATTERN)
end

.extract_version_parts(from_v, to_v) ⇒ Object



136
137
138
139
140
141
142
# File 'lib/dependabot/cargo/version.rb', line 136

def self.extract_version_parts(from_v, to_v)
  from_parts = from_v.to_s.split(".").map(&:to_i)
  to_parts = to_v.to_s.split(".").map(&:to_i)

  [from_parts[0] || 0, from_parts[1] || 0, from_parts[2] || 0,
   to_parts[0] || 0, to_parts[1] || 0, to_parts[2] || 0]
end

.normalize_versions(from_version, to_version) ⇒ Object



129
130
131
132
133
# File 'lib/dependabot/cargo/version.rb', line 129

def self.normalize_versions(from_version, to_version)
  from_v = from_version.is_a?(String) ? T.cast(new(from_version), Dependabot::Cargo::Version) : from_version
  to_v = to_version.is_a?(String) ? T.cast(new(to_version), Dependabot::Cargo::Version) : to_version
  [from_v, to_v]
end

.standard_semver_type(from_major, from_minor, from_patch, to_major, to_minor, to_patch) ⇒ Object



155
156
157
158
159
160
161
# File 'lib/dependabot/cargo/version.rb', line 155

def self.standard_semver_type(from_major, from_minor, from_patch, to_major, to_minor, to_patch)
  return "major" if to_major > from_major
  return "minor" if to_minor > from_minor
  return "patch" if to_patch > from_patch

  "patch"
end

.update_type(from_version, to_version) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/dependabot/cargo/version.rb', line 108

def self.update_type(from_version, to_version)
  from_v, to_v = normalize_versions(from_version, to_version)
  from_major, from_minor, from_patch, to_major, to_minor, to_patch = extract_version_parts(from_v, to_v)

  # Standard semver for 1.0.0+ versions
  return standard_semver_type(from_major, from_minor, from_patch, to_major, to_minor, to_patch) if from_major >= 1

  # Cargo pre-1.0 semver rules
  cargo_pre_1_0_type(from_major, from_minor, from_patch, to_major, to_minor, to_patch)
rescue StandardError => e
  # Log the error but return a safe default
  Dependabot.logger.warn("Error in Cargo::Version.update_type: #{e.message}")
  "major" # Default to major for safety
end

Instance Method Details

#ignored_major_versionsObject



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/dependabot/cargo/version.rb', line 81

def ignored_major_versions
  parts = to_s.split(".")
  major = parts[0].to_i
  minor = parts[1].to_i

  # For 0.0.z versions, patch changes are breaking
  # So ignoring "major" means ignoring all >= 0.0.(z+1)
  if major.zero? && minor.zero?
    patch = parts[2].to_i
    lower_parts = [0, 0, patch + 1] + [lowest_prerelease_suffix]
    return [">= #{lower_parts.join('.')}"]
  end

  # For 0.y.z versions (y > 0), minor changes are breaking
  # So ignoring "major" means ignoring all >= 0.(y+1).0
  if major.zero?
    lower_parts = [0, minor + 1] + [lowest_prerelease_suffix]
    return [">= #{lower_parts.join('.')}"]
  end

  # For 1.y.z+ versions, use standard semantic versioning
  super
end

#ignored_minor_versionsObject



69
70
71
72
73
74
75
76
77
78
# File 'lib/dependabot/cargo/version.rb', line 69

def ignored_minor_versions
  parts = to_s.split(".")
  major = parts[0].to_i

  # For 0.y.z versions, minor changes are breaking, so treat as major
  return ignored_major_versions if major.zero?

  # For 1.y.z+ versions, use standard semantic versioning
  super
end

#ignored_patch_versionsObject



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/dependabot/cargo/version.rb', line 53

def ignored_patch_versions
  parts = to_s.split(".")
  major = parts[0].to_i
  minor = parts[1].to_i

  # For 0.0.z versions, patch changes are breaking, so treat as major
  return ignored_major_versions if major.zero? && minor.zero?

  # For 0.y.z versions, patch changes are compatible, use standard logic
  return super if major.zero?

  # For 1.y.z+ versions, use standard semantic versioning
  super
end

#inspectObject

:nodoc:



36
37
38
# File 'lib/dependabot/cargo/version.rb', line 36

def inspect # :nodoc:
  "#<#{self.class} #{@version_string}>"
end

#to_sObject



31
32
33
# File 'lib/dependabot/cargo/version.rb', line 31

def to_s
  @version_string
end