From 758515dc9a47ddbd44358bc10aa17e3aaec3992a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 15 Jul 2025 13:09:45 -0400 Subject: [PATCH] fsck: Fix location of annexed files when run in linked worktrees This cleans up after the bug that was fixed in commit 6a9e923c74a1ae5c4c904e7a28e9339bdc241427 Object files that were stored in the wrong location are rescued, and after that any wrong location logs will be fixed by the usual fsck. --- Annex.hs | 8 +++- CHANGELOG | 2 + Command/Fsck.hs | 42 ++++++++++++++++++- ...in_secondary_worktree___40__win__41__.mdwn | 2 + ..._cfb97162cd21818995f9d71a5ce3a0d0._comment | 8 ++++ 5 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 doc/bugs/Missing_file_content_in_secondary_worktree___40__win__41__/comment_7_cfb97162cd21818995f9d71a5ce3a0d0._comment diff --git a/Annex.hs b/Annex.hs index 84b2bda0ad..aba23587fb 100644 --- a/Annex.hs +++ b/Annex.hs @@ -12,6 +12,7 @@ module Annex ( AnnexState(..), AnnexRead(..), new, + new', run, eval, makeRunner, @@ -291,10 +292,13 @@ newAnnexState c r = do - Ensures the config is read, if it was not already, and performs - any necessary git repo fixups. -} new :: Git.Repo -> IO (AnnexState, AnnexRead) -new r = do +new = new' fixupRepo + +new' :: (Git.Repo -> GitConfig -> IO Git.Repo) -> Git.Repo -> IO (AnnexState, AnnexRead) +new' f r = do r' <- Git.Config.read r let c = extractGitConfig FromGitConfig r' - st <- newAnnexState c =<< fixupRepo r' c + st <- newAnnexState c =<< f r' c rd <- newAnnexRead c return (st, rd) diff --git a/CHANGELOG b/CHANGELOG index d85abaa2c1..7216b21fbb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,8 @@ git-annex (10.20250631) UNRELEASED; urgency=medium symlinks, that caused annexed file content to be stored in the wrong location inside the git directory, and also caused pointer files to not get populated. + * fsck: Fix location of annexed files when run in linked worktrees + that have experienced the above bug. * Fix symlinks generated to annexed content when in adjusted unlocked branch in a linked worktree on a filesystem not supporting symlinks. diff --git a/Command/Fsck.hs b/Command/Fsck.hs index 50c21149b3..cd9dd335e1 100644 --- a/Command/Fsck.hs +++ b/Command/Fsck.hs @@ -1,6 +1,6 @@ {- git-annex command - - - Copyright 2010-2023 Joey Hess + - Copyright 2010-2025 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -15,6 +15,7 @@ import qualified Annex import qualified Remote import qualified Types.Backend import qualified Backend +import qualified Git import Annex.Content import Annex.Verify #ifndef mingw32_HOST_OS @@ -24,6 +25,7 @@ import Annex.Content.Presence import Annex.Content.Presence.LowLevel import Annex.Perms import Annex.Link +import Annex.Fixup import Logs.Location import Logs.Trust import Logs.Activity @@ -102,6 +104,8 @@ seek o = startConcurrency commandStages $ do from <- maybe (pure Nothing) (Just <$$> getParsed) (fsckFromOption o) u <- maybe getUUID (pure . Remote.uuid) from checkDeadRepo u + when (isNothing from) $ + cleanupLinkedWorkTreeBug i <- prepIncremental u (incrementalOpt o) let seeker = AnnexedFileSeeker { startAction = const $ start from i @@ -768,4 +772,38 @@ withFsckDb (ContIncremental h) a = a h withFsckDb (StartIncremental h) a = a h withFsckDb (NonIncremental mh) a = maybe noop a mh withFsckDb (ScheduleIncremental _ _ i) a = withFsckDb i a - + +-- A bug caused linked worktrees on filesystems not supporting symlinks +-- to not use the common annex directory, but one annex directory per +-- linked worktree. Object files could end up stored in those directories. +-- +-- When run in a linked worktree with its own annex directory that is not a +-- symlink, move any object files to the right location, and delete the +-- annex directory. +cleanupLinkedWorkTreeBug :: Annex () +cleanupLinkedWorkTreeBug = + whenM (Annex.inRepo needsGitLinkFixup) $ do + r <- Annex.gitRepo + -- mainWorkTreePath is set by fixupUnusualRepos. + -- Unsetting it makes a version of the Repo that uses + -- the wrong object location. + let r' = r { Git.mainWorkTreePath = Nothing } + let dir = gitAnnexDir r' + whenM (liftIO $ dirnotsymlink dir) $ do + showSideAction $ "Cleaning up directory " + <> QuotedPath dir + <> " created by buggy version of git-annex" + (st, rd) <- liftIO $ Annex.new' (\r'' _c -> pure r'') r' + ks <- liftIO $ Annex.eval (st, rd) $ + listKeys InAnnex + forM_ ks $ \k -> void $ tryNonAsync $ do + loc <- liftIO $ gitAnnexLocation k r' + (Annex.gitconfig st) + moveAnnex k loc + void $ tryNonAsync $ liftIO $ + removeDirectoryRecursive dir + where + dirnotsymlink dir = + tryIO (R.getSymbolicLinkStatus (fromOsPath dir)) >>= \case + Right st -> return $ not (isSymbolicLink st) + Left _ -> return False diff --git a/doc/bugs/Missing_file_content_in_secondary_worktree___40__win__41__.mdwn b/doc/bugs/Missing_file_content_in_secondary_worktree___40__win__41__.mdwn index bbbb8143b3..9aa0d48d6d 100644 --- a/doc/bugs/Missing_file_content_in_secondary_worktree___40__win__41__.mdwn +++ b/doc/bugs/Missing_file_content_in_secondary_worktree___40__win__41__.mdwn @@ -97,3 +97,5 @@ This is on win11. Absolutely! Approaching 15 years of bigger, better, faster, more ;-) [[!tag projects/INM7]] + +> [[fixed|done]] --[[Joey]] diff --git a/doc/bugs/Missing_file_content_in_secondary_worktree___40__win__41__/comment_7_cfb97162cd21818995f9d71a5ce3a0d0._comment b/doc/bugs/Missing_file_content_in_secondary_worktree___40__win__41__/comment_7_cfb97162cd21818995f9d71a5ce3a0d0._comment new file mode 100644 index 0000000000..bb752665bf --- /dev/null +++ b/doc/bugs/Missing_file_content_in_secondary_worktree___40__win__41__/comment_7_cfb97162cd21818995f9d71a5ce3a0d0._comment @@ -0,0 +1,8 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 7""" + date="2025-07-15T17:07:43Z" + content=""" +Running `git-annex fsck` in the affected worktree will clean up from this +bug. +"""]]