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