module Versionomy::Formats

Version number format.

A format controls the parsing and unparsing of a version number. Any time a version number is parsed from a string, a format is provided to parse it. Similarly, every version number value references a format that is used to unparse it back into a string.

A format is always tied to a particular schema and knows how to parse only that schema's version numbers.

Under many circumstances, you should use the standard format, which can be retrieved by calling Versionomy::Format#standard. This format understands most common version numbers, including prerelease (e.g. alpha, beta, release candidate, etc.) forms and patchlevels.

You may also create your own formats, either by implementing the format contract (see Versionomy::Format::Base), or by using the Versionomy::Format::Delimiter tool, which can be used to construct parsers for many version number formats.

Format registry

Formats may be registered with Versionomy and given a name using the methods of this module. This allows version numbers to be serialized with their format. When a version number is serialized, its format name is written to the stream, along with the version number's string representation. When the version number is reconstructed, its format is looked up by name so versionomy can determine how to parse the string.

Format names are strings that may include letters, numerals, dashes, underscores, and periods. By convention, periods are used as namespace delimiters. Format names without a namespace (that is, with no periods) are considered reserved for standard versionomy formats. If you define your own format, you should use a name that includes a namespace (e.g. “mycompany.LibraryVersion”) to reduce the chance of name collisions.

You may register formats directly using the register method, or set it up to be autoloaded on demand. When a format is requested, if it has not been registered explicitly, Versionomy looks for a format definition file for that format. Such a file has the name of the format, with the “.rb” extension for ruby (e.g. “mycompany.LibraryVersion.rb”) and must be located in a directory in versionomy's format lookup path. By default, the directory containing versionomy's predefined formats (such as “standard”) is in this path. However, you may add your own directories using the Versionomy::Format.add_directory method. This lets you autoload your own formats. A format definition file itself must contain ruby code that defines the format and registers it using the correct name. See the files in the “lib/versionomy/format_definitions/” directory for examples.

Public Class Methods

add_directory(path_, high_priority_=false) click to toggle source

Add a directory to the format path.

The format path is an array of directory paths. These directories are searched for format definitions if a format name that has not been registered is requested.

If high_priority_ is set to true, the directory is added to the front of the lookup path; otherwise it is added to the back.

# File lib/versionomy/format.rb, line 115
def add_directory(path_, high_priority_=false)
  path_ = ::File.expand_path(path_)
  @mutex.synchronize do
    unless @directories.include?(path_)
      if high_priority_
        @directories.unshift(path_)
      else
        @directories.push(path_)
      end
    end
  end
end
canonical_name_for(format_, strict_=false) click to toggle source

Get the canonical name for the given format, as a string. This is the first name the format was registered under.

If the given format was never registered, and strict is set to true, raises Versionomy::Errors::UnknownFormatError. If strict is set to false, returns nil if the given format was never registered.

# File lib/versionomy/format.rb, line 200
def canonical_name_for(format_, strict_=false)
  name_ = @mutex.synchronize{ @formats_to_names[format_.object_id] }
  if name_.nil? && strict_
    raise Errors::UnknownFormatError
  end
  name_
end
get(name_, strict_=false) click to toggle source

Get the format with the given name.

If the given name has not been defined, attempts to autoload it from a format definition file. See the description of the Format module for details on this procedure.

If the given name still cannot be resolved, and strict is set to true, raises Versionomy::Errors::UnknownFormatError. If strict is set to false, returns nil if the given name cannot be resolved.

# File lib/versionomy/format.rb, line 139
def get(name_, strict_=false)
  name_ = _check_name(name_)
  format_ = @mutex.synchronize{ @names_to_formats[name_] }
  if format_.nil?
    # Attempt to find the format in the directory path
    dirs_ = @mutex.synchronize{ @directories.dup }
    dirs_.each do |dir_|
      path_ = "#{dir_}/#{name_}.rb"
      if ::File.readable?(path_)
        @load_mutex.synchronize{ ::Kernel.load(path_) }
      end
      format_ = @mutex.synchronize{ @names_to_formats[name_] }
      break unless format_.nil?
    end
  end
  if format_.nil? && strict_
    raise Errors::UnknownFormatError, name_
  end
  format_
