1 2 module 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 Has (peeks, focusIO, MonadHas) 19 import Store.Types 20 -- import 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