{-# LANGUAGE NoImplicitPrelude #-}

{-|
Module      : Stack.Types.FileDigestCache
License     : BSD-3-Clause
-}

module Stack.Types.FileDigestCache
  ( FileDigestCache
  , newFileDigestCache
  , readFileDigest
  ) where

import qualified Data.Map.Strict as Map
import qualified Pantry.SHA256 as SHA256
import           Stack.Prelude

-- | Type synonym representing caches of digests of files.

type FileDigestCache = IORef (Map FilePath SHA256)

newFileDigestCache :: MonadIO m => m FileDigestCache
newFileDigestCache :: forall (m :: * -> *). MonadIO m => m FileDigestCache
newFileDigestCache = Map FilePath SHA256 -> m FileDigestCache
forall (m :: * -> *) a. MonadIO m => a -> m (IORef a)
newIORef Map FilePath SHA256
forall k a. Map k a
Map.empty

readFileDigest :: MonadIO m => FileDigestCache -> FilePath -> m SHA256
readFileDigest :: forall (m :: * -> *).
MonadIO m =>
FileDigestCache -> FilePath -> m SHA256
readFileDigest FileDigestCache
cache FilePath
filePath = do
  digests <- FileDigestCache -> m (Map FilePath SHA256)
forall (m :: * -> *) a. MonadIO m => IORef a -> m a
readIORef FileDigestCache
cache
  case Map.lookup filePath digests of
    Just SHA256
digest -> SHA256 -> m SHA256
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SHA256
digest
    Maybe SHA256
Nothing -> do
      sha256 <- FilePath -> m SHA256
forall (m :: * -> *). MonadIO m => FilePath -> m SHA256
SHA256.hashFile FilePath
filePath
      writeIORef cache $ Map.insert filePath sha256 digests
      pure sha256