From 681313dfd4e840e6366f3c39eddd92f65d764188 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 23 Oct 2020 14:56:12 -0400 Subject: [PATCH] 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. --- CHANGELOG | 2 + Git/Construct.hs | 39 ++++++++++++------- Git/CurrentRepo.hs | 11 +++--- ...ype___40__Not_a_directory__41____34__.mdwn | 2 + ..._23f3dac4a22cf7202a0bb849ee499766._comment | 8 ++-- 5 files changed, 38 insertions(+), 24 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 213d07c42f..9d64142eae 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,8 @@ git-annex (8.20201008) UNRELEASED; urgency=medium * When a special remote has chunking enabled, but no chunk sizes are recorded (or the recorded ones are not found), speculatively try chunks using the configured chunk size. + * Fixed some problems that prevented this command from working: + git submodule foreach git annex init -- Joey Hess Thu, 08 Oct 2020 10:48:17 -0400 diff --git a/Git/Construct.hs b/Git/Construct.hs index 19c89958f2..39ac04df18 100644 --- a/Git/Construct.hs +++ b/Git/Construct.hs @@ -21,6 +21,7 @@ module Git.Construct ( repoAbsPath, checkForRepo, newFrom, + adjustGitDirFile, ) where #ifndef mingw32_HOST_OS @@ -73,7 +74,7 @@ fromAbsPath dir , ret (takeDirectory canondir) ) | 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 -- exist, as long as dir didn't end with a -- path separator @@ -198,7 +199,7 @@ expandTilde = expandt True checkForRepo :: FilePath -> IO (Maybe RepoLocation) checkForRepo dir = check isRepo $ - check (gitDirFile dir) $ + check (checkGitDirFile dir) $ check isBareRepo $ return Nothing where @@ -219,24 +220,36 @@ checkForRepo dir = <&&> doesDirectoryExist (dir "objects") 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 -- make .git be a file pointing to the real git directory. -- Detect that, and return a RepoLocation with gitdir pointing -- to the real git directory. -gitDirFile :: FilePath -> IO (Maybe RepoLocation) -gitDirFile dir = do - c <- firstLine <$> - catchDefaultIO "" (readFile $ dir ".git") - return $ if gitdirprefix `isPrefixOf` c - then Just $ Local - { gitdir = toRawFilePath $ absPathFrom dir $ - drop (length gitdirprefix) c - , worktree = Just (toRawFilePath dir) - } - else Nothing +adjustGitDirFile :: RepoLocation -> IO RepoLocation +adjustGitDirFile loc = fromMaybe loc <$> adjustGitDirFile' loc + +adjustGitDirFile' :: RepoLocation -> IO (Maybe RepoLocation) +adjustGitDirFile' loc = do + let gd = fromRawFilePath (gitdir loc) + c <- firstLine <$> catchDefaultIO "" (readFile gd) + if gitdirprefix `isPrefixOf` c + then do + top <- takeDirectory <$> absPath gd + return $ Just $ loc + { gitdir = toRawFilePath $ absPathFrom top $ + drop (length gitdirprefix) c + } + else return Nothing where gitdirprefix = "gitdir: " + newFrom :: RepoLocation -> Repo newFrom l = Repo { location = l diff --git a/Git/CurrentRepo.hs b/Git/CurrentRepo.hs index 054a81e0b0..508e71cc9d 100644 --- a/Git/CurrentRepo.hs +++ b/Git/CurrentRepo.hs @@ -67,15 +67,14 @@ get = do configure (Just d) _ = do absd <- absPath d curr <- getCurrentDirectory - r <- Git.Config.read $ newFrom $ - Local - { gitdir = toRawFilePath absd - , worktree = Just (toRawFilePath curr) - } + loc <- adjustGitDirFile $ Local + { gitdir = toRawFilePath absd + , worktree = Just (toRawFilePath curr) + } + r <- Git.Config.read $ newFrom loc return $ if Git.Config.isBare r then r { location = (location r) { worktree = Nothing } } else r - configure Nothing Nothing = giveup "Not in a git repository." addworktree w r = changelocation r $ Local diff --git a/doc/bugs/__34__git_submodule_foreach_git_annex_init__34___fails_with___34__git__58___createProcess__58___runInteractiveProcess__58___chdir__58___inappropriate_type___40__Not_a_directory__41____34__.mdwn b/doc/bugs/__34__git_submodule_foreach_git_annex_init__34___fails_with___34__git__58___createProcess__58___runInteractiveProcess__58___chdir__58___inappropriate_type___40__Not_a_directory__41____34__.mdwn index c79dcae139..873a233c44 100644 --- a/doc/bugs/__34__git_submodule_foreach_git_annex_init__34___fails_with___34__git__58___createProcess__58___runInteractiveProcess__58___chdir__58___inappropriate_type___40__Not_a_directory__41____34__.mdwn +++ b/doc/bugs/__34__git_submodule_foreach_git_annex_init__34___fails_with___34__git__58___createProcess__58___runInteractiveProcess__58___chdir__58___inappropriate_type___40__Not_a_directory__41____34__.mdwn @@ -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) I use it regularly with great success :) + +> [[fixed|done]] --[[Joey]] diff --git a/doc/bugs/__34__git_submodule_foreach_git_annex_init__34___fails_with___34__git__58___createProcess__58___runInteractiveProcess__58___chdir__58___inappropriate_type___40__Not_a_directory__41____34__/comment_3_23f3dac4a22cf7202a0bb849ee499766._comment b/doc/bugs/__34__git_submodule_foreach_git_annex_init__34___fails_with___34__git__58___createProcess__58___runInteractiveProcess__58___chdir__58___inappropriate_type___40__Not_a_directory__41____34__/comment_3_23f3dac4a22cf7202a0bb849ee499766._comment index a57d48445e..27a3c5bd0e 100644 --- a/doc/bugs/__34__git_submodule_foreach_git_annex_init__34___fails_with___34__git__58___createProcess__58___runInteractiveProcess__58___chdir__58___inappropriate_type___40__Not_a_directory__41____34__/comment_3_23f3dac4a22cf7202a0bb849ee499766._comment +++ b/doc/bugs/__34__git_submodule_foreach_git_annex_init__34___fails_with___34__git__58___createProcess__58___runInteractiveProcess__58___chdir__58___inappropriate_type___40__Not_a_directory__41____34__/comment_3_23f3dac4a22cf7202a0bb849ee499766._comment @@ -25,13 +25,11 @@ Where does that path that does not exist come from? .git/modules/sub/config has "core.worktree = ../../../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 -from the cwd, like it usually is. It's worth noting that setting -`GIT_WORK_TREE` to the same value makes git behave differently! -Nothing in git's docs seem to explain this mess. +back to the work tree. git-annex interprets it as relative to `GIT_DIR`, +which git submodule sets to ".git". 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* command is git-annex init, and go ahead with the fixes. Which would avoid