git-gui: use rev-parse exclusively to find a repository

git-gui attempts to use env(GIT_DIR) directly as the git repository, accepting GIT_DIR if it is a directory. Only if that fails is git rev-parse used to discover the repository. But, this avoids all of git-core's validity checking on a repository, thus possibly deferring an error to a later step, possibly unexpected. Repository validation should be part of initial setup so that later processing does not need error trapping for configuration errors. Let's just invoke rev-parse so all error checking is done. While here, let's cleanup the error handling. Stop if an error occurs and the user set GIT_DIR or GIT_WORK_TREE. Use of either or both of those variables is supported by git, but their use also means the user has taken responsibility that they are correct, so a failure is something the user must address. Otherwise on error, continue the existing behavior and show the repository picker. But, let's move the possible invocation of repository_chooser::pick to a separate code block. This permits adding separate conditions on using pick independent of repository discovery, and will be exploited later in the series. Note that the picker always returns with the current directory in the root of a worktree with the git repository is in the .git subdirectory. The variable "picked" is used by git-gui to automatically execute the "Explore Working Copy" menu item after the repository picker is run. This is controlled by config variable gui.autoexplore, and happens after all discovery is complete. Remove a later check on whether _gitdir is a directory: that code cannot be reached without rev-parse already validating the repository. _prefix is set as part of worktree discovery, but must be {} if not running with a worktree. Initialze this as {} along with other global variables, this is the correct value is no worktree is found. Signed-off-by: Mark Levedahl <mlevedahl@gmail.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org>

Mark Levedahl committed May 31, 2026 at 19:02 UTC edcf9188beacfda06b66c8e4819314278c4fa457
1 file changed +34 -15
git-gui.sh
+34 -15
@@ -374,6 +374,7 @@ set _gitdir {}
374 set _gitworktree {}
375 set _isbare {}
376 set _githtmldir {}
377 +set _prefix {}
378 set _reponame {}
379 set _shellpath {@@SHELL_PATH@@}
380
@@ -1125,6 +1126,24 @@ unset argv0dir
1126 ##
1127 ## repository setup
1128
1129 +proc is_gitvars_error {err} {
1130 + set havevars 0
1131 + set GIT_DIR {}
1132 + set GIT_WORK_TREE {}
1133 + catch {set GIT_DIR $::env(GIT_DIR); set havevars 1}
1134 + catch {set GIT_WORK_TREE $::env(GIT_WORK_TREE); set havevars 1}
1135 +
1136 + if {$havevars} {
1137 + catch {wm withdraw .}
1138 + error_popup [strcat [mc "Invalid configuration:"] \
1139 + "\n" "GIT_DIR: " $GIT_DIR \
1140 + "\n" "GIT_WORK_TREE: " $GIT_WORK_TREE \
1141 + "\n\n$err"]
1142 + return 1
1143 + }
1144 + return 0
1145 +}
1146 +
1147 proc set_gitdir_vars {} {
1148 global _gitdir _gitworktree env
1149 set env(GIT_DIR) $_gitdir
@@ -1139,16 +1158,22 @@ proc unset_gitdir_vars {} {
1158 catch {unset env(GIT_WORK_TREE)}
1159 }
1160
1161 +# find repository
1162 +set _gitdir {}
1163 +if {$_gitdir eq {}} {
1164 + if {[catch {
1165 + set _gitdir [git rev-parse --absolute-git-dir]
1166 + } err]} {
1167 + if {[is_gitvars_error $err]} {
1168 + exit 1
1169 + }
1170 + set _gitdir {}
1171 + }
1172 +}
1173 +
1174 set picked 0
1143 -if {[catch {
1144 - set _gitdir $env(GIT_DIR)
1145 - set _prefix {}
1146 - }]
1147 - && [catch {
1148 - # beware that from the .git dir this sets _prefix to the empty string
1149 - set _gitdir [git rev-parse --absolute-git-dir]
1150 - set _prefix [git rev-parse --show-prefix]
1151 - } err]} {
1175 +if {$_gitdir eq {}} {
1176 + unset_gitdir_vars
1177 load_config 1
1178 apply_config
1179 choose_repository::pick
@@ -1159,7 +1184,6 @@ if {[catch {
1184 error_popup [strcat [mc "Unusable repo/worktree:"] " [pwd] \n\n$err"]
1185 exit 1
1186 }
1162 - set _prefix {}
1187 set picked 1
1188 }
1189
@@ -1174,11 +1198,6 @@ if {$hashalgorithm eq "sha1"} {
1198 exit 1
1199 }
1200
1177 -if {![file isdirectory $_gitdir]} {
1178 - catch {wm withdraw .}
1179 - error_popup [strcat [mc "Git directory not found:"] "\n\n$_gitdir"]
1180 - exit 1
1181 -}
1201 # _gitdir exists, so try loading the config
1202 load_config 0
1203 apply_config