Skip to content

Commit 2f55d6f

Browse files
committed
Make gitdir work with worktrees, respect core.hooksPath, etc
Since v2.9.0, Git knows about the config variable core.hookspath that allows overriding the path to the directory containing the Git hooks. Since v2.10.0, the `--git-path` option respects that config variable, too, so we may just as well use that command. Other paths inside `.git` are equally subject to differ from `<gitdir>/<path>`, i.e. inside worktrees, where _some_ paths live in the "gitdir" and some live in the "commondir" (i.e. the "gitdir" of the main worktree). For Git versions older than v2.5.0 (which was the first version to support the `--git-path` option for the `rev-parse` command), we simply fall back to the previous code. An original patch handled only the hooksPath setting, however, during the code submission it was deemed better to fix all call to the `gitdir` function. To avoid spawning a gazillion `git rev-parse --git-path` instances, we cache the returned paths, priming the cache upon startup in a single `git rev-parse invocation` with some paths (that have been determined via a typical startup and via grepping the source code for calls to the `gitdir` function). This fixes git-for-windows#1755 Initial-patch-by: Philipp Gortan <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 60c60b6 commit 2f55d6f

File tree

1 file changed

+58
-4
lines changed

1 file changed

+58
-4
lines changed

git-gui.sh

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ if {[tk windowingsystem] eq "aqua"} {
158158

159159
set _appname {Git Gui}
160160
set _gitdir {}
161+
array set _gitdir_cache {}
161162
set _gitworktree {}
162163
set _isbare {}
163164
set _gitexec {}
@@ -197,12 +198,59 @@ proc appname {} {
197198
return $_appname
198199
}
199200

201+
proc prime_gitdir_cache {} {
202+
global _gitdir _gitdir_cache
203+
204+
set gitdir_cmd [list git rev-parse --git-dir]
205+
206+
# `--git-path` is only supported since Git v2.5.0
207+
if {[package vcompare $::_git_version 2.5.0] >= 0} {
208+
# This list was generated from a typical startup as well as from
209+
# grepping through Git GUI's source code.
210+
set gitdir_keys [list \
211+
CHERRY_PICK_HEAD FETCH_HEAD GITGUI_BCK GITGUI_EDITMSG \
212+
GITGUI_MSG HEAD hooks hooks/prepare-commit-msg \
213+
index.lock info info/exclude logs MERGE_HEAD MERGE_MSG \
214+
MERGE_RR objects "objects/4\[0-1\]/*" \
215+
"objects/4\[0-3\]/*" objects/info \
216+
objects/info/alternates objects/pack packed-refs \
217+
PREPARE_COMMIT_MSG rebase-merge/head-name remotes \
218+
rr-cache rr-cache/MERGE_RR SQUASH_MSG \
219+
]
220+
221+
foreach key $gitdir_keys {
222+
lappend gitdir_cmd --git-path $key
223+
}
224+
}
225+
226+
set i -1
227+
foreach path [split [eval $gitdir_cmd] "\n"] {
228+
if {$i eq -1} {
229+
set _gitdir $path
230+
} else {
231+
set _gitdir_cache([lindex $gitdir_keys $i]) $path
232+
}
233+
incr i
234+
}
235+
}
236+
200237
proc gitdir {args} {
201-
global _gitdir
238+
global _gitdir _gitdir_cache
239+
202240
if {$args eq {}} {
203241
return $_gitdir
204242
}
205-
return [eval [list file join $_gitdir] $args]
243+
244+
set args [eval [list file join] $args]
245+
if {![info exists _gitdir_cache($args)]} {
246+
if {[package vcompare $::_git_version 2.5.0] >= 0} {
247+
set _gitdir_cache($args) [git rev-parse --git-path $args]
248+
} else {
249+
set _gitdir_cache($args) [file join $_gitdir $args]
250+
}
251+
}
252+
253+
return $_gitdir_cache($args)
206254
}
207255

208256
proc gitexec {args} {
@@ -1242,7 +1290,7 @@ if {[catch {
12421290
&& [catch {
12431291
# beware that from the .git dir this sets _gitdir to .
12441292
# and _prefix to the empty string
1245-
set _gitdir [git rev-parse --git-dir]
1293+
prime_gitdir_cache
12461294
set _prefix [git rev-parse --show-prefix]
12471295
} err]} {
12481296
load_config 1
@@ -1453,10 +1501,16 @@ proc rescan {after {honor_trustmtime 1}} {
14531501
global HEAD PARENT MERGE_HEAD commit_type
14541502
global ui_index ui_workdir ui_comm
14551503
global rescan_active file_states
1456-
global repo_config
1504+
global repo_config _gitdir_cache
14571505
14581506
if {$rescan_active > 0 || ![lock_index read]} return
14591507
1508+
# Only re-prime gitdir cache on a full rescan
1509+
if {$after ne "ui_ready"} {
1510+
array unset _gitdir_cache
1511+
prime_gitdir_cache
1512+
}
1513+
14601514
repository_state newType newHEAD newMERGE_HEAD
14611515
if {[string match amend* $commit_type]
14621516
&& $newType eq {normal}

0 commit comments

Comments
 (0)