Skip to content

Commit f28c2bd

Browse files
author
James Couball
committed
Set and retrieve the path to the git binary used by this library
1 parent 29123fe commit f28c2bd

File tree

8 files changed

+514
-10
lines changed

8 files changed

+514
-10
lines changed

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# Ruby Git
1+
# RubyGit
22

33
**THIS PROJECT IS A WORK IN PROGRESS AND IS NOT USEFUL IN ITS CURRENT STATE**
44

55
[![Build Status](https://travis-ci.org/jcouball/ruby_git.svg?branch=main)](https://travis-ci.org/jcouball/ruby_git)
66
[![Maintainability](https://api.codeclimate.com/v1/badges/2d8d52a55d655b6a3def/maintainability)](https://codeclimate.com/github/jcouball/ruby_git/maintainability)
77

8-
Ruby Git is an object-oriented wrapper for the `git` command line tool for working with Worktrees
8+
RubyGit is an object-oriented wrapper for the `git` command line tool for working with Worktrees
99
and Repositories. It tries to make more sense out of the Git command line.
1010

1111
## Installation
@@ -26,6 +26,16 @@ Or install it directly from the command line:
2626

2727
## Usage
2828

29+
To configure RubyGit:
30+
31+
```Ruby
32+
RubyGit.git.path = '/usr/local/bin/git'
33+
34+
# Returns the user set path or searches for 'git' in ENV['PATH']
35+
RubyGit.git.path #=> '/usr/local/bin/git'
36+
RubyGit.git.version #=> [2,28,0]
37+
```
38+
2939
To work with an existing Worktree:
3040

3141
```Ruby

lib/ruby_git.rb

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
# frozen_string_literal: true
22

33
require 'ruby_git/version'
4+
require 'ruby_git/file_helpers'
5+
require 'ruby_git/git_binary'
46

7+
# RubyGit is an object-oriented wrapper for the `git` command line tool for
8+
# working with Worktrees and Repositories. It tries to make more sense out
9+
# of the Git command line.
10+
#
11+
# @api public
12+
#
513
module RubyGit
6-
class Error < StandardError; end
14+
# Return information about the git binary used by this library
15+
#
16+
# Use this object to set the path to the git binary to use or to see the
17+
# path being used.
18+
#
19+
# @example Setting the git binary path
20+
# RubyGit.git.path = '/usr/local/bin/git'
21+
#
22+
# @return [RubyGit::GitBinary]
23+
#
24+
def self.git
25+
(@git ||= RubyGit::GitBinary.new)
26+
end
727
end

lib/ruby_git/file_helpers.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# frozen_string_literal: true
2+
3+
module RubyGit
4+
# A namespace for several file utility methods that I wish were part of FileUtils.
5+
#
6+
# @api public
7+
#
8+
module FileHelpers
9+
# Cross platform way to find an executable file within a list of paths
10+
#
11+
# Works for both Linux/Unix and Windows.
12+
#
13+
# @example Searching over the PATH for a command
14+
# path = FileUtils.which('git')
15+
#
16+
# @example Overriding the default PATH
17+
# path = FileUtils.which('git', ['/usr/bin', '/usr/local/bin'])
18+
#
19+
# @param [String] cmd The basename of the executable file to search for
20+
# @param [Array<String>] paths The list of directories to search for basename in
21+
# @param [Array<String>] exts The list of extensions that indicate that a file is executable
22+
#
23+
# `exts` is for Windows. Other platforms should accept the default.
24+
#
25+
# @return [Pathname,nil] The path to the first executable file found on the path or
26+
# nil an executable file was not found.
27+
#
28+
def self.which(
29+
cmd,
30+
paths: ENV['PATH'].split(File::PATH_SEPARATOR),
31+
exts: (ENV['PATHEXT']&.split(';') || [''])
32+
)
33+
raise 'PATH is not set' unless ENV.keys.include?('PATH')
34+
35+
paths
36+
.product(exts)
37+
.map { |path, ext| Pathname.new(File.join(path, "#{cmd}#{ext}")) }
38+
.reject { |path| path.directory? || !path.executable? }
39+
.find { |exe_path| !exe_path.directory? && exe_path.executable? }
40+
end
41+
end
42+
end

lib/ruby_git/git_binary.rb

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# frozen_string_literal: true
2+
3+
module RubyGit
4+
# Sets and tracks the path to a git executable and reports the version
5+
#
6+
# @api public
7+
#
8+
class GitBinary
9+
# Return a new GitBinary object
10+
#
11+
# @example
12+
# GitBinary.new
13+
#
14+
def initialize
15+
@path = nil
16+
end
17+
18+
# Sets the path to the git binary
19+
#
20+
# The given path must point to an executable file or a RuntimeError is raised.
21+
#
22+
# @example Setting the path to the git binary
23+
# git.path = '/usr/local/bin/git'
24+
#
25+
# @param [String] path the path to a git executable
26+
#
27+
# @return [Pathname]
28+
#
29+
# @raise [RuntimeError] A RuntimeError is raised when the path is not to an
30+
# existing executable file.
31+
#
32+
def path=(path)
33+
new_path = Pathname.new(path)
34+
raise "'#{new_path}' does not exist." unless new_path.exist?
35+
raise "'#{new_path}' is not a file." unless new_path.file?
36+
raise "'#{new_path}' is not executable." unless new_path.executable?
37+
38+
@path = new_path
39+
end
40+
41+
# Retrieve the path to the git binary
42+
#
43+
# @example Get the git found on the PATH
44+
# git = RubyGit::GitBinary.new
45+
# path = git.path
46+
#
47+
# @return [Pathname] the path to the git binary
48+
#
49+
# @raise [RuntimeError] if path was not set via `path=` and either PATH is not set
50+
# or git was not found on the path.
51+
#
52+
def path
53+
@path || (@path = self.class.default_path)
54+
end
55+
56+
# Get the default path to to a git binary by searching the PATH
57+
#
58+
# @example Find the pathname to `super_git`
59+
# git = RubyGit::GitBinary.new
60+
# git.path = git.default_path(basename: 'super_git')
61+
#
62+
# @param [String] basename The basename of the git command
63+
#
64+
# @return [Pathname] the path to the git binary found in the path
65+
#
66+
# @raise [RuntimeError] if either PATH is not set or an executable file
67+
# basename was not found on the path.
68+
#
69+
def self.default_path(basename: 'git')
70+
RubyGit::FileHelpers.which(basename) || raise("Could not find '#{basename}' in the PATH.")
71+
end
72+
73+
# The version of git referred to by the path
74+
#
75+
# @example for version 2.28.0
76+
# git = RubyGit::GitBinary.new
77+
# puts git.version #=> [2,28,0]
78+
#
79+
# @return [Array<Integer>] an array of integers representing the version.
80+
#
81+
# @raise [RuntimeError] if path was not set via `path=` and either PATH is not set
82+
# or git was not found on the path.
83+
#
84+
def version
85+
output = `#{path} --version`
86+
version = output[/\d+\.\d+(\.\d+)+/]
87+
version.split('.').collect(&:to_i)
88+
end
89+
end
90+
end

lib/ruby_git/version.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

33
module RubyGit
4+
# The ruby_git gem version
5+
#
46
VERSION = '0.1.1'
57
end

0 commit comments

Comments
 (0)