diff options
Diffstat (limited to 'source/Felix/Output')
| -rw-r--r-- | source/Felix/Output/Atomic.hs | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/source/Felix/Output/Atomic.hs b/source/Felix/Output/Atomic.hs new file mode 100644 index 0000000..39ea9c8 --- /dev/null +++ b/source/Felix/Output/Atomic.hs @@ -0,0 +1,29 @@ +{-# LANGUAGE NoImplicitPrelude #-} + +-- | Sibling-temporary replacement for generated byte artifacts. +module Felix.Output.Atomic (writeBytesAtomically) where + +import Base + +import Data.ByteString (ByteString) +import Data.ByteString qualified as ByteString +import System.Directory qualified as Directory +import System.FilePath.Posix qualified as Posix + +writeBytesAtomically :: FilePath -> ByteString -> IO () +writeBytesAtomically destination bytes = do + let directory = Posix.takeDirectory destination + template = Posix.takeFileName destination <> ".tmp" + bracketOnError + (openBinaryTempFileWithDefaultPermissions directory template) + cleanupTemporary + \(temporary, handle) -> do + ByteString.hPut handle bytes + hFlush handle + hClose handle + Directory.renameFile temporary destination + +cleanupTemporary :: (FilePath, Handle) -> IO () +cleanupTemporary (temporary, handle) = do + void (tryIOError (hClose handle)) + void (tryIOError (Directory.removeFile temporary)) |
