Skip to content

Commit 70565e3

Browse files
committed
Add Git.binary_version to return the version of the git command line
1 parent f5299a9 commit 70565e3

File tree

4 files changed

+142
-3
lines changed

4 files changed

+142
-3
lines changed

CONTRIBUTING.md

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# @title How To Contribute
44
-->
55

6+
# Contributing to the git gem
7+
8+
* [Summary](#summary)
69
* [How to contribute](#how-to-contribute)
710
* [How to report an issue or request a feature](#how-to-report-an-issue-or-request-a-feature)
811
* [How to submit a code or documentation change](#how-to-submit-a-code-or-documentation-change)
@@ -19,9 +22,9 @@
1922
* [Continuous integration](#continuous-integration)
2023
* [Documentation](#documentation)
2124
* [Licensing](#licensing)
25+
* [Building a specific version of the git command-line](#building-a-specific-version-of-the-git-command-line)
2226

23-
24-
# Contributing to the git gem
27+
## Summary
2528

2629
Thank you for your interest in contributing to the `ruby-git` project.
2730

@@ -172,6 +175,9 @@ $ bin/test test_object test_archive
172175

173176
# run all unit tests:
174177
$ bin/test
178+
179+
# run unit tests with a different version of the git command line:
180+
$ GIT_PATH=/Users/james/Downloads/git-2.30.2/bin-wrappers bin/test
175181
```
176182

177183
### Continuous integration
@@ -190,4 +196,58 @@ New and updated public-facing features should be documented in the project's [RE
190196

191197
`ruby-git` uses [the MIT license](https://choosealicense.com/licenses/mit/) as declared in the [LICENSE](LICENSE) file.
192198

193-
Licensing is critical to open-source projects as it ensures the software remains available under the terms desired by the author.
199+
Licensing is critical to open-source projects as it ensures the software remains available under the terms desired by the author.
200+
201+
## Building a specific version of the git command-line
202+
203+
For testing, it is helpful to be able to build and use a specific version of the git
204+
command-line with the git gem.
205+
206+
Instructions to do this can be found on the page [How to install
207+
Git](https://www.atlassian.com/git/tutorials/install-git) from Atlassian.
208+
209+
I have successfully used the instructions in the section "Build Git from source on OS
210+
X" on MacOS 15. I have copied the following instructions from the Atlassian page.
211+
212+
1. From your terminal install XCode's Command Line Tools:
213+
214+
```shell
215+
xcode-select --install
216+
```
217+
218+
2. Install [Homebrew](http://brew.sh/)
219+
220+
3. Using Homebrew, install openssl:
221+
222+
```shell
223+
brew install openssl
224+
```
225+
226+
4. Download the source tarball for the desired version from
227+
[here](https://mirrors.edge.kernel.org/pub/software/scm/git/) and extract it
228+
229+
5. Build Git run make with the following command:
230+
231+
```shell
232+
NO_GETTEXT=1 make CFLAGS="-I/usr/local/opt/openssl/include" LDFLAGS="-L/usr/local/opt/openssl/lib"
233+
```
234+
235+
6. The newly built git command will be found at `bin-wrappers/git`
236+
237+
7. Use the new git command-line version
238+
239+
Configure the git gem to use the newly built version:
240+
241+
```ruby
242+
require 'git'
243+
# set the binary path
244+
Git.configure { |config| config.binary_path = '/Users/james/Downloads/git-2.30.2/bin-wrappers/git' }
245+
# validate the version
246+
assert_equal([2, 30, 2], Git.binary_version)
247+
```
248+
249+
or run tests using the newly built version:
250+
251+
```shell
252+
GIT_PATH=/Users/james/Downloads/git-2.30.2/bin-wrappers bin/test
253+
```

lib/git.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,15 @@ def self.ls_remote(location = nil, options = {})
381381
def self.open(working_dir, options = {})
382382
Base.open(working_dir, options)
383383
end
384+
385+
# Return the version of the git binary
386+
#
387+
# @example
388+
# Git.binary_version # => [2, 46, 0]
389+
#
390+
# @return [Array<Integer>] the version of the git binary
391+
#
392+
def self.binary_version(binary_path = Git::Base.config.binary_path)
393+
Base.binary_version(binary_path)
394+
end
384395
end

lib/git/base.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ def self.config
3636
@@config ||= Config.new
3737
end
3838

39+
def self.binary_version(binary_path)
40+
git_cmd = "#{binary_path} -c core.quotePath=true -c color.ui=false version 2>&1"
41+
result, status = Open3.capture2(git_cmd)
42+
result = result.chomp
43+
44+
if status.success?
45+
version = result[/\d+(\.\d+)+/]
46+
version_parts = version.split('.').collect { |i| i.to_i }
47+
version_parts.fill(0, version_parts.length...3)
48+
else
49+
raise RuntimeError, "Failed to get git version: #{status}\n#{result}"
50+
end
51+
end
52+
3953
# (see Git.init)
4054
def self.init(directory = '.', options = {})
4155
normalize_paths(options, default_working_directory: directory, default_repository: directory, bare: options[:bare])
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
require 'test_helper'
2+
3+
class TestGitBinaryVersion < Test::Unit::TestCase
4+
def windows_mocked_git_binary = <<~GIT_SCRIPT
5+
@echo off
6+
# Loop through the arguments and check for the version command
7+
for %%a in (%*) do (
8+
if "%%a" == "version" (
9+
echo git version 1.2.3
10+
exit /b 0
11+
)
12+
)
13+
exit /b 1
14+
GIT_SCRIPT
15+
16+
def linux_mocked_git_binary = <<~GIT_SCRIPT
17+
#!/bin/sh
18+
# Loop through the arguments and check for the version command
19+
for arg in "$@"; do
20+
if [ "$arg" = "version" ]; then
21+
echo "git version 1.2.3"
22+
exit 0
23+
fi
24+
done
25+
exit 1
26+
GIT_SCRIPT
27+
28+
def test_binary_version_windows
29+
omit('Only implemented for Windows') unless windows_platform?
30+
31+
in_temp_dir do |path|
32+
git_binary_path = File.join(path, 'my_git.bat')
33+
File.write(git_binary_path, windows_mocked_git_binary)
34+
assert_equal([1, 2, 3], Git.binary_version(git_binary_path))
35+
end
36+
end
37+
38+
def test_binary_version_linux
39+
omit('Only implemented for Linux') if windows_platform?
40+
41+
in_temp_dir do |path|
42+
git_binary_path = File.join(path, 'my_git.bat')
43+
File.write(git_binary_path, linux_mocked_git_binary)
44+
File.chmod(0755, git_binary_path)
45+
assert_equal([1, 2, 3], Git.binary_version(git_binary_path))
46+
end
47+
end
48+
49+
def test_binary_version_bad_binary_path
50+
assert_raise RuntimeError do
51+
Git.binary_version('/path/to/nonexistent/git')
52+
end
53+
end
54+
end

0 commit comments

Comments
 (0)