1 {-# LANGUAGE OverloadedStrings, TupleSections #-}
    2 module Databrary.Store.Temp
    3   ( TempFile(..)
    4   , makeTempFileAs
    5   , makeTempFile
    6   , releaseTempFile
    7   , renameTempFile
    8   ) where
    9 
   10 import Control.Exception (bracket)
   11 import Control.Monad (void)
   12 import Control.Monad.Trans.Resource (InternalState, runInternalState, ReleaseKey, allocate, release, unprotect)
   13 import System.IO (Handle, hClose)
   14 import System.Posix.FilePath (RawFilePath)
   15 import System.Posix.Files.ByteString (removeLink, rename)
   16 import System.Posix.Temp.ByteString (mkstemp)
   17 
   18 import Databrary.Has (peeks, focusIO, MonadHas)
   19 import Databrary.Store.Types
   20 -- import Databrary.Action.Types
   21 
   22 data TempFile = TempFile
   23   { tempFileRelease :: ReleaseKey
   24   , tempFilePath :: RawFilePath
   25   }
   26 
   27 makeTempFileAs :: RawFilePath -> (Handle -> IO ()) -> InternalState -> IO TempFile
   28 makeTempFileAs d g rs = bracket
   29   (runInternalState (allocate (mkstemp d) (removeLink . fst)) rs)
   30   (hClose . snd . snd)
   31   (\(k, (f, h)) -> TempFile k f <$ g h)
   32 
   33 makeTempFile :: (MonadStorage c m, MonadHas InternalState c m) => (Handle -> IO ()) -> m TempFile
   34 makeTempFile f = do
   35   tmp <- peeks storageTemp
   36   focusIO $ makeTempFileAs tmp f
   37 
   38 releaseTempFile :: TempFile -> InternalState -> IO ()
   39 releaseTempFile = runInternalState . release . tempFileRelease
   40 
   41 renameTempFile :: TempFile -> RawFilePath -> InternalState -> IO ()
   42 renameTempFile (TempFile k f) t rs = do
   43   rename f t
   44   void $ runInternalState (unprotect k) rs