Class: Ukiryu::Definition::VersionResolver
- Inherits:
-
Object
- Object
- Ukiryu::Definition::VersionResolver
- Defined in:
- lib/ukiryu/definition/version_resolver.rb
Overview
Resolve semantic version constraints
This class handles semantic versioning constraints like:
-
“1.0” - exact version
-
“>= 1.0” - minimum version (inclusive)
-
“~> 1.2” - pessimistic version constraint
Defined Under Namespace
Classes: Constraint
Class Method Summary collapse
-
.compare_versions(v1, v2) ⇒ Integer
Compare two version strings.
-
.latest(versions) ⇒ String?
Get the latest version from a list.
-
.parse_constraint(constraint_string) ⇒ Array<Constraint>
Parse a version constraint string.
-
.parse_version(version_string) ⇒ Array<Integer>
Parse a version string into components.
-
.pessimistic_range(version) ⇒ Array<String>
Get the compatible version range for a pessimistic constraint.
-
.resolve(constraint, available_versions) ⇒ String?
Resolve the best matching version from available versions.
-
.satisfies?(version, constraint) ⇒ Boolean
Check if a version satisfies a constraint.
Class Method Details
.compare_versions(v1, v2) ⇒ Integer
Compare two version strings
149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/ukiryu/definition/version_resolver.rb', line 149 def self.compare_versions(v1, v2) parts1 = v1.is_a?(Array) ? v1 : parse_version(v1) parts2 = v2.is_a?(Array) ? v2 : parse_version(v2) max_length = [parts1.length, parts2.length].max max_length.times do |i| p1 = parts1[i] || 0 p2 = parts2[i] || 0 comparison = p1 <=> p2 return comparison unless comparison.zero? end 0 end |
.latest(versions) ⇒ String?
Get the latest version from a list
176 177 178 179 180 |
# File 'lib/ukiryu/definition/version_resolver.rb', line 176 def self.latest(versions) return nil if versions.nil? || versions.empty? versions.max_by { |v| parse_version(v) } end |
.parse_constraint(constraint_string) ⇒ Array<Constraint>
Parse a version constraint string
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/ukiryu/definition/version_resolver.rb', line 57 def self.parse_constraint(constraint_string) return [Constraint.exact(constraint_string)] unless constraint_string.match?(/[<>=~]/) constraints = [] # Split by comma for compound constraints constraint_string.split(',').map(&:strip).each do |part| case part when /\A~>(?:\s*(.+))?/ # Updated regex for ~> operator # Pessimistic version constraint version = ::Regexp.last_match(1) || '' constraints << Constraint.pessimistic(version.strip) when /\A>=\s*(.+)/ # Minimum version (inclusive) constraints << Constraint.min(::Regexp.last_match(1)) when /\A>\s*(.+)/ # Minimum version (exclusive) constraints << Constraint.new(:>, ::Regexp.last_match(1)) when /\A<=\s*(.+)/ # Maximum version (inclusive) constraints << Constraint.max(::Regexp.last_match(1)) when /\A<\s*(.+)/ # Maximum version (exclusive) constraints << Constraint.new(:<, ::Regexp.last_match(1)) when /\A==\s*(.+)/ # Exact version constraints << Constraint.exact(::Regexp.last_match(1)) else # Assume exact version constraints << Constraint.exact(part.strip) end end constraints end |
.parse_version(version_string) ⇒ Array<Integer>
Parse a version string into components
168 169 170 |
# File 'lib/ukiryu/definition/version_resolver.rb', line 168 def self.parse_version(version_string) version_string.to_s.split('.').map(&:to_i) end |
.pessimistic_range(version) ⇒ Array<String>
Get the compatible version range for a pessimistic constraint
186 187 188 189 190 191 |
# File 'lib/ukiryu/definition/version_resolver.rb', line 186 def self.pessimistic_range(version) parts = parse_version(version) min = version max = "#{parts[0...-1].join('.')}.#{parts[-1] + 1}" [min, max] end |
.resolve(constraint, available_versions) ⇒ String?
Resolve the best matching version from available versions
131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/ukiryu/definition/version_resolver.rb', line 131 def self.resolve(constraint, available_versions) return nil if available_versions.nil? || available_versions.empty? # Parse constraint constraints = parse_constraint(constraint) # Filter versions that satisfy the constraint matching = available_versions.select { |v| satisfies?(v, constraints) } # Return highest matching version matching.max_by { |v| parse_version(v) } end |
.satisfies?(version, constraint) ⇒ Boolean
Check if a version satisfies a constraint
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/ukiryu/definition/version_resolver.rb', line 98 def self.satisfies?(version, constraint) constraints = constraint.is_a?(Array) ? constraint : parse_constraint(constraint) v_parts = parse_version(version) constraints.all? do |c| case c.operator when :== v_parts == parse_version(c.version) when :>= compare_versions(v_parts, parse_version(c.version)) >= 0 when :> compare_versions(v_parts, parse_version(c.version)).positive? when :<= compare_versions(v_parts, parse_version(c.version)) <= 0 when :< compare_versions(v_parts, parse_version(c.version)).negative? when '~>'.to_sym # Pessimistic version constraint: >= x.y.z, < x.(y+1).0 base = parse_version(c.version) upper = base[0...-1] + [base[-1] + 1, 0] compare_versions(v_parts, base) >= 0 && compare_versions(v_parts, upper).negative? else false end end end |