deal with .git pointer file in Git.CurrentRepo

This fixes the bug.

Note, it's only done when GIT_DIR is set. When it's not set,
Git.Construct already handled it. This is why it was only noticed with this
git submodule command.

This commit was sponsored by Brett Eisenberg on Patreon.
This commit is contained in:
Joey Hess 2020-10-23 14:56:12 -04:00
parent 893d7b21e8
commit 681313dfd4
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
5 changed files with 38 additions and 24 deletions

View file

@ -12,6 +12,8 @@ git-annex (8.20201008) UNRELEASED; urgency=medium
* When a special remote has chunking enabled, but no chunk sizes are * When a special remote has chunking enabled, but no chunk sizes are
recorded (or the recorded ones are not found), speculatively try recorded (or the recorded ones are not found), speculatively try
chunks using the configured chunk size. chunks using the configured chunk size.
* Fixed some problems that prevented this command from working:
git submodule foreach git annex init
-- Joey Hess <id@joeyh.name> Thu, 08 Oct 2020 10:48:17 -0400 -- Joey Hess <id@joeyh.name> Thu, 08 Oct 2020 10:48:17 -0400

View file

@ -21,6 +21,7 @@ module Git.Construct (
repoAbsPath, repoAbsPath,
checkForRepo, checkForRepo,
newFrom, newFrom,
adjustGitDirFile,
) where ) where
#ifndef mingw32_HOST_OS #ifndef mingw32_HOST_OS
@ -73,7 +74,7 @@ fromAbsPath dir
, ret (takeDirectory canondir) , ret (takeDirectory canondir)
) )
| otherwise = ifM (doesDirectoryExist dir) | otherwise = ifM (doesDirectoryExist dir)
( gitDirFile dir >>= maybe (ret dir) (pure . newFrom) ( checkGitDirFile dir >>= maybe (ret dir) (pure . newFrom)
-- git falls back to dir.git when dir doesn't -- git falls back to dir.git when dir doesn't
-- exist, as long as dir didn't end with a -- exist, as long as dir didn't end with a
-- path separator -- path separator
@ -198,7 +199,7 @@ expandTilde = expandt True
checkForRepo :: FilePath -> IO (Maybe RepoLocation) checkForRepo :: FilePath -> IO (Maybe RepoLocation)
checkForRepo dir = checkForRepo dir =
check isRepo $ check isRepo $
check (gitDirFile dir) $ check (checkGitDirFile dir) $
check isBareRepo $ check isBareRepo $
return Nothing return Nothing
where where
@ -219,24 +220,36 @@ checkForRepo dir =
<&&> doesDirectoryExist (dir </> "objects") <&&> doesDirectoryExist (dir </> "objects")
gitSignature file = doesFileExist $ dir </> file gitSignature file = doesFileExist $ dir </> file
-- Check for a .git file.
checkGitDirFile :: FilePath -> IO (Maybe RepoLocation)
checkGitDirFile dir = adjustGitDirFile' $ Local
{ gitdir = toRawFilePath (dir </> ".git")
, worktree = Just (toRawFilePath dir)
}
-- git-submodule, git-worktree, and --separate-git-dir -- git-submodule, git-worktree, and --separate-git-dir
-- make .git be a file pointing to the real git directory. -- make .git be a file pointing to the real git directory.
-- Detect that, and return a RepoLocation with gitdir pointing -- Detect that, and return a RepoLocation with gitdir pointing
-- to the real git directory. -- to the real git directory.
gitDirFile :: FilePath -> IO (Maybe RepoLocation) adjustGitDirFile :: RepoLocation -> IO RepoLocation
gitDirFile dir = do adjustGitDirFile loc = fromMaybe loc <$> adjustGitDirFile' loc
c <- firstLine <$>
catchDefaultIO "" (readFile $ dir </> ".git") adjustGitDirFile' :: RepoLocation -> IO (Maybe RepoLocation)
return $ if gitdirprefix `isPrefixOf` c adjustGitDirFile' loc = do
then Just $ Local let gd = fromRawFilePath (gitdir loc)
{ gitdir = toRawFilePath $ absPathFrom dir $ c <- firstLine <$> catchDefaultIO "" (readFile gd)
drop (length gitdirprefix) c if gitdirprefix `isPrefixOf` c
, worktree = Just (toRawFilePath dir) then do
} top <- takeDirectory <$> absPath gd
else Nothing return $ Just $ loc
{ gitdir = toRawFilePath $ absPathFrom top $
drop (length gitdirprefix) c
}
else return Nothing
where where
gitdirprefix = "gitdir: " gitdirprefix = "gitdir: "
newFrom :: RepoLocation -> Repo newFrom :: RepoLocation -> Repo
newFrom l = Repo newFrom l = Repo
{ location = l { location = l

View file

@ -67,15 +67,14 @@ get = do
configure (Just d) _ = do configure (Just d) _ = do
absd <- absPath d absd <- absPath d
curr <- getCurrentDirectory curr <- getCurrentDirectory
r <- Git.Config.read $ newFrom $ loc <- adjustGitDirFile $ Local
Local { gitdir = toRawFilePath absd
{ gitdir = toRawFilePath absd , worktree = Just (toRawFilePath curr)
, worktree = Just (toRawFilePath curr) }
} r <- Git.Config.read $ newFrom loc
return $ if Git.Config.isBare r return $ if Git.Config.isBare r
then r { location = (location r) { worktree = Nothing } } then r { location = (location r) { worktree = Nothing } }
else r else r
configure Nothing Nothing = giveup "Not in a git repository." configure Nothing Nothing = giveup "Not in a git repository."
addworktree w r = changelocation r $ Local addworktree w r = changelocation r $ Local

View file

@ -28,3 +28,5 @@ As a workaround, manually changing directory into each submodule and running `gi
### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders) ### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
I use it regularly with great success :) I use it regularly with great success :)
> [[fixed|done]] --[[Joey]]

View file

@ -25,13 +25,11 @@ Where does that path that does not exist come from?
.git/modules/sub/config has "core.worktree = ../../../sub" .git/modules/sub/config has "core.worktree = ../../../sub"
git clone sets that. And it's a path from ../.git/modules/sub/ git clone sets that. And it's a path from ../.git/modules/sub/
back to the work tree. git-annex interprets it as well, a regular path back to the work tree. git-annex interprets it as relative to `GIT_DIR`,
from the cwd, like it usually is. It's worth noting that setting which git submodule sets to ".git".
`GIT_WORK_TREE` to the same value makes git behave differently!
Nothing in git's docs seem to explain this mess.
So git-annex needs to check if .git is a gitdir: reference, and So git-annex needs to check if .git is a gitdir: reference, and
then interpret core.worktree relative to it. then interpret core.worktree relative to what it points to.
Or, alternatively, fixupUnusualRepos could learn to tell if the *current* Or, alternatively, fixupUnusualRepos could learn to tell if the *current*
command is git-annex init, and go ahead with the fixes. Which would avoid command is git-annex init, and go ahead with the fixes. Which would avoid