deal with .git pointer file in Git.CurrentRepo
authorJoey Hess <joeyh@joeyh.name>
Fri, 23 Oct 2020 18:56:12 +0000 (14:56 -0400)
committerJoey Hess <joeyh@joeyh.name>
Fri, 23 Oct 2020 18:56:12 +0000 (14:56 -0400)
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
Git/Construct.hs
Git/CurrentRepo.hs
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
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 213d07c42fc1f265053ef2932ff252d57b9c9374..9d64142eaec61ca23e06f993dcd8248d2126ab34 100644 (file)
--- 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 <id@joeyh.name>  Thu, 08 Oct 2020 10:48:17 -0400
 
index 19c89958f254177acc8875c13773eb5eea521c69..39ac04df1824934cfe2808c64a67f8b7647cc425 100644 (file)
@@ -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
index 054a81e0b01b565f34b00e5db40d816bdb4d4394..508e71cc9d37c69e6c28d54fd7005a16f8b1053c 100644 (file)
@@ -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
index a57d48445e3f313b6c03409c0dfb9e1a8d4354bf..27a3c5bd0e28a0e7423deaa93b31bc9350e84813 100644 (file)
@@ -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