end
register(name_, format_, silent_=false) click to toggle source

Register the given format under the given name.

Valid names may contain only letters, digits, underscores, dashes, and periods.

Raises Versionomy::Errors::FormatRedefinedError if the name has already been defined.

# File lib/versionomy/format.rb, line 178
def register(name_, format_, silent_=false)
  name_ = _check_name(name_)
  @mutex.synchronize do
    if @names_to_formats.include?(name_)
      unless silent_
        raise Errors::FormatRedefinedError, name_
      end
    else
      @names_to_formats[name_] = format_
      @formats_to_names[format_.object_id] = name_
    end
  end
end
registered?(name_) click to toggle source

Determines whether a format with the given name has been registered explicitly. Does not attempt to autoload the format.

# File lib/versionomy/format.rb, line 164
def registered?(name_)
  name_ = _check_name(name_)
  @mutex.synchronize{ @names_to_formats.include?(name_) }
end
rubygems() click to toggle source

Get the rubygems format. This is identical to calling get('rubygems').

The rubygems format is designed to be parse-compatible with the Gem::Version class used in rubygems. The only caveat is, whereas Gem::Version handles an arbitrary number of fields, this format is limited to a maximum of 8.

For the exact annotated definition of the rubygems schema and format, see the source code for Versionomy::Format::Rubygems#create.

# File lib/versionomy/format_definitions/rubygems.rb, line 53
def self.rubygems
  get('rubygems')
end
semver() click to toggle source

Get the semver format. This is identical to calling get('semver').

The semver format is designed to conform to the Semantic Versioning spec by Tom Preston-Warner. See semver.org/

For the exact annotated definition of the semver schema and format, see the source code for Versionomy::Format::Semver#create.

# File lib/versionomy/format_definitions/semver.rb, line 51
def self.semver
  get('semver')
end
standard() click to toggle source

Get the standard format. This is identical to calling get('standard').

The standard format is designed to handle most commonly-used version number forms, and allow parsing and comparison between them.

The standard schema is the heart of this format, providing a common structure for most version numbers.

It begins with four numeric fields: “major.minor.tiny.tiny2”.

The next field, :release_type, defines the remaining structure. The release type can be one of these symbolic values: :development, :alpha, :beta, :preview, :release_candidate, :release.

Depending on that value, additional fields become available. For example, the :alpha value enables the fields :alpha_version and :alpha_minor, which represent version number fields after the “a” alpha specifier. i.e. “2.1a30” has an alpha_version of 30. “2.1a30.2” also has an alpha_minor of 2. Similarly, the :beta release_type value enables the fields :beta_version and :beta_minor. A release_type of :release enables :patchlevel and :patchlevel_minor, to support versions like “1.8.7p72”.

The format itself is a delimiter-based format that understands a wide variety of string representations of this version schema. Examples of supported syntax include:

2.0
2.0.42.10
2.0b2
2.0rc15
2.0-5
2.0p5
2.0 Alpha 1
2.0a5.3
2.1.42.10-4.3

Because the standard format is based on Versionomy::Format::Delimiter, a number of parameters are available for parsing and unparsing. See the documentation for the delimiter class for more information.

Two of the fields have styles that can be set when unparsing. The :release_type field can be unparsed as either :long style (e.g. “1.0alpha2”) or :short style (e.g. “1.0a2”). The patchlevel field can be unparsed as either :number style (e.g. “2.1-1”) or :letter style (e.g. “2.1a”). Most fields can have their delimiter specified during unparsing as well.

For the exact annotated definition of the standard schema and format, see the source code for Versionomy::Format::Standard#create.

# File lib/versionomy/format_definitions/standard.rb, line 98
def self.standard
  get('standard')
end