Avoid Git.Config.updateLocation adding "/.git" to the end of the repo

path to a bare repo when git config is not allowed to list the configs
due to the CVE-2022-24765 fix.

That resulted in a confusing error message, and prevented the nice
message that explains how to mark the repo as safe to use.

Made isBare a tristate so that the case where core.bare is not returned can
be handled.

The handling in updateLocation is to check if the directory
contains config and objects and if so assume it's bare.
Note that if that heuristic is somehow wrong, it would construct a repo
that thinks it's bare but is not. That could cause follow-on problems,
but since git-annex then checks checkRepoConfigInaccessible, and skips
using the repo anyway, a wrong guess should not be a problem.

Sponsored-by: Luke Shumaker on Patreon
This commit is contained in:
Joey Hess 2023-02-14 14:00:36 -04:00
parent 12b45d3b89
commit c1ef4a7481
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
7 changed files with 39 additions and 30 deletions

View file

@ -1,6 +1,6 @@
{- Construction of Git Repo objects
-
- Copyright 2010-2021 Joey Hess <id@joeyh.name>
- Copyright 2010-2023 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
@ -23,6 +23,7 @@ module Git.Construct (
checkForRepo,
newFrom,
adjustGitDirFile,
isBareRepo,
) where
#ifndef mingw32_HOST_OS
@ -216,7 +217,7 @@ checkForRepo :: FilePath -> IO (Maybe RepoLocation)
checkForRepo dir =
check isRepo $
check (checkGitDirFile (toRawFilePath dir)) $
check isBareRepo $
check (checkdir (isBareRepo dir)) $
return Nothing
where
check test cont = maybe cont (return . Just) =<< test
@ -225,16 +226,17 @@ checkForRepo dir =
, return Nothing
)
isRepo = checkdir $
gitSignature (".git" </> "config")
doesFileExist (dir </> ".git" </> "config")
<||>
-- A git-worktree lacks .git/config, but has .git/gitdir.
-- (Normally the .git is a file, not a symlink, but it can
-- be converted to a symlink and git will still work;
-- this handles that case.)
gitSignature (".git" </> "gitdir")
isBareRepo = checkdir $ gitSignature "config"
<&&> doesDirectoryExist (dir </> "objects")
gitSignature file = doesFileExist $ dir </> file
doesFileExist (dir </> ".git" </> "gitdir")
isBareRepo :: FilePath -> IO Bool
isBareRepo dir = doesFileExist (dir </> "config")
<&&> doesDirectoryExist (dir </> "objects")
-- Check for a .git file.
checkGitDirFile :: RawFilePath -> IO (Maybe RepoLocation)