Module: Vers::ComposerVersion

Extended by:
ComposerVersion
Included in:
ComposerVersion
Defined in:
lib/vers/composer_version.rb

Defined Under Namespace

Classes: Parsed

Constant Summary collapse

PATTERN =
/\Av?([0-9]+(?:\.[0-9]+){0,3})(?:[-._]?([a-z]+)(?:[.-]?([0-9]+(?:[.-][0-9]+)*))?)?(?:\+\S+)?\z/i
NUMERIC_BRANCH_PATTERN =
/\Av?\d+(?:\.\d+)*\.x-dev\z/i
STABILITIES =
{
  "dev" => 0,
  "a" => 1,
  "alpha" => 1,
  "b" => 2,
  "beta" => 2,
  "rc" => 3,
  "stable" => 4,
  "p" => 5,
  "pl" => 5,
  "patch" => 5
}.freeze

Instance Method Summary collapse

Instance Method Details

#branch?(value) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
63
# File 'lib/vers/composer_version.rb', line 60

def branch?(value)
  string = value.to_s.strip
  (string.downcase.start_with?("dev-") && string.length > 4) || string.match?(NUMERIC_BRANCH_PATTERN)
end

#compare(left, right) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/vers/composer_version.rb', line 26

def compare(left, right)
  parsed_left = parse(left)
  parsed_right = parse(right)
  left_branch = branch?(left)
  right_branch = branch?(right)

  return -1 if left_branch && !right_branch
  return 1 if !left_branch && right_branch
  return left.downcase <=> right.downcase unless parsed_left && parsed_right

  parsed_left.core.zip(parsed_right.core).each do |left_part, right_part|
    comparison = VersionComparison.compare_numbers(left_part, right_part)
    return comparison unless comparison.zero?
  end

  comparison = parsed_left.stability <=> parsed_right.stability
  return comparison unless comparison.zero?

  compare_numbers(parsed_left.number, parsed_right.number)
end

#compare_numbers(left, right) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/vers/composer_version.rb', line 105

def compare_numbers(left, right)
  left_parts = left.split(/[.-]/)
  right_parts = right.split(/[.-]/)

  [left_parts.length, right_parts.length].max.times do |index|
    comparison = VersionComparison.compare_numbers(left_parts[index], right_parts[index])
    return comparison unless comparison.zero?
  end

  0
end

#explicit_stability?(value) ⇒ Boolean

Returns:

  • (Boolean)


93
94
95
96
# File 'lib/vers/composer_version.rb', line 93

def explicit_stability?(value)
  match = PATTERN.match(value.to_s.strip.sub(/\Av(?=\d)/i, ""))
  match && !match[2].nil?
end

#normalize(value, implicit_stability: nil) ⇒ Object

Raises:

  • (ArgumentError)


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/vers/composer_version.rb', line 70

def normalize(value, implicit_stability: nil)
  string = value.to_s.strip
  return string if branch?(string)

  match = PATTERN.match(string.sub(/\Av(?=\d)/i, ""))
  raise ArgumentError, "Invalid Composer version: #{value}" unless match

  core = match[1].split(".").map { |part| VersionComparison.normalize_number(part) }
  core << "0" while core.length < 3
  qualifier = match[2]&.downcase || implicit_stability
  qualifier = {"a" => "alpha", "b" => "beta", "rc" => "RC", "p" => "patch", "pl" => "patch"}.fetch(qualifier, qualifier)
  return core.join(".") if qualifier.nil? || qualifier == "stable"

  "#{core.join(".")}-#{qualifier}#{match[3]}"
end

#parse(value) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/vers/composer_version.rb', line 47

def parse(value)
  match = PATTERN.match(value.to_s.strip)
  return nil unless match

  core = match[1].split(".")
  core << "0" while core.length < 4
  qualifier = match[2]&.downcase
  stability = qualifier ? STABILITIES[qualifier] : 4
  return nil unless stability

  Parsed.new(core.freeze, stability, match[3].to_s)
end

#prerelease?(value) ⇒ Boolean

Returns:

  • (Boolean)


98
99
100
101
102
103
# File 'lib/vers/composer_version.rb', line 98

def prerelease?(value)
  return true if branch?(value)

  parsed = parse(value)
  parsed && parsed.stability < STABILITIES.fetch("stable")
end

#release_parts(value) ⇒ Object



86
87
88
89
90
91
# File 'lib/vers/composer_version.rb', line 86

def release_parts(value)
  match = PATTERN.match(value.to_s.strip.sub(/\Av(?=\d)/i, ""))
  return nil unless match

  match[1].split(".")
end

#valid?(value) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
68
# File 'lib/vers/composer_version.rb', line 65

def valid?(value)
  string = value.to_s.strip
  !string.empty? && !string.match?(/[[:space:]]/) && (!parse(string).nil? || branch?(string))
end