Skip to content

Commit 10c2080

Browse files
committed
Add support for git-worktree
Main reason we didn't previously support work trees was because we had assumed that the `.git` directory was always located in the repository root. With separate work trees, this is not necessarily the case. Add support by using Git commands to fetch the location of the GIT_DIR instead of trying to determine it ourself.
1 parent ea3907a commit 10c2080

File tree

5 files changed

+26
-51
lines changed

5 files changed

+26
-51
lines changed

README.md

-7
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,6 @@ This project aims to support the following Ruby runtimes on both \*nix and Windo
5757

5858
* MRI 2.x
5959

60-
## Limitations
61-
62-
Overcommit does not currently support
63-
[`git-worktree`](https://git-scm.com/docs/git-worktree) (introduced in Git 2.5),
64-
but there is an [open issue](https://github.com/brigade/overcommit/issues/336)
65-
tracking progress on adding support.
66-
6760
### Dependencies
6861

6962
Some of the hooks have third-party dependencies. For example, to lint your

lib/overcommit/git_config.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def comment_character
1414
def hooks_path
1515
path = `git config --get core.hooksPath`.chomp
1616
return File.join(Overcommit::Utils.git_dir, 'hooks') if path.empty?
17-
File.absolute_path(path)
17+
File.absolute_path(path, Dir.pwd)
1818
end
1919
end
2020
end

lib/overcommit/utils.rb

+13-22
Original file line numberDiff line numberDiff line change
@@ -43,38 +43,29 @@ def script_path(script)
4343
def repo_root
4444
@repo_root ||=
4545
begin
46-
git_dir = Pathname.new(File.expand_path('.')).enum_for(:ascend).find do |path|
47-
File.exist?(File.join(path, '.git'))
46+
result = execute(%w[git rev-parse --show-toplevel])
47+
unless result.success?
48+
raise Overcommit::Exceptions::InvalidGitRepo,
49+
'Unable to determine location of GIT_DIR. ' \
50+
'Not a recognizable Git repository!'
4851
end
49-
50-
unless git_dir
51-
raise Overcommit::Exceptions::InvalidGitRepo, 'no .git directory found'
52-
end
53-
54-
git_dir.to_s
52+
result.stdout.chomp("\n")
5553
end
5654
end
5755

5856
# Returns an absolute path to the .git directory for a repo.
5957
#
60-
# @param repo_dir [String] root directory of git repo
6158
# @return [String]
62-
def git_dir(repo_dir = repo_root)
59+
def git_dir
6360
@git_dir ||=
6461
begin
65-
git_dir = File.expand_path('.git', repo_dir)
66-
67-
# .git could also be a file that contains the location of the git directory
68-
unless File.directory?(git_dir)
69-
git_dir = File.read(git_dir)[/^gitdir: (.*)$/, 1]
70-
71-
# Resolve relative paths
72-
unless git_dir.start_with?('/')
73-
git_dir = File.expand_path(git_dir, repo_dir)
74-
end
62+
result = execute(%w[git rev-parse --git-common-dir])
63+
unless result.success?
64+
raise Overcommit::Exceptions::InvalidGitRepo,
65+
'Unable to determine location of GIT_DIR. ' \
66+
'Not a recognizable Git repository!'
7567
end
76-
77-
git_dir
68+
File.expand_path(result.stdout.chomp("\n"), Dir.pwd)
7869
end
7970
end
8071

spec/overcommit/utils_spec.rb

+6-20
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,13 @@
5252
end
5353
end
5454

55-
context 'when .git is a file' do
56-
before do
57-
FileUtils.rm_rf('.git', secure: true)
58-
echo("gitdir: #{git_dir_path}", '.git')
59-
end
55+
context 'when .git directory is not located in the repository' do
56+
let(:git_dir) { Dir.mktmpdir }
57+
let(:repo_dir) { repo(git_dir: git_dir) }
6058

61-
context 'and is a relative path' do
62-
let(:git_dir_path) { '../.git' }
63-
64-
it 'returns the path contained in the file' do
65-
# realpath is so spec passes on Mac OS X
66-
subject.should == File.join(File.realpath(File.dirname(repo_dir)), '.git')
67-
end
68-
end
69-
70-
context 'and is an absolute path' do
71-
let(:git_dir_path) { '/some/arbitrary/path/.git' }
72-
73-
it 'returns the path contained in the file' do
74-
subject.should == git_dir_path
75-
end
59+
it 'returns the path of the external Git directory' do
60+
# realpath is so spec passes on Mac OS X
61+
subject.should == File.realpath(git_dir)
7662
end
7763
end
7864
end

spec/support/git_spec_helpers.rb

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ module GitSpecHelpers
1111
# @return [String] path of the repository
1212
def repo(options = {})
1313
directory('some-repo') do
14-
`git init --template="#{options[:template_dir]}"`
14+
create_cmd = %w[git init]
15+
create_cmd += ['--template', options[:template_dir]] if options[:template_dir]
16+
create_cmd += ['--separate-git-dir', options[:git_dir]] if options[:git_dir]
17+
18+
result = Overcommit::Utils.execute(create_cmd)
19+
raise "Unable to create repo: #{result.stderr}" unless result.success?
1520

1621
# Need to define user info since some CI contexts don't have defaults set
1722
`git config --local user.name "Overcommit Tester"`

0 commit comments

Comments
 (0)