class QB::Package::Version

Constants

IDENTIFIER_SEPARATOR

What separates identifiers (the base undivided values).

@return [String]

MIXED_SEGMENT
NAME_SEGMENT
NUMBER_IDENTIFIER_RE

Pattern to match string identifiers that are version “numlets” (the non-negative integer number part of version “numbers”).

@return [Regexp]

NUMBER_SEGMENT
POSSIBLE_VERSION_RE

Reasonably simple regular expression to extract things that might be versions from strings.

Intended for use on reasonably short strings like `git tag` output or what-not… probably not well suited for sifting through mountains of text.

Structure:

  1. The major version number, matched by a digit `1-9` followed by any number of digits.

  2. A separator to the next segment, which is:

    1. `.` separating to the minor version number

    2. `-` separating to the prerelease

    3. `+` separating to the build

  3. One or more of `a-z`, `A-Z`, `0-9`, `.`, `-`, `_`, `+`

  4. Ends with one of those that is not `.`, `_` or `+`, so `a-z`, `A-Z`, `0-9`.

This will match many strings that are not versions, but it should not miss any that are. It cold obviously be refined and improve to reduce false positives at the cost of additional complexity, but I wanted to start simple and complicate it as needed.

@return [Regexp]

Public Class Methods

extract(string) click to toggle source

Extract version number from a string.

@param [String] string

String containing versions.

@return [Array<QB::Package::Version]

Any versions extracted from the string.
# File lib/qb/package/version.rb, line 285
def self.extract string
  string.scan( POSSIBLE_VERSION_RE ).map { |possible_version_string|
    begin
      from possible_version_string
    rescue
      nil
    end
  }.compact
end
from(object) click to toggle source

Utilities


# File lib/qb/package/version.rb, line 251
def self.from object
  QB::Package::Version::From.object object
end
from_string(string) click to toggle source

@depreciated Use {.from} instead.

# File lib/qb/package/version.rb, line 258
def self.from_string string
  QB::Package::Version::From.string string
end
to_time_segment(time) click to toggle source

Time formatted to be stuck in a version segment per [Semver][] spec. We also strip out '-' to avoid possible parsing weirdness.

[Semver]: semver.org/

@return [String]

# File lib/qb/package/version.rb, line 272
def self.to_time_segment time
  time.utc.iso8601.gsub /[^0-9A-Za-z]/, ''
end

Public Instance Methods

<=>(other) click to toggle source
# File lib/qb/package/version.rb, line 480
def <=> other
  to_a <=> other.to_a
end
==(other) click to toggle source

Test for equality.

