diff options
author | Joey Hess <joey@kitenet.net> | 2013-03-04 14:25:18 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2013-03-04 14:25:22 -0400 |
commit | 0a959d31d29ed95ff648fcf4027803d3db41ae57 (patch) | |
tree | 36a73782a131205f50948cd2fb05e74c9051b72c /Assistant | |
parent | 711ef96d67f467c193e637ae5a7d5837c8cf9910 (diff) |
fixed the race breaking moving files from archive in direct mode
assistant: Fix bug in direct mode that could occur when a symlink is moved
out of an archive directory, and resulted in the file not being set to
direct mode when it was transferred.
The bug was that the direct mode mapping was not up-to-date when the
transferrer finished. So, finding no direct mode place to store the object,
it was put into .git/annex in indirect mode.
To fix this, just make the watcher update the direct mode mapping to
include the new file before it starts the transfer. (Seems we don't need to
update it to remove the old file if the link was moved, because the direct
mode code will notice it's not present and the mapping gets updated for its
removal later.)
The reason this was a race, and was probably not seen often is because
the committer came along and updated the direct mode mapping as part of
adding the moved symlink. But when the file was sufficiently small or
the remote sufficiently fast, this could happen after the transfer
finished.
Diffstat (limited to 'Assistant')
-rw-r--r-- | Assistant/Threads/SanityChecker.hs | 4 | ||||
-rw-r--r-- | Assistant/Threads/Watcher.hs | 8 |
2 files changed, 8 insertions, 4 deletions
diff --git a/Assistant/Threads/SanityChecker.hs b/Assistant/Threads/SanityChecker.hs index 906167ca8..a6166214a 100644 --- a/Assistant/Threads/SanityChecker.hs +++ b/Assistant/Threads/SanityChecker.hs @@ -19,6 +19,7 @@ import qualified Git.Config import Utility.ThreadScheduler import qualified Assistant.Threads.Watcher as Watcher import Utility.LogFile +import Config import Data.Time.Clock.POSIX @@ -105,7 +106,8 @@ dailyCheck = do liftAnnex $ warning msg void $ addAlert $ sanityCheckFixAlert msg addsymlink file s = do - Watcher.runHandler Watcher.onAddSymlink file s + isdirect <- liftAnnex isDirect + Watcher.runHandler (Watcher.onAddSymlink isdirect) file s insanity $ "found unstaged symlink: " ++ file hourlyCheck :: Assistant () diff --git a/Assistant/Threads/Watcher.hs b/Assistant/Threads/Watcher.hs index 7e373e95a..4eac622f9 100644 --- a/Assistant/Threads/Watcher.hs +++ b/Assistant/Threads/Watcher.hs @@ -82,7 +82,7 @@ runWatcher = do direct <- liftAnnex isDirect addhook <- hook $ if direct then onAddDirect else onAdd delhook <- hook onDel - addsymlinkhook <- hook onAddSymlink + addsymlinkhook <- hook $ onAddSymlink direct deldirhook <- hook onDelDir errhook <- hook onErr let hooks = mkWatchHooks @@ -193,10 +193,12 @@ onAddDirect file fs = do - Or, if it is a git-annex symlink, ensure it points to the content - before adding it. -} -onAddSymlink :: Handler -onAddSymlink file filestatus = go =<< liftAnnex (Backend.lookupFile file) +onAddSymlink :: Bool -> Handler +onAddSymlink isdirect file filestatus = go =<< liftAnnex (Backend.lookupFile file) where go (Just (key, _)) = do + when isdirect $ + liftAnnex $ void $ addAssociatedFile key file link <- liftAnnex $ calcGitLink file key ifM ((==) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file)) ( do |