require_relative './version/auto' require_relative './version/bump' require_relative './version/comparable' require_relative './version/scm' require_relative './version/git' module Builderator module Control ## # Version management tools # # Initial version boosted shamelessly from # https://github.com/RiotGamesMinions/thor-scmversion ## class Version FORMAT = /(?\d+)\.(?\d+)\.(?\d+)(?-(?[A-Za-z0-9]+)\.(?\d+))?(?:\+build\.(?\d+))?$/ DEFAULT_PRERELEASE_NAME = 'alpha'.freeze ## Order of precedence for release types RELEASE_TYPES = { 'major' => 0, 'major-prerelease' => 5, 'minor' => 10, 'minor-prerelease' => 15, 'patch' => 20, 'patch-prerelease' => 25, 'release' => 30, 'prerelease' => 35, 'build' => 40 } class << self def current @current ||= SCM.tags.last if @current.nil? && Util.relative_path('VERSION').exist? @current = Version.from_string(Util.relative_path('VERSION').read) end if @current.nil? fail 'No current version found! Create a VERSION file or set a version tag in your SCM.' end @current end def set_config_version Config.defaults.version = current.to_s Config.recompile end def write current.write end ## # Alias `bump` to the current version ## def bump(type = nil, prerelease_name = nil) @current = current.clone current.bump(type, prerelease_name) SCM.tags << current current end ## Parse a SemVer string into a Version def from_string(arg, options = {}) matchdata = arg.match(FORMAT) return nil if matchdata.nil? new(matchdata[:major], matchdata[:minor], matchdata[:patch], matchdata[:build], options).tap do |version| version.is_prerelease = !matchdata[:prerelease].nil? if version.is_prerelease version.prerelease_name = matchdata[:prerelease_name] version.prerelease_iteration = matchdata[:prerelease_iteration].to_i end end end end def initialize(major, minor, patch, build = nil, **options) @major = major.to_i @minor = minor.to_i @patch = patch.to_i @build = build.to_i unless build.nil? @ref = options[:ref] end include Auto include Bump include Comparable attr_accessor :ref attr_accessor :major attr_accessor :minor attr_accessor :patch attr_accessor :is_prerelease attr_accessor :prerelease_name attr_accessor :prerelease_iteration attr_accessor :build ## Create or bump a new prerelease train def prerelease(name = nil) self.build = nil ## Reset the build counter ## Increment current prerelease train if is_prerelease && (name.nil? || name == prerelease_name) self.prerelease_iteration += 1 return self end ## New prerelease train self.is_prerelease = true self.prerelease_name = name.nil? ? DEFAULT_PRERELEASE_NAME : name self.prerelease_iteration = 0 self end def write Util.relative_path('VERSION').write(to_s) end def to_s string = [major, minor, patch].join('.') string << "-#{prerelease_name}.#{prerelease_iteration}" if is_prerelease string << "+build.#{build}" unless build.nil? string end end end end