mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Refactor and document Version
.
This commit is contained in:
parent
b14bc2857b
commit
c53f362476
@ -1019,7 +1019,7 @@ module Homebrew
|
||||
problem "missing version"
|
||||
elsif !version.detected_from_url?
|
||||
version_text = version
|
||||
version_url = Version.detect(url, specs)
|
||||
version_url = Version.detect(url, **specs)
|
||||
if version_url.to_s == version_text.to_s && version.instance_of?(Version)
|
||||
problem "version #{version_text} is redundant with version scanned from URL"
|
||||
end
|
||||
|
@ -468,7 +468,7 @@ module Homebrew
|
||||
unless version
|
||||
specs = {}
|
||||
specs[:tag] = tag if tag
|
||||
version = Version.detect(url, specs)
|
||||
version = Version.detect(url, **specs)
|
||||
end
|
||||
# if we haven't already found open requests, try for an exact match across closed requests
|
||||
GitHub.check_for_duplicate_pull_requests("#{formula.name} #{version}", tap_full_name, state: "closed", args: args)
|
||||
|
@ -34,7 +34,7 @@ module Homebrew
|
||||
@version = if @version
|
||||
Version.create(@version)
|
||||
else
|
||||
Version.detect(url, {})
|
||||
Version.detect(url)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -203,7 +203,7 @@ class Resource
|
||||
return Version::NULL if val.nil? && url.nil?
|
||||
|
||||
case val
|
||||
when nil then Version.detect(url, specs)
|
||||
when nil then Version.detect(url, **specs)
|
||||
when String then Version.create(val)
|
||||
when Version then val
|
||||
else
|
||||
|
@ -63,17 +63,19 @@ describe Version::NULL do
|
||||
end
|
||||
end
|
||||
|
||||
describe Version::NullToken do
|
||||
describe Version do
|
||||
describe "::NULL_TOKEN" do
|
||||
subject { described_class::NULL_TOKEN }
|
||||
|
||||
specify "#inspect" do
|
||||
expect(subject.inspect).to eq("#<Version::NullToken>")
|
||||
end
|
||||
|
||||
it "is equal to itself" do
|
||||
expect(subject).to be == described_class.new
|
||||
expect(subject).to be == described_class::NULL_TOKEN
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Version do
|
||||
specify "comparison" do
|
||||
expect(described_class.create("0.1")).to be == described_class.create("0.1.0")
|
||||
expect(described_class.create("0.1")).to be < described_class.create("0.2")
|
||||
@ -259,9 +261,17 @@ describe Version do
|
||||
end
|
||||
end
|
||||
|
||||
specify "#detected_from_url?" do
|
||||
expect(described_class.create("1.0")).not_to be_detected_from_url
|
||||
expect(Version::FromURL.new("1.0")).to be_detected_from_url
|
||||
describe "#detected_from_url?" do
|
||||
it "is false if created explicitly" do
|
||||
expect(described_class.new("1.0.0")).not_to be_detected_from_url
|
||||
end
|
||||
|
||||
it "is true if the version was detected from a URL" do
|
||||
version = described_class.detect("https://example.org/archive-1.0.0.tar.gz")
|
||||
|
||||
expect(version).to eq "1.0.0"
|
||||
expect(version).to be_detected_from_url
|
||||
end
|
||||
end
|
||||
|
||||
specify "#head?" do
|
||||
@ -363,9 +373,9 @@ describe Version do
|
||||
end
|
||||
|
||||
describe "::detect" do
|
||||
matcher :be_detected_from do |url, specs = {}|
|
||||
matcher :be_detected_from do |url, **specs|
|
||||
match do |expected|
|
||||
@detected = described_class.detect(url, specs)
|
||||
@detected = described_class.detect(url, **specs)
|
||||
@detected == expected
|
||||
end
|
||||
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
require "version/null"
|
||||
|
||||
# A formula's version.
|
||||
#
|
||||
# @api private
|
||||
class Version
|
||||
include Comparable
|
||||
|
||||
@ -9,6 +12,7 @@ class Version
|
||||
/#{"^" if full}#{Regexp.escape(name)}(@\d[\d.]*)?#{"$" if full}/
|
||||
end
|
||||
|
||||
# A part of a `Version`.
|
||||
class Token
|
||||
include Comparable
|
||||
|
||||
@ -67,9 +71,10 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
# A pseudo-token representing the absence of a token.
|
||||
class NullToken < Token
|
||||
def initialize(value = nil)
|
||||
super
|
||||
def initialize
|
||||
super(nil)
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
@ -95,9 +100,12 @@ class Version
|
||||
"#<#{self.class.name}>"
|
||||
end
|
||||
end
|
||||
private_constant :NullToken
|
||||
|
||||
# Represents the absence of a token.
|
||||
NULL_TOKEN = NullToken.new.freeze
|
||||
|
||||
# A token string.
|
||||
class StringToken < Token
|
||||
PATTERN = /[a-z]+/i.freeze
|
||||
|
||||
@ -119,6 +127,7 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
# A token consisting of only numbers.
|
||||
class NumericToken < Token
|
||||
PATTERN = /[0-9]+/i.freeze
|
||||
|
||||
@ -146,12 +155,14 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
# A token consisting of an alphabetic and a numeric part.
|
||||
class CompositeToken < StringToken
|
||||
def rev
|
||||
value[/[0-9]+/].to_i
|
||||
end
|
||||
end
|
||||
|
||||
# A token representing the part of a version designating it is an alpha release.
|
||||
class AlphaToken < CompositeToken
|
||||
PATTERN = /alpha[0-9]*|a[0-9]+/i.freeze
|
||||
|
||||
@ -169,6 +180,7 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
# A token representing the part of a version designating it is a beta release.
|
||||
class BetaToken < CompositeToken
|
||||
PATTERN = /beta[0-9]*|b[0-9]+/i.freeze
|
||||
|
||||
@ -188,6 +200,7 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
# A token representing the part of a version designating it is a pre-release.
|
||||
class PreToken < CompositeToken
|
||||
PATTERN = /pre[0-9]*/i.freeze
|
||||
|
||||
@ -207,6 +220,7 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
# A token representing the part of a version designating it is a release-candidate.
|
||||
class RCToken < CompositeToken
|
||||
PATTERN = /rc[0-9]*/i.freeze
|
||||
|
||||
@ -226,6 +240,7 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
# A token representing the part of a version designating it is a patch release.
|
||||
class PatchToken < CompositeToken
|
||||
PATTERN = /p[0-9]*/i.freeze
|
||||
|
||||
@ -252,19 +267,10 @@ class Version
|
||||
NumericToken::PATTERN,
|
||||
StringToken::PATTERN,
|
||||
).freeze
|
||||
private_constant :SCAN_PATTERN
|
||||
|
||||
class FromURL < Version
|
||||
def detected_from_url?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def self.detect(url, specs)
|
||||
if specs.key?(:tag)
|
||||
FromURL.parse(specs[:tag])
|
||||
else
|
||||
FromURL.parse(url)
|
||||
end
|
||||
def self.detect(url, **specs)
|
||||
parse(specs.fetch(:tag, url), detected_from_url: true)
|
||||
end
|
||||
|
||||
def self.create(val)
|
||||
@ -277,9 +283,9 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
def self.parse(spec)
|
||||
def self.parse(spec, detected_from_url: false)
|
||||
version = _parse(spec)
|
||||
version.nil? ? NULL : new(version)
|
||||
version.nil? ? NULL : new(version, detected_from_url: detected_from_url)
|
||||
end
|
||||
|
||||
def self._parse(spec)
|
||||
@ -424,14 +430,15 @@ class Version
|
||||
|
||||
private_class_method :_parse
|
||||
|
||||
def initialize(val)
|
||||
def initialize(val, detected_from_url: false)
|
||||
raise TypeError, "Version value must be a string; got a #{val.class} (#{val})" unless val.respond_to?(:to_str)
|
||||
|
||||
@version = val.to_str
|
||||
@detected_from_url = detected_from_url
|
||||
end
|
||||
|
||||
def detected_from_url?
|
||||
false
|
||||
@detected_from_url
|
||||
end
|
||||
|
||||
def head?
|
||||
@ -550,10 +557,13 @@ class Version
|
||||
end
|
||||
end
|
||||
|
||||
# A formula's [HEAD version](https://docs.brew.sh/Formula-Cookbook#unstable-versions-head).
|
||||
#
|
||||
# @api private
|
||||
class HeadVersion < Version
|
||||
attr_reader :commit
|
||||
|
||||
def initialize(val)
|
||||
def initialize(*)
|
||||
super
|
||||
@commit = @version[/^HEAD-(.+)$/, 1]
|
||||
end
|
||||
|
@ -1,6 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Version
|
||||
# Represents the absence of a version.
|
||||
NULL = Class.new do
|
||||
include Comparable
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user