module Data.Git.Storage.CacheFile (CacheFile, newCacheVal, getCacheVal) where
import Control.Applicative ((<$>))
import Control.Concurrent.MVar
import qualified Control.Exception as E
import Filesystem.Path
import Filesystem.Path.CurrentOS (encodeString)
import Prelude hiding (FilePath)
import System.PosixCompat.Files (getFileStatus, modificationTime)
import System.PosixCompat.Types (EpochTime)
data CacheFile a = CacheFile
{ cacheFilepath :: FilePath
, cacheRefresh :: IO a
, cacheIniVal :: a
, cacheLock :: MVar (MTime, a)
}
timeZero = 0
newCacheVal :: FilePath -> IO a -> a -> IO (CacheFile a)
newCacheVal path refresh initialVal =
CacheFile path refresh initialVal <$> newMVar (MTime timeZero, initialVal)
getCacheVal :: CacheFile a -> IO a
getCacheVal cachefile = modifyMVar (cacheLock cachefile) getOrRefresh
where getOrRefresh s@(mtime, cachedVal) = do
cMTime <- getMTime $ cacheFilepath cachefile
case cMTime of
Nothing -> return ((MTime timeZero, cacheIniVal cachefile), cacheIniVal cachefile)
Just newMtime | newMtime > mtime -> cacheRefresh cachefile >>= \v -> return ((newMtime, v), v)
| otherwise -> return (s, cachedVal)
newtype MTime = MTime EpochTime deriving (Eq,Ord)
getMTime filepath = (Just . MTime . modificationTime <$> getFileStatus (encodeString filepath))
`E.catch` \(_ :: E.SomeException) -> return Nothing