Direct mode: Support filesystems like FAT which can change their inodes each time they are mounted.

This commit is contained in:
Joey Hess 2013-02-19 16:26:07 -04:00
parent 0f4cc559a7
commit 624e34649f
7 changed files with 69 additions and 15 deletions

View file

@ -304,8 +304,8 @@ prepSendAnnex key = withObjectLoc key indirect direct
direct (f:fs) = do
cache <- recordedInodeCache key
-- check that we have a good file
ifM (liftIO $ compareInodeCache f cache)
( return $ Just (f, liftIO $ compareInodeCache f cache)
ifM (sameInodeCache f cache)
( return $ Just (f, sameInodeCache f cache)
, direct fs
)
@ -356,7 +356,7 @@ removeAnnex key = withObjectLoc key remove removedirect
cache <- recordedInodeCache key
removeInodeCache key
mapM_ (resetfile cache) fs
resetfile cache f = whenM (liftIO $ compareInodeCache f cache) $ do
resetfile cache f = whenM (sameInodeCache f cache) $ do
l <- calcGitLink f key
top <- fromRepo Git.repoPath
cwd <- liftIO getCurrentDirectory

View file

@ -1,6 +1,6 @@
{- git-annex file content managing for direct mode
-
- Copyright 2010,2012 Joey Hess <joey@kitenet.net>
- Copyright 2012-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@ -14,12 +14,13 @@ module Annex.Content.Direct (
recordedInodeCache,
updateInodeCache,
writeInodeCache,
compareInodeCache,
sameInodeCache,
removeInodeCache,
toInodeCache,
) where
import Common.Annex
import qualified Annex
import Annex.Perms
import qualified Git
import Utility.TempFile
@ -94,9 +95,7 @@ normaliseAssociatedFile file = do
- expected mtime and inode.
-}
goodContent :: Key -> FilePath -> Annex Bool
goodContent key file = do
old <- recordedInodeCache key
liftIO $ compareInodeCache file old
goodContent key file = sameInodeCache file =<< recordedInodeCache key
changedFileStatus :: Key -> FileStatus -> Annex Bool
changedFileStatus key status = do
@ -128,3 +127,45 @@ removeInodeCache key = withInodeCacheFile key $ \f -> do
withInodeCacheFile :: Key -> (FilePath -> Annex a) -> Annex a
withInodeCacheFile key a = a =<< inRepo (gitAnnexInodeCache key)
{- Checks if a file's InodeCache matches its current info.
-
- If the inodes have changed, only the size and mtime are compared.
-}
sameInodeCache :: FilePath -> Maybe InodeCache -> Annex Bool
sameInodeCache _ Nothing = return False
sameInodeCache file (Just old) = go =<< liftIO (genInodeCache file)
where
go Nothing = return False
go (Just curr)
| curr == old = return True
| otherwise = ifM inodesChanged
( return $ compareWeak curr old
, return False
)
{- Some filesystems get new inodes each time they are mounted.
- In order to work on such a filesystem, a sentinal file is used to detect
- when the inodes have changed. -}
inodesChanged :: Annex Bool
inodesChanged = maybe calc return =<< Annex.getState Annex.inodeschanged
where
calc = do
sentinalfile <- fromRepo gitAnnexInodeSentinal
sentinalcachefile <- fromRepo gitAnnexInodeSentinalCache
scache <- liftIO $ genInodeCache sentinalfile
scached <- liftIO $ catchMaybeIO $ readInodeCache <$> readFile sentinalcachefile
case (scache, scached) of
(Just c1, Just (Just c2)) -> changed $ c1 /= c2
_ -> do
writesentinal
changed True
changed v = do
Annex.changeState $ \s -> s { Annex.inodeschanged = Just v }
return v
writesentinal = do
sentinalfile <- fromRepo gitAnnexInodeSentinal
sentinalcachefile <- fromRepo gitAnnexInodeSentinalCache
liftIO $ writeFile sentinalfile ""
liftIO $ maybe noop (writeFile sentinalcachefile . showInodeCache)
=<< genInodeCache sentinalfile

View file

@ -85,7 +85,7 @@ addDirect file cache = do
got Nothing = do
showEndFail
return False
got (Just (key, _)) = ifM (liftIO $ compareInodeCache file $ Just cache)
got (Just (key, _)) = ifM (sameInodeCache file $ Just cache)
( do
stageSymlink file =<< hashSymlink =<< calcGitLink file key
writeInodeCache key cache