main-branch/ruby_git

View on GitHub
lib/ruby_git/git_binary.rb

Summary

Maintainability
A
25 mins
Test Coverage
A
100%
# frozen_string_literal: true

module RubyGit
  # Sets and tracks the path to a git executable and reports the version
  #
  # @api public
  #
  class GitBinary
    # Return a new GitBinary object
    #
    # @example
    #   GitBinary.new
    #
    def initialize(path = nil)
      @path = Pathname.new(path) unless path.nil?
    end

    # Sets the path to the git binary
    #
    # The given path must point to an executable file or a RuntimeError is raised.
    #
    # @example Setting the path to the git binary
    #   git.path = '/usr/local/bin/git'
    #
    # @param [String] path the path to a git executable
    #
    # @return [Pathname]
    #
    # @raise [RuntimeError] A RuntimeError is raised when the path does not refer
    #   to an existing executable file.
    #
    def path=(path)
      new_path = Pathname.new(path)
      raise "'#{new_path}' does not exist." unless new_path.exist?
      raise "'#{new_path}' is not a file." unless new_path.file?
      raise "'#{new_path}' is not executable." unless new_path.executable?

      @path = new_path
    end

    # Retrieve the path to the git binary
    #
    # @example Get the git found on the PATH
    #   git = RubyGit::GitBinary.new
    #   git.path
    #    => #<Pathname:/usr/bin/git>
    #
    # @return [Pathname] the path to the git binary
    #
    # @raise [RuntimeError] if path was not set via `path=` and either PATH is not set
    #   or git was not found on the path.
    #
    def path
      @path || (@path = self.class.default_path)
    end

    # Get the default path to to a git binary by searching the PATH
    #
    # @example Find the pathname to `super_git`
    #   git = RubyGit::GitBinary.new
    #   git.default_path(basename: 'super_git')
    #    => #<Pathname:/usr/bin/super_git>
    #
    # @param [String] basename The basename of the git command
    #
    # @return [Pathname] the path to the git binary found in the path
    #
    # @raise [RuntimeError] if either PATH is not set or an executable file
    #   `basename` was not found on the path.
    #
    def self.default_path(basename: 'git', path: ENV['PATH'], path_ext: ENV['PATHEXT'])
      RubyGit::FileHelpers.which(basename, path: path, path_ext: path_ext) ||
        raise("Could not find '#{basename}' in the PATH.")
    end

    # The version of git referred to by the path
    #
    # @example for version 2.28.0
    #   git = RubyGit::GitBinary.new
    #   git.version
    #    => [2, 28, 0]
    #
    # @return [Array<Integer>] an array of integers representing the version.
    #
    # @raise [RuntimeError] if path was not set via `path=` and either PATH is not set
    #   or git was not found on the path.
    #
    def version
      output = `#{path} --version`
      version = output[/\d+\.\d+(\.\d+)+/]
      version.split('.').collect(&:to_i)
    end

    # Return the path as a string
    #
    # @example
    #   git = RubyGit::GitBinary.new('/usr/bin/git')
    #   git.to_s
    #    => '/usr/bin/git'
    #
    # @return [String] the path to the binary
    #
    # @raise [RuntimeError] if path was not set via `path=` and either PATH is not set
    #   or git was not found on the path.
    #
    def to_s
      path.to_s
    end
  end
end