From 41ebed39419d53878d07c361a7564cbe290da879 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 28 Aug 2020 15:08:14 -0400 Subject: [PATCH] Support git remotes where .git is a file, not a directory Eg when --separate-git-dir was used, and core.symlinks=false. This commit was sponsored by Brock Spratlen on Patreon. --- CHANGELOG | 2 + Git/Construct.hs | 38 ++++++++++--------- ...dir_OK_under_Linux_FAIL_under_Windows.mdwn | 2 + ..._97ab8d245680e23a9e4b471796db2119._comment | 35 +++++++++++++++++ 4 files changed, 60 insertions(+), 17 deletions(-) create mode 100644 doc/bugs/separate-git-dir_OK_under_Linux_FAIL_under_Windows/comment_1_97ab8d245680e23a9e4b471796db2119._comment diff --git a/CHANGELOG b/CHANGELOG index 0189cbfeb9..7ac371a783 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,8 @@ git-annex (8.20200815) UNRELEASED; urgency=medium held by another process. * test: Stop gpg-agent daemons that are started for the test framework's gpg key. + * Support git remotes where .git is a file, not a directory, + eg when --separate-git-dir was used. -- Joey Hess Fri, 14 Aug 2020 14:57:45 -0400 diff --git a/Git/Construct.hs b/Git/Construct.hs index 5b656eba72..19c89958f2 100644 --- a/Git/Construct.hs +++ b/Git/Construct.hs @@ -1,6 +1,6 @@ {- Construction of Git Repo objects - - - Copyright 2010-2012 Joey Hess + - Copyright 2010-2020 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -73,7 +73,7 @@ fromAbsPath dir , ret (takeDirectory canondir) ) | otherwise = ifM (doesDirectoryExist dir) - ( ret dir + ( gitDirFile 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 +198,7 @@ expandTilde = expandt True checkForRepo :: FilePath -> IO (Maybe RepoLocation) checkForRepo dir = check isRepo $ - check gitDirFile $ + check (gitDirFile dir) $ check isBareRepo $ return Nothing where @@ -217,22 +217,26 @@ checkForRepo dir = gitSignature (".git" "gitdir") isBareRepo = checkdir $ gitSignature "config" <&&> doesDirectoryExist (dir "objects") - gitDirFile = do - -- git-submodule, git-worktree, and --separate-git-dir - -- make .git be a file pointing to the real git directory. - 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 - where - gitdirprefix = "gitdir: " gitSignature file = doesFileExist $ dir file +-- 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 + where + gitdirprefix = "gitdir: " + newFrom :: RepoLocation -> Repo newFrom l = Repo { location = l diff --git a/doc/bugs/separate-git-dir_OK_under_Linux_FAIL_under_Windows.mdwn b/doc/bugs/separate-git-dir_OK_under_Linux_FAIL_under_Windows.mdwn index 58c757f4f8..acf9391139 100644 --- a/doc/bugs/separate-git-dir_OK_under_Linux_FAIL_under_Windows.mdwn +++ b/doc/bugs/separate-git-dir_OK_under_Linux_FAIL_under_Windows.mdwn @@ -178,3 +178,5 @@ shaddy@jazz-debian:~/slaveproj$ ls -lL services ### 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) This issue is not a show stopper. I otherwise love the concepts behind git-annex very much. + +> [[fixed|done]] --[[Joey]] diff --git a/doc/bugs/separate-git-dir_OK_under_Linux_FAIL_under_Windows/comment_1_97ab8d245680e23a9e4b471796db2119._comment b/doc/bugs/separate-git-dir_OK_under_Linux_FAIL_under_Windows/comment_1_97ab8d245680e23a9e4b471796db2119._comment new file mode 100644 index 0000000000..1c24fbe3f0 --- /dev/null +++ b/doc/bugs/separate-git-dir_OK_under_Linux_FAIL_under_Windows/comment_1_97ab8d245680e23a9e4b471796db2119._comment @@ -0,0 +1,35 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 1""" + date="2020-08-28T18:03:46Z" + content=""" +--separate-git-dir makes eg, masterproj/.git be a file that contains the +path to the git dir. + +git-annex init converts such a .git file to a symlink. That is necessary +for git-annex symlinks to be resolved, since they always link to files +inside .git, and if it's a file, the symlinks won't point to the object +files. + +On windows, since core.symlinks is false, it does not make that change. + +So, I think the problem might be that, when .git is a file rather +than a symlink, git-annex in the clone doesn't read the .git file to determine +the real git repo location, and so can't find annexed files in its remote. + +Seem to have found a way to produce the same problem on linux: + +* git init --separate-git-dir masterproj.git masterproj +* cd masterproj; git config core.symlinks false +* git-annex init +* add file, commit, make clone + +git-annex get in the clone then fails + + openat(AT_FDCWD, "../masterproj/.git/annex/objects/3f/3K/SHA256E-s30--32a7ec5a2905bbeda54a699ed797c96c1fea7b5bc31a6cc104b2ddefe65a95bb/SHA256E-s30--32a7ec5a2905bbeda54a699ed797c96c1fea7b5bc31a6cc104b2ddefe65a95bb", O_RDONLY) = -1 ENOTDIR (Not a directory) + +So, I think it would make sense for git-annex to notice when +a remote's .git is a file rather than a directory, and adjust the remote +accordingly, so it uses its actual git directory. That will solve +this situation. +"""]]