https://github.com/JuliaLang/julia
Tip revision: 87a946f563ccbfc7be362b2b2c5ed541e05ffaf0 authored by Tim Holy on 08 September 2021, 20:53:14 UTC
Update base/indices.jl
Update base/indices.jl
Tip revision: 87a946f
version.jl
# This file is a part of Julia. License is MIT: https://julialang.org/license
## semantic version numbers (https://semver.org/)
const VerTuple = Tuple{Vararg{Union{UInt64,String}}}
const VInt = UInt32
"""
VersionNumber
Version number type which follow the specifications of
[semantic versioning](https://semver.org/), composed of major, minor
and patch numeric values, followed by pre-release and build
alpha-numeric annotations. See also [`@v_str`](@ref).
# Examples
```jldoctest
julia> VersionNumber("1.2.3")
v"1.2.3"
julia> VersionNumber("2.0.1-rc1")
v"2.0.1-rc1"
```
"""
struct VersionNumber
major::VInt
minor::VInt
patch::VInt
prerelease::VerTuple
build::VerTuple
function VersionNumber(major::VInt, minor::VInt, patch::VInt,
pre::VerTuple,
bld::VerTuple)
major >= 0 || throw(ArgumentError("invalid negative major version: $major"))
minor >= 0 || throw(ArgumentError("invalid negative minor version: $minor"))
patch >= 0 || throw(ArgumentError("invalid negative patch version: $patch"))
for ident in pre
if ident isa Integer
ident >= 0 || throw(ArgumentError("invalid negative pre-release identifier: $ident"))
else
if !occursin(r"^(?:|[0-9a-z-]*[a-z-][0-9a-z-]*)$"i, ident) ||
isempty(ident) && !(length(pre)==1 && isempty(bld))
throw(ArgumentError("invalid pre-release identifier: $(repr(ident))"))
end
end
end
for ident in bld
if ident isa Integer
ident >= 0 || throw(ArgumentError("invalid negative build identifier: $ident"))
else
if !occursin(r"^(?:|[0-9a-z-]*[a-z-][0-9a-z-]*)$"i, ident) ||
isempty(ident) && length(bld)!=1
throw(ArgumentError("invalid build identifier: $(repr(ident))"))
end
end
end
new(major, minor, patch, pre, bld)
end
end
VersionNumber(major::Integer, minor::Integer = 0, patch::Integer = 0,
pre::Tuple{Vararg{Union{Integer,AbstractString}}} = (),
bld::Tuple{Vararg{Union{Integer,AbstractString}}} = ()) =
VersionNumber(VInt(major), VInt(minor), VInt(patch),
map(x->x isa Integer ? UInt64(x) : String(x), pre),
map(x->x isa Integer ? UInt64(x) : String(x), bld))
VersionNumber(v::Tuple) = VersionNumber(v...)
function print(io::IO, v::VersionNumber)
v == typemax(VersionNumber) && return print(io, "∞")
print(io, v.major)
print(io, '.')
print(io, v.minor)
print(io, '.')
print(io, v.patch)
if !isempty(v.prerelease)
print(io, '-')
join(io, v.prerelease,'.')
end
if !isempty(v.build)
print(io, '+')
join(io, v.build,'.')
end
end
show(io::IO, v::VersionNumber) = print(io, "v\"", v, "\"")
Broadcast.broadcastable(v::VersionNumber) = Ref(v)
const VERSION_REGEX = r"^
v? # prefix (optional)
(\d+) # major (required)
(?:\.(\d+))? # minor (optional)
(?:\.(\d+))? # patch (optional)
(?:(-)| # pre-release (optional)
([a-z][0-9a-z-]*(?:\.[0-9a-z-]+)*|-(?:[0-9a-z-]+\.)*[0-9a-z-]+)?
(?:(\+)|
(?:\+((?:[0-9a-z-]+\.)*[0-9a-z-]+))? # build (optional)
))
$"ix
function split_idents(s::AbstractString)
idents = split(s, '.')
pidents = Union{UInt64,String}[occursin(r"^\d+$", ident) ? parse(UInt64, ident) : String(ident) for ident in idents]
return tuple(pidents...)::VerTuple
end
function tryparse(::Type{VersionNumber}, v::AbstractString)
v == "∞" && return typemax(VersionNumber)
m = match(VERSION_REGEX, String(v)::String)
m === nothing && return nothing
major, minor, patch, minus, prerl, plus, build = m.captures
major = parse(VInt, major::AbstractString)
minor = minor !== nothing ? parse(VInt, minor) : VInt(0)
patch = patch !== nothing ? parse(VInt, patch) : VInt(0)
if prerl !== nothing && !isempty(prerl) && prerl[1] == '-'
prerl = prerl[2:end] # strip leading '-'
end
prerl = prerl !== nothing ? split_idents(prerl) : minus !== nothing ? ("",) : ()
build = build !== nothing ? split_idents(build) : plus !== nothing ? ("",) : ()
return VersionNumber(major, minor, patch, prerl::VerTuple, build::VerTuple)
end
function parse(::Type{VersionNumber}, v::AbstractString)
ver = tryparse(VersionNumber, v)
ver === nothing && throw(ArgumentError("invalid version string: $v"))
return ver
end
VersionNumber(v::AbstractString) = parse(VersionNumber, v)
"""
@v_str
String macro used to parse a string to a [`VersionNumber`](@ref).
# Examples
```jldoctest
julia> v"1.2.3"
v"1.2.3"
julia> v"2.0.1-rc1"
v"2.0.1-rc1"
```
"""
macro v_str(v); VersionNumber(v); end
function typemax(::Type{VersionNumber})
∞ = typemax(VInt)
VersionNumber(∞, ∞, ∞, (), ("",))
end
typemin(::Type{VersionNumber}) = v"0-"
ident_cmp(a::Integer, b::Integer) = cmp(a, b)
ident_cmp(a::Integer, b::String ) = isempty(b) ? +1 : -1
ident_cmp(a::String, b::Integer) = isempty(a) ? -1 : +1
ident_cmp(a::String, b::String ) = cmp(a, b)
function ident_cmp(A::VerTuple, B::VerTuple)
for (a, b) in Iterators.Zip{Tuple{VerTuple,VerTuple}}((A, B))
c = ident_cmp(a, b)
(c != 0) && return c
end
length(A) < length(B) ? -1 :
length(B) < length(A) ? +1 : 0
end
function ==(a::VersionNumber, b::VersionNumber)
(a.major != b.major) && return false
(a.minor != b.minor) && return false
(a.patch != b.patch) && return false
(ident_cmp(a.prerelease, b.prerelease) != 0) && return false
(ident_cmp(a.build, b.build) != 0) && return false
return true
end
issupbuild(v::VersionNumber) = length(v.build)==1 && isempty(v.build[1])
function isless(a::VersionNumber, b::VersionNumber)
(a.major < b.major) && return true
(a.major > b.major) && return false
(a.minor < b.minor) && return true
(a.minor > b.minor) && return false
(a.patch < b.patch) && return true
(a.patch > b.patch) && return false
(!isempty(a.prerelease) && isempty(b.prerelease)) && return true
(isempty(a.prerelease) && !isempty(b.prerelease)) && return false
c = ident_cmp(a.prerelease,b.prerelease)
(c < 0) && return true
(c > 0) && return false
(!issupbuild(a) && issupbuild(b)) && return true
(issupbuild(a) && !issupbuild(b)) && return false
c = ident_cmp(a.build,b.build)
(c < 0) && return true
return false
end
function hash(v::VersionNumber, h::UInt)
h += 0x8ff4ffdb75f9fede % UInt
h = hash(v.major, h)
h = hash(v.minor, h)
h = hash(v.patch, h)
h = hash(v.prerelease, ~h)
h = hash(v.build, ~h)
end
lowerbound(v::VersionNumber) = VersionNumber(v.major, v.minor, v.patch, ("",), ())
upperbound(v::VersionNumber) = VersionNumber(v.major, v.minor, v.patch, (), ("",))
thispatch(v::VersionNumber) = VersionNumber(v.major, v.minor, v.patch)
thisminor(v::VersionNumber) = VersionNumber(v.major, v.minor, 0)
thismajor(v::VersionNumber) = VersionNumber(v.major, 0, 0)
nextpatch(v::VersionNumber) = v < thispatch(v) ? thispatch(v) : VersionNumber(v.major, v.minor, v.patch+1)
nextminor(v::VersionNumber) = v < thisminor(v) ? thisminor(v) : VersionNumber(v.major, v.minor+1, 0)
nextmajor(v::VersionNumber) = v < thismajor(v) ? thismajor(v) : VersionNumber(v.major+1, 0, 0)
## julia version info
"""
VERSION
A `VersionNumber` object describing which version of Julia is in use. For details see
[Version Number Literals](@ref man-version-number-literals).
"""
const VERSION = try
ver = VersionNumber(VERSION_STRING)
if !isempty(ver.prerelease) && !GIT_VERSION_INFO.tagged_commit
if GIT_VERSION_INFO.build_number >= 0
ver = VersionNumber(ver.major, ver.minor, ver.patch, (ver.prerelease..., GIT_VERSION_INFO.build_number), ver.build)
else
println("WARNING: no build number found for pre-release version")
ver = VersionNumber(ver.major, ver.minor, ver.patch, (ver.prerelease..., "unknown"), ver.build)
end
elseif GIT_VERSION_INFO.build_number > 0
println("WARNING: ignoring non-zero build number for VERSION")
end
ver
catch e
println("while creating Base.VERSION, ignoring error $e")
VersionNumber(0)
end
const libllvm_version = if endswith(libllvm_version_string, "jl")
# strip the "jl" SONAME suffix (JuliaLang/julia#33058)
# (LLVM does never report a prerelease version anyway)
VersionNumber(libllvm_version_string[1:end-2])
else
VersionNumber(libllvm_version_string)
end
libllvm_path() = ccall(:jl_get_libllvm, Any, ())
function banner(io::IO = stdout)
if GIT_VERSION_INFO.tagged_commit
commit_string = TAGGED_RELEASE_BANNER
elseif isempty(GIT_VERSION_INFO.commit)
commit_string = ""
else
days = Int(floor((ccall(:jl_clock_now, Float64, ()) - GIT_VERSION_INFO.fork_master_timestamp) / (60 * 60 * 24)))
days = max(0, days)
unit = days == 1 ? "day" : "days"
distance = GIT_VERSION_INFO.fork_master_distance
commit = GIT_VERSION_INFO.commit_short
if distance == 0
commit_string = "Commit $(commit) ($(days) $(unit) old master)"
else
branch = GIT_VERSION_INFO.branch
commit_string = "$(branch)/$(commit) (fork: $(distance) commits, $(days) $(unit))"
end
end
commit_date = isempty(Base.GIT_VERSION_INFO.date_string) ? "" : " ($(split(Base.GIT_VERSION_INFO.date_string)[1]))"
if get(io, :color, false)
c = text_colors
tx = c[:normal] # text
jl = c[:normal] # julia
d1 = c[:bold] * c[:blue] # first dot
d2 = c[:bold] * c[:red] # second dot
d3 = c[:bold] * c[:green] # third dot
d4 = c[:bold] * c[:magenta] # fourth dot
print(io,""" $(d3)_$(tx)
$(d1)_$(tx) $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx) | Documentation: https://docs.julialang.org
$(d1)(_)$(jl) | $(d2)(_)$(tx) $(d4)(_)$(tx) |
$(jl)_ _ _| |_ __ _$(tx) | Type \"?\" for help, \"]?\" for Pkg help.
$(jl)| | | | | | |/ _` |$(tx) |
$(jl)| | |_| | | | (_| |$(tx) | Version $(VERSION)$(commit_date)
$(jl)_/ |\\__'_|_|_|\\__'_|$(tx) | $(commit_string)
$(jl)|__/$(tx) |
""")
else
print(io,"""
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type \"?\" for help, \"]?\" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version $(VERSION)$(commit_date)
_/ |\\__'_|_|_|\\__'_| | $(commit_string)
|__/ |
""")
end
end