Compares classes then {QB::Package::Version#to_a} results.

@param [Object] other

Object to compare to self.

@return [Boolean]

True if self and other are considered equal.
# File lib/qb/package/version.rb, line 474
def == other
  other.class == self.class &&
  other.to_a == self.to_a
end
build?() click to toggle source

@return [Boolean]

 True if any build segments are present (stuff after '+' character
 in SemVer / "NPM" format). Tests if {@build} is empty.

 As of writing, we don't have a way to convey build segments in
"Gem" version format, so this will always be false when loading a
 Gem version.
# File lib/qb/package/version.rb, line 329
def build?
  !build.empty?
end
build_commit() click to toggle source

@todo Document commit method.

@param [type] arg_name

@todo Add name param description.

@return [return_type]

@todo Document return value.
# File lib/qb/package/version.rb, line 389
def build_commit
  if build?
    build.find { |seg| seg =~ /[0-9a-f]{7}/ }
  end
end
build_dirty?() click to toggle source

Is the build “dirty”?

@return [Boolean]

# File lib/qb/package/version.rb, line 338
def build_dirty?
  if build?
    build.any? { |seg| seg.is_a?( String ) && seg.include?( 'dirty' ) }
  end
end
Also aliased as: dirty?
build_version(*build, branch: nil, ref: nil, time: nil, dirty: nil) click to toggle source

Return a new {QB::Package::Version} with build information added.

@return [QB::Package::Version]

# File lib/qb/package/version.rb, line 429
def build_version *build, branch: nil, ref: nil, time: nil, dirty: nil
  build.map! &:to_s
  
  repo_segments = [
    branch,
    ref,
    ('dirty' if dirty),
    (self.class.to_time_segment(time) if dirty && time),
  ].compact
  
  if build.empty? && repo_segments.empty?
    raise ArgumentError,
          "Need to provide at least one arg: build, branch, ref, dirty."
  end
  
  unless repo_segments.empty?
    build = [*build, repo_segments.join( '-' )]
  end
  
  merge raw: nil, build: build
end
dirty?()
Alias for: build_dirty?
docker_tag() click to toggle source

Docker image tag for the version.

See {QB::Util::DockerMixin::ClassMethods#to_docker_tag}.

@return [String]

# File lib/qb/package/version.rb, line 402
def docker_tag
  self.class.to_docker_tag semver
end
eql?(other) click to toggle source
# File lib/qb/package/version.rb, line 521
def eql? other
  self == other && self.hash == other.hash
end
hash() click to toggle source
# File lib/qb/package/version.rb, line 516
def hash
  to_a.hash
end
level?() click to toggle source
# File lib/qb/package/version.rb, line 347
def level?
  is_a? QB::Package::Version::Leveled
end
normalized()
Alias for: semver
prerelease?() click to toggle source

@return [Boolean]

True if any prerelease segments are present (stuff after '-' in
SemVer / "NPM" format, or the first string segment and anything
following it in "Gem" format). Tests if {@prerelease} is not
empty.
# File lib/qb/package/version.rb, line 316
def prerelease?
  !prerelease.empty?
end
prerelease_version() click to toggle source

@return [QB::Package::Version]

A new {QB::Package::Version} created from {#release} and
{#prerelease} data, but without any build information.
# File lib/qb/package/version.rb, line 456
def prerelease_version
  merge raw: nil, build: []
end
release() click to toggle source

Derived Properties


# File lib/qb/package/version.rb, line 355
def release
  [major, minor, patch, *revision].join '.'
end
release?() click to toggle source

@return [Boolean]

True if this version is a release (no prerelease or build values).
# File lib/qb/package/version.rb, line 305
def release?
  prerelease.empty? && build.empty?
end
release_version() click to toggle source

@return [QB::Package::Version]

A new {QB::Package::Version} created from {#release}. Even if `self`
*is* a release version already, still returns a new instance.
# File lib/qb/package/version.rb, line 418
def release_version
  self.class.from release
end
semver() click to toggle source

@return [String]

The Semver version string
(`Major.minor.patch-prerelease+build` format).
# File lib/qb/package/version.rb, line 364
def semver
  result = release
  
  unless prerelease.empty?
    result += "-#{ prerelease.join '.' }"
  end
  
  unless build.empty?
    result += "+#{ build.join '.' }"
  end
  
  result
end
Also aliased as: normalized
to_a() click to toggle source

Return array of the version elements in order from greatest to least precedence.

This is considered the representative structure for the object's data, from which all other values are dependently derived, and is used in {#==}, {#hash} and {#eql?}.

@example

version = QB::Package::Version.from "0.1.2-rc.10+master.0ab1c3d"

version.to_a
# => [0, 1, 2, ['rc', 10], ['master', '0ab1c3d']]

QB::Package::Version.from( '1' ).to_a
# => [1, nil, nil, [], []]

@return [Array]

# File lib/qb/package/version.rb, line 504
def to_a
  [
    major,
    minor,
    patch,
    revision,
    prerelease,
    build,
  ]
end
to_s() click to toggle source
# File lib/qb/package/version.rb, line 526
def to_s
  "#<QB::Package::Version semver=#{ semver } raw=#{ @raw }>"
end