From 490211a7f9cf9080bc913a481d8e11865931e46b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 19 Feb 2013 16:26:07 -0400 Subject: Direct mode: Support filesystems like FAT which can change their inodes each time they are mounted. --- Annex/Content/Direct.hs | 51 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) (limited to 'Annex/Content') diff --git a/Annex/Content/Direct.hs b/Annex/Content/Direct.hs index 67a966142..1ae127ef6 100644 --- a/Annex/Content/Direct.hs +++ b/Annex/Content/Direct.hs @@ -1,6 +1,6 @@ {- git-annex file content managing for direct mode - - - Copyright 2010,2012 Joey Hess + - Copyright 2012-2013 Joey Hess - - 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 -- cgit v1.2.3