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