fsck: Fix location of annexed files when run in linked worktrees

This cleans up after the bug that was fixed in commit
6a9e923c74
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.
This commit is contained in:
Joey Hess 2025-07-15 13:09:45 -04:00
parent 313d1b10fa
commit 758515dc9a
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
5 changed files with 58 additions and 4 deletions

View file

@ -12,6 +12,7 @@ module Annex (
AnnexState(..), AnnexState(..),
AnnexRead(..), AnnexRead(..),
new, new,
new',
run, run,
eval, eval,
makeRunner, makeRunner,
@ -291,10 +292,13 @@ newAnnexState c r = do
- Ensures the config is read, if it was not already, and performs - Ensures the config is read, if it was not already, and performs
- any necessary git repo fixups. -} - any necessary git repo fixups. -}
new :: Git.Repo -> IO (AnnexState, AnnexRead) 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 r' <- Git.Config.read r
let c = extractGitConfig FromGitConfig r' let c = extractGitConfig FromGitConfig r'
st <- newAnnexState c =<< fixupRepo r' c st <- newAnnexState c =<< f r' c
rd <- newAnnexRead c rd <- newAnnexRead c
return (st, rd) return (st, rd)

View file

@ -6,6 +6,8 @@ git-annex (10.20250631) UNRELEASED; urgency=medium
symlinks, that caused annexed file content to be stored in the wrong symlinks, that caused annexed file content to be stored in the wrong
location inside the git directory, and also caused pointer files to not location inside the git directory, and also caused pointer files to not
get populated. 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 * Fix symlinks generated to annexed content when in adjusted unlocked
branch in a linked worktree on a filesystem not supporting symlinks. branch in a linked worktree on a filesystem not supporting symlinks.

View file

@ -1,6 +1,6 @@
{- git-annex command {- git-annex command
- -
- Copyright 2010-2023 Joey Hess <id@joeyh.name> - Copyright 2010-2025 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -15,6 +15,7 @@ import qualified Annex
import qualified Remote import qualified Remote
import qualified Types.Backend import qualified Types.Backend
import qualified Backend import qualified Backend
import qualified Git
import Annex.Content import Annex.Content
import Annex.Verify import Annex.Verify
#ifndef mingw32_HOST_OS #ifndef mingw32_HOST_OS
@ -24,6 +25,7 @@ import Annex.Content.Presence
import Annex.Content.Presence.LowLevel import Annex.Content.Presence.LowLevel
import Annex.Perms import Annex.Perms
import Annex.Link import Annex.Link
import Annex.Fixup
import Logs.Location import Logs.Location
import Logs.Trust import Logs.Trust
import Logs.Activity import Logs.Activity
@ -102,6 +104,8 @@ seek o = startConcurrency commandStages $ do
from <- maybe (pure Nothing) (Just <$$> getParsed) (fsckFromOption o) from <- maybe (pure Nothing) (Just <$$> getParsed) (fsckFromOption o)
u <- maybe getUUID (pure . Remote.uuid) from u <- maybe getUUID (pure . Remote.uuid) from
checkDeadRepo u checkDeadRepo u
when (isNothing from) $
cleanupLinkedWorkTreeBug
i <- prepIncremental u (incrementalOpt o) i <- prepIncremental u (incrementalOpt o)
let seeker = AnnexedFileSeeker let seeker = AnnexedFileSeeker
{ startAction = const $ start from i { startAction = const $ start from i
@ -768,4 +772,38 @@ withFsckDb (ContIncremental h) a = a h
withFsckDb (StartIncremental h) a = a h withFsckDb (StartIncremental h) a = a h
withFsckDb (NonIncremental mh) a = maybe noop a mh withFsckDb (NonIncremental mh) a = maybe noop a mh
withFsckDb (ScheduleIncremental _ _ i) a = withFsckDb i a 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

View file

@ -97,3 +97,5 @@ This is on win11.
Absolutely! Approaching 15 years of bigger, better, faster, more ;-) Absolutely! Approaching 15 years of bigger, better, faster, more ;-)
[[!tag projects/INM7]] [[!tag projects/INM7]]
> [[fixed|done]] --[[Joey]]

View file

@ -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.
"""]]