atomic-write-0.2.1.0/0000755000000000000000000000000007346545000012445 5ustar0000000000000000atomic-write-0.2.1.0/LICENSE0000644000000000000000000000206307346545000013453 0ustar0000000000000000MIT License Copyright (c) 2022 Stack Builders Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.atomic-write-0.2.1.0/Setup.hs0000644000000000000000000000005607346545000014102 0ustar0000000000000000import Distribution.Simple main = defaultMain atomic-write-0.2.1.0/atomic-write.cabal0000644000000000000000000001124507346545000016040 0ustar0000000000000000name: atomic-write version: 0.2.1.0 synopsis: Atomically write to a file homepage: https://github.com/stackbuilders/atomic-write description: . Atomically write to a file on POSIX-compliant systems while preserving permissions. . On most Unix systems, `mv` is an atomic operation. This makes it simple to write to a file atomically just by using the mv operation. However, this will destroy the permissions on the original file. This library does the following to preserve permissions while atomically writing to a file: . * If an original file exists, take those permissions and apply them to the temp file before `mv`ing the file into place. . * If the original file does not exist, create a following with default permissions (based on the currently-active umask). . This way, when the file is `mv`'ed into place, the permissions will be the ones held by the original file. . This library is based on similar implementations found in common libraries in Ruby and Python: . * . * . * . To use `atomic-write`, import the module corresponding to the type you wish to write atomically, e.g., to write a (strict) ByteString atomically: . > import System.AtomicWrite.Writer.ByteString . Then you can use the atomicWriteFile function that accepts a `FilePath` and a `ByteString`, e.g.: . > atomicWriteFile myFilePath myByteString license: MIT license-file: LICENSE author: Justin Leitgeb maintainer: support@stackbuilders.com copyright: 2015-2019 Stack Builders Inc. category: System build-type: Simple cabal-version: >=1.10 tested-with: GHC ==8.4.3, GHC ==8.10.7, GHC ==9.4.7 bug-reports: https://github.com/stackbuilders/atomic-write/issues library exposed-modules: System.AtomicWrite.Writer.ByteString , System.AtomicWrite.Writer.ByteString.Binary , System.AtomicWrite.Writer.ByteStringBuilder , System.AtomicWrite.Writer.LazyByteString , System.AtomicWrite.Writer.LazyByteString.Binary , System.AtomicWrite.Writer.String , System.AtomicWrite.Writer.String.Binary , System.AtomicWrite.Writer.Text , System.AtomicWrite.Writer.Text.Binary , System.AtomicWrite.Writer.LazyText , System.AtomicWrite.Writer.LazyText.Binary other-modules: System.AtomicWrite.Internal build-depends: base >= 4.5 && < 5.0 , temporary >= 1.3 && < 1.4 , unix-compat >= 0.5 && < 1.0 , directory >= 1.3 && < 1.4 , filepath >= 1.4 && < 1.5 , text >= 1.2 && < 3.0 , bytestring >= 0.10.4 && < 0.13.0 hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall test-suite atomic-write-test type: exitcode-stdio-1.0 hs-source-dirs: spec main-is: Spec.hs other-modules: System.AtomicWrite.Writer.ByteStringSpec , System.AtomicWrite.Writer.ByteString.BinarySpec , System.AtomicWrite.Writer.ByteStringBuilderSpec , System.AtomicWrite.Writer.LazyByteStringSpec , System.AtomicWrite.Writer.LazyByteString.BinarySpec , System.AtomicWrite.Writer.StringSpec , System.AtomicWrite.Writer.String.BinarySpec , System.AtomicWrite.Writer.TextSpec , System.AtomicWrite.Writer.Text.BinarySpec , System.AtomicWrite.Writer.LazyTextSpec , System.AtomicWrite.Writer.LazyText.BinarySpec build-depends: base >= 4.5 && < 5.0 , atomic-write , temporary , unix-compat , filepath , text , bytestring , hspec >= 2.5 && < 2.12 build-tools: hspec-discover >= 2.0 && < 3.0 default-language: Haskell2010 ghc-options: -Wall source-repository head type: git location: git@github.com:stackbuilders/atomic-write.git atomic-write-0.2.1.0/spec/0000755000000000000000000000000007346545000013377 5ustar0000000000000000atomic-write-0.2.1.0/spec/Spec.hs0000644000000000000000000000005407346545000014624 0ustar0000000000000000{-# OPTIONS_GHC -F -pgmF hspec-discover #-} atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/ByteString/0000755000000000000000000000000007346545000022460 5ustar0000000000000000atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/ByteString/BinarySpec.hs0000644000000000000000000001235707346545000025063 0ustar0000000000000000module System.AtomicWrite.Writer.ByteString.BinarySpec (spec) where import Test.Hspec (Spec, describe, it, shouldBe) import System.AtomicWrite.Writer.ByteString.Binary (atomicWriteFile, atomicWriteFileWithMode) import System.FilePath.Posix (joinPath) import System.IO.Temp (withSystemTempDirectory) import System.PosixCompat.Files (fileMode, getFileStatus, setFileCreationMask, setFileMode) import Data.ByteString.Char8 (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes the contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/0000755000000000000000000000000007346545000020366 5ustar0000000000000000atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/ByteStringBuilderSpec.hs0000644000000000000000000001172507346545000025144 0ustar0000000000000000module System.AtomicWrite.Writer.ByteStringBuilderSpec (spec) where import Test.Hspec (it, describe, shouldBe, Spec) import System.AtomicWrite.Writer.ByteStringBuilder (atomicWriteFile, atomicWriteFileWithMode) import System.IO.Temp (withSystemTempDirectory) import System.FilePath.Posix (joinPath) import System.PosixCompat.Files (setFileMode, setFileCreationMask, getFileStatus, fileMode) import Data.ByteString.Builder (lazyByteString) import Data.ByteString.Lazy.Char8 (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ lazyByteString $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ lazyByteString $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ lazyByteString $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ lazyByteString $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ lazyByteString $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ lazyByteString $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/ByteStringSpec.hs0000644000000000000000000001223407346545000023631 0ustar0000000000000000module System.AtomicWrite.Writer.ByteStringSpec (spec) where import Test.Hspec (Spec, describe, it, shouldBe) import System.AtomicWrite.Writer.ByteString (atomicWriteFile, atomicWriteFileWithMode) import System.FilePath.Posix (joinPath) import System.IO.Temp (withSystemTempDirectory) import System.PosixCompat.Files (fileMode, getFileStatus, setFileCreationMask, setFileMode) import Data.ByteString.Char8 (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/LazyByteString/0000755000000000000000000000000007346545000023320 5ustar0000000000000000atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/LazyByteString/BinarySpec.hs0000644000000000000000000001263007346545000025715 0ustar0000000000000000module System.AtomicWrite.Writer.LazyByteString.BinarySpec (spec) where import Test.Hspec (Spec, describe, it, shouldBe) import System.AtomicWrite.Writer.LazyByteString.Binary (atomicWriteFile, atomicWriteFileWithMode) import System.FilePath.Posix (joinPath) import System.IO.Temp (withSystemTempDirectory) import System.PosixCompat.Files (fileMode, getFileStatus, setFileCreationMask, setFileMode) import Data.ByteString.Lazy.Char8 (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/LazyByteStringSpec.hs0000644000000000000000000001147007346545000024472 0ustar0000000000000000module System.AtomicWrite.Writer.LazyByteStringSpec (spec) where import Test.Hspec (it, describe, shouldBe, Spec) import System.AtomicWrite.Writer.LazyByteString (atomicWriteFile, atomicWriteFileWithMode) import System.IO.Temp (withSystemTempDirectory) import System.FilePath.Posix (joinPath) import System.PosixCompat.Files (setFileMode, setFileCreationMask, getFileStatus, fileMode) import Data.ByteString.Lazy.Char8 (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/LazyText/0000755000000000000000000000000007346545000022152 5ustar0000000000000000atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/LazyText/BinarySpec.hs0000644000000000000000000001232207346545000024545 0ustar0000000000000000module System.AtomicWrite.Writer.LazyText.BinarySpec (spec) where import Test.Hspec (Spec, describe, it, shouldBe) import System.AtomicWrite.Writer.LazyText.Binary (atomicWriteFile, atomicWriteFileWithMode) import System.FilePath.Posix (joinPath) import System.IO.Temp (withSystemTempDirectory) import System.PosixCompat.Files (fileMode, getFileStatus, setFileCreationMask, setFileMode) import Data.Text.Lazy (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/LazyTextSpec.hs0000644000000000000000000001144007346545000023321 0ustar0000000000000000module System.AtomicWrite.Writer.LazyTextSpec (spec) where import Test.Hspec (it, describe, shouldBe, Spec) import System.AtomicWrite.Writer.LazyText (atomicWriteFile, atomicWriteFileWithMode) import System.IO.Temp (withSystemTempDirectory) import System.FilePath.Posix (joinPath) import System.PosixCompat.Files (setFileMode, setFileCreationMask, getFileStatus, fileMode) import Data.Text.Lazy (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/String/0000755000000000000000000000000007346545000021634 5ustar0000000000000000atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/String/BinarySpec.hs0000644000000000000000000001221407346545000024227 0ustar0000000000000000module System.AtomicWrite.Writer.String.BinarySpec (spec) where import Test.Hspec (Spec, describe, it, shouldBe) import System.AtomicWrite.Writer.String.Binary (atomicWriteFile, atomicWriteFileWithMode) import System.FilePath (joinPath) import System.IO.Temp (withSystemTempDirectory) import System.PosixCompat.Files (fileMode, getFileStatus, setFileCreationMask, setFileMode) {-# ANN module "HLint: ignore Reduce duplication" #-} spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/StringSpec.hs0000644000000000000000000001202307346545000023001 0ustar0000000000000000module System.AtomicWrite.Writer.StringSpec (spec) where import Test.Hspec (Spec, describe, it, shouldBe) import System.AtomicWrite.Writer.String (atomicWriteFile, atomicWriteFileWithMode) import System.FilePath (joinPath) import System.IO.Temp (withSystemTempDirectory) import System.PosixCompat.Files (fileMode, getFileStatus, setFileCreationMask, setFileMode) {-# ANN module "HLint: ignore Reduce duplication" #-} spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/Text/0000755000000000000000000000000007346545000021312 5ustar0000000000000000atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/Text/BinarySpec.hs0000644000000000000000000001224607346545000023712 0ustar0000000000000000module System.AtomicWrite.Writer.Text.BinarySpec (spec) where import Test.Hspec (Spec, describe, it, shouldBe) import System.AtomicWrite.Writer.Text.Binary (atomicWriteFile, atomicWriteFileWithMode) import System.FilePath.Posix (joinPath) import System.IO.Temp (withSystemTempDirectory) import System.PosixCompat.Files (fileMode, getFileStatus, setFileCreationMask, setFileMode) import Data.Text (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/spec/System/AtomicWrite/Writer/TextSpec.hs0000644000000000000000000001142307346545000022462 0ustar0000000000000000module System.AtomicWrite.Writer.TextSpec (spec) where import Test.Hspec (it, describe, shouldBe, Spec) import System.AtomicWrite.Writer.Text (atomicWriteFile, atomicWriteFileWithMode) import System.IO.Temp (withSystemTempDirectory) import System.FilePath.Posix (joinPath) import System.PosixCompat.Files (setFileMode, setFileCreationMask, getFileStatus, fileMode) import Data.Text (pack) spec :: Spec spec = do describe "atomicWriteFile" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFile path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "preserves the permissions of original file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100644 it "creates a new file with permissions based on active umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] sampleFilePath = joinPath [tmpDir, "sampleFile"] -- Set somewhat distinctive defaults for test _ <- setFileCreationMask 0o100171 -- We don't know what the default file permissions are, so create a -- file to sample them. writeFile sampleFilePath "I'm being written to sample permissions" newStat <- getFileStatus sampleFilePath fileMode newStat `shouldBe` 0o100606 atomicWriteFile filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- The default tempfile permissions are 0600, so this fails unless we -- make sure that the default umask is relied on for creation of the -- tempfile. fileMode resultStat `shouldBe` 0o100606 describe "atomicWriteFileWithMode" $ do it "writes contents to a file" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let path = joinPath [ tmpDir, "writeTest.tmp" ] atomicWriteFileWithMode 0o100777 path $ pack "just testing" contents <- readFile path contents `shouldBe` "just testing" it "changes the permissions of a previously created file, regardless of umask" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] writeFile filePath "initial contents" setFileMode filePath 0o100644 newStat <- getFileStatus filePath fileMode newStat `shouldBe` 0o100644 -- New files are created with 100600 perms. _ <- setFileCreationMask 0o100066 -- Create a new file once different mask is set and make sure that mask -- is applied. writeFile (joinPath [tmpDir, "sanityCheck"]) "with sanity check mask" sanityCheckStat <- getFileStatus $ joinPath [tmpDir, "sanityCheck"] fileMode sanityCheckStat `shouldBe` 0o100600 -- Since we move, this makes the new file assume the filemask of 0600 atomicWriteFileWithMode 0o100655 filePath $ pack "new contents" resultStat <- getFileStatus filePath -- reset mask to not break subsequent specs _ <- setFileCreationMask 0o100022 -- Fails when using atomic mv command unless apply perms on initial file fileMode resultStat `shouldBe` 0o100655 it "creates a new file with specified permissions" $ withSystemTempDirectory "atomicFileTest" $ \tmpDir -> do let filePath = joinPath [tmpDir, "testFile"] atomicWriteFileWithMode 0o100606 filePath $ pack "new contents" resultStat <- getFileStatus filePath fileMode resultStat `shouldBe` 0o100606 atomic-write-0.2.1.0/src/System/AtomicWrite/0000755000000000000000000000000007346545000016747 5ustar0000000000000000atomic-write-0.2.1.0/src/System/AtomicWrite/Internal.hs0000644000000000000000000000620007346545000021055 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Internal -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to create a temporary file with correct permissions -- atomically. module System.AtomicWrite.Internal where import System.Directory (doesFileExist, renameFile) import System.FilePath (takeDirectory) import System.IO (Handle, hClose, hSetBinaryMode, openTempFile, openTempFileWithDefaultPermissions) import System.Posix.Types (FileMode) import System.PosixCompat.Files (fileMode, getFileStatus, setFileMode) -- | Returns a temporary file with permissions correctly set. Chooses -- either previously-set permissions if the file that we're writing -- to existed, or permissions following the current umask. tempFileFor :: FilePath -- ^ The target filepath that we will replace atomically. -> IO (FilePath, Handle) tempFileFor targetFilePath = doesFileExist targetFilePath >>= tmpFile targetFilePath (takeDirectory targetFilePath) "atomic.write" where tmpFile :: FilePath -> FilePath -> String -> Bool -> IO (FilePath, Handle) tmpFile targetPath workingDirectory template previousExisted = if previousExisted then openTempFile workingDirectory template >>= \(tmpPath, handle) -> getFileStatus targetPath >>= setFileMode tmpPath . fileMode >> return (tmpPath, handle) else openTempFileWithDefaultPermissions workingDirectory template closeAndRename :: Handle -> FilePath -> FilePath -> IO () closeAndRename tmpHandle tempFile destFile = hClose tmpHandle >> renameFile tempFile destFile maybeSetFileMode :: FilePath -> Maybe FileMode -> IO () maybeSetFileMode path = maybe ( return () ) ( \mode -> setFileMode path mode ) -- Helper Function atomicWriteFileMaybeModeText :: Maybe FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> (Handle -> a -> IO ()) -- ^ The function to use to write on the file -> a -- ^ The content to write to the file -> IO () atomicWriteFileMaybeModeText mmode path hF text = tempFileFor path >>= \(tmpPath, h) -> hSetBinaryMode h False >> hF h text >> closeAndRename h tmpPath path >> maybeSetFileMode path mmode -- Helper Function atomicWriteFileMaybeModeBinary :: Maybe FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> (Handle -> a -> IO ()) -- ^ The function to use to write on the file -> a -- ^ The content to write to the file -> IO () atomicWriteFileMaybeModeBinary mmode path hF text = tempFileFor path >>= \(tmpPath, h) -> hSetBinaryMode h True >> hF h text >> closeAndRename h tmpPath path >> maybeSetFileMode path mmode atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/0000755000000000000000000000000007346545000020223 5ustar0000000000000000atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/ByteString.hs0000644000000000000000000000306107346545000022651 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.ByteString -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a ByteString -- to a file in text mode. module System.AtomicWrite.Writer.ByteString (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (atomicWriteFileMaybeModeText) import System.Posix.Types (FileMode) import Data.ByteString (ByteString, hPutStr) -- | Creates or modifies a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on POSIX-compliant -- systems and updates permissions. atomicWriteFileWithMode :: FileMode -> FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFileWithMode = atomicWriteFileMaybeMode . Just -- | Helper function atomicWriteFileMaybeMode :: Maybe FileMode -> FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path = atomicWriteFileMaybeModeText mmode path hPutStr atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/ByteString/0000755000000000000000000000000007346545000022315 5ustar0000000000000000atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/ByteString/Binary.hs0000644000000000000000000000330507346545000024076 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.ByteString.Binary -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a ByteString -- to a file open in binary mode module System.AtomicWrite.Writer.ByteString.Binary (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (atomicWriteFileMaybeModeBinary) import System.Posix.Types (FileMode) import Data.ByteString (ByteString, hPutStr) -- | Creates or modifies a file atomically on POSIX-compliant -- systems while preserving permissions. The file is opened in -- binary mode. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on POSIX-compliant -- systems and updates permissions. The file is opened in binary -- mode. atomicWriteFileWithMode :: FileMode -> FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFileWithMode mode = atomicWriteFileMaybeMode $ Just mode -- | Helper function for opening the file in binary mode. atomicWriteFileMaybeMode :: Maybe FileMode -> FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path = atomicWriteFileMaybeModeBinary mmode path hPutStr atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/ByteStringBuilder.hs0000644000000000000000000000425307346545000024164 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.ByteStringBuilder -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a ByteStringBuilder -- to a file. module System.AtomicWrite.Writer.ByteStringBuilder (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (closeAndRename, maybeSetFileMode, tempFileFor) import Data.ByteString.Builder (Builder, hPutBuilder) import GHC.IO.Handle (BufferMode (BlockBuffering), hSetBinaryMode, hSetBuffering) import System.Posix.Types (FileMode) -- | Creates or modifies a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> Builder -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on POSIX-compliant -- systems and updates permissions. atomicWriteFileWithMode :: FileMode -> FilePath -- ^ The path where the file will be updated or created -> Builder -- ^ The content to write to the file -> IO () atomicWriteFileWithMode mode = atomicWriteFileMaybeMode $ Just mode -- Helper function atomicWriteFileMaybeMode :: Maybe FileMode -> FilePath -- ^ The path where the file will be updated or created -> Builder -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path builder = do (temppath, h) <- tempFileFor path -- Recommendations for binary and buffering are from the -- Data.ByteString.Builder docs: -- http://hackage.haskell.org/package/bytestring-0.10.2.0/docs/Data-ByteString-Builder.html#v:hPutBuilder hSetBinaryMode h True hSetBuffering h (BlockBuffering Nothing) hPutBuilder h builder closeAndRename h temppath path -- set new permissions if a FileMode was provided maybeSetFileMode path mmode atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/LazyByteString.hs0000644000000000000000000000316307346545000023514 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.LazyByteString -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a Lazy ByteString -- to a file. module System.AtomicWrite.Writer.LazyByteString (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (atomicWriteFileMaybeModeText) import Data.ByteString.Lazy (ByteString, hPutStr) import System.Posix.Types (FileMode) -- | Creates or modifies a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on -- POSIX-compliant systems and updates permissions atomicWriteFileWithMode :: FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFileWithMode = atomicWriteFileMaybeMode . Just -- Helper Function atomicWriteFileMaybeMode :: Maybe FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path = atomicWriteFileMaybeModeText mmode path hPutStr atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/LazyByteString/0000755000000000000000000000000007346545000023155 5ustar0000000000000000atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/LazyByteString/Binary.hs0000644000000000000000000000322307346545000024735 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.LazyByteString.Binary -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a Lazy ByteString -- to a file in binary mode. module System.AtomicWrite.Writer.LazyByteString.Binary (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (atomicWriteFileMaybeModeBinary) import Data.ByteString.Lazy (ByteString, hPutStr) import System.Posix.Types (FileMode) -- | Creates or modifies a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on -- POSIX-compliant systems and updates permissions atomicWriteFileWithMode :: FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFileWithMode = atomicWriteFileMaybeMode . Just -- Helper Function atomicWriteFileMaybeMode :: Maybe FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> ByteString -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path = atomicWriteFileMaybeModeBinary mmode path hPutStr atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/LazyText.hs0000644000000000000000000000316307346545000022346 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.LazyText -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a Text -- to a file. module System.AtomicWrite.Writer.LazyText (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (atomicWriteFileMaybeModeText) import Data.Text.Lazy (Text) import Data.Text.Lazy.IO (hPutStr) import System.Posix.Types (FileMode) -- | Creates a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on -- POSIX-compliant systems and updates permissions atomicWriteFileWithMode :: FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFileWithMode = atomicWriteFileMaybeMode . Just -- Helper Function atomicWriteFileMaybeMode :: Maybe FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path = atomicWriteFileMaybeModeText mmode path hPutStr atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/LazyText/0000755000000000000000000000000007346545000022007 5ustar0000000000000000atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/LazyText/Binary.hs0000644000000000000000000000322307346545000023567 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.LazyText.Binary -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a Text -- to a file in binary mode. module System.AtomicWrite.Writer.LazyText.Binary (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (atomicWriteFileMaybeModeBinary) import Data.Text.Lazy (Text) import Data.Text.Lazy.IO (hPutStr) import System.Posix.Types (FileMode) -- | Creates a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on -- POSIX-compliant systems and updates permissions atomicWriteFileWithMode :: FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFileWithMode = atomicWriteFileMaybeMode . Just -- Helper Function atomicWriteFileMaybeMode :: Maybe FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path = atomicWriteFileMaybeModeBinary mmode path hPutStr atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/String.hs0000644000000000000000000000427207346545000022032 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.String -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a String -- to a file. module System.AtomicWrite.Writer.String (atomicWriteFile, atomicWithFile, atomicWriteFileWithMode, atomicWithFileAndMode) where import System.AtomicWrite.Internal (closeAndRename, maybeSetFileMode, tempFileFor) import System.IO (Handle, hPutStr) import System.Posix.Types (FileMode) -- | Creates or modifies a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> String -- ^ The content to write to the file -> IO () atomicWriteFile = (. flip hPutStr) . atomicWithFile -- | Creates or modifies a file atomically on -- POSIX-compliant systems and updates permissions atomicWriteFileWithMode :: FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> String -- ^ The content to write to the file -> IO () atomicWriteFileWithMode mode = ( . flip hPutStr) . atomicWithFileAndMode mode -- | A general version of 'atomicWriteFile' atomicWithFile :: FilePath -> (Handle -> IO ()) -> IO () atomicWithFile = atomicWithFileAndMaybeMode Nothing -- | A general version of 'atomicWriteFileWithMode' atomicWithFileAndMode :: FileMode -> FilePath -> (Handle -> IO ()) -> IO () atomicWithFileAndMode = atomicWithFileAndMaybeMode . Just -- | Helper function atomicWithFileAndMaybeMode :: Maybe FileMode -> FilePath -> (Handle -> IO ()) -> IO () atomicWithFileAndMaybeMode mmode path action = tempFileFor path >>= \(tmpPath, h) -> action h >> closeAndRename h tmpPath path >> maybeSetFileMode path mmode atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/String/0000755000000000000000000000000007346545000021471 5ustar0000000000000000atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/String/Binary.hs0000644000000000000000000000442407346545000023255 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.String.Binary -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a String -- to a file in binary mode. module System.AtomicWrite.Writer.String.Binary (atomicWriteFile, atomicWithFile, atomicWriteFileWithMode, atomicWithFileAndMode) where import System.AtomicWrite.Internal (closeAndRename, maybeSetFileMode, tempFileFor) import System.IO (Handle, hPutStr, hSetBinaryMode) import System.Posix.Types (FileMode) -- | Creates or modifies a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> String -- ^ The content to write to the file -> IO () atomicWriteFile = (. flip hPutStr) . atomicWithFile -- | Creates or modifies a file atomically on -- POSIX-compliant systems and updates permissions atomicWriteFileWithMode :: FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> String -- ^ The content to write to the file -> IO () atomicWriteFileWithMode mode = ( . flip hPutStr) . atomicWithFileAndMode mode -- | A general version of 'atomicWriteFile' atomicWithFile :: FilePath -> (Handle -> IO ()) -> IO () atomicWithFile = atomicWithFileAndMaybeMode Nothing -- | A general version of 'atomicWriteFileWithMode' atomicWithFileAndMode :: FileMode -> FilePath -> (Handle -> IO ()) -> IO () atomicWithFileAndMode = atomicWithFileAndMaybeMode . Just -- | Helper function atomicWithFileAndMaybeMode :: Maybe FileMode -> FilePath -> (Handle -> IO ()) -> IO () atomicWithFileAndMaybeMode mmode path action = tempFileFor path >>= \(tmpPath, h) -> hSetBinaryMode h True >> action h >> closeAndRename h tmpPath path >> maybeSetFileMode path mmode atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/Text.hs0000644000000000000000000000315307346545000021505 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.Text -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a Text -- to a file. module System.AtomicWrite.Writer.Text (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (atomicWriteFileMaybeModeText) import Data.Text (Text) import Data.Text.IO (hPutStr) import System.Posix.Types (FileMode) -- | Creates a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on -- POSIX-compliant systems and updates permissions atomicWriteFileWithMode :: FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFileWithMode = atomicWriteFileMaybeMode . Just -- Helper Function atomicWriteFileMaybeMode :: Maybe FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path = atomicWriteFileMaybeModeText mmode path hPutStr atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/Text/0000755000000000000000000000000007346545000021147 5ustar0000000000000000atomic-write-0.2.1.0/src/System/AtomicWrite/Writer/Text/Binary.hs0000644000000000000000000000321407346545000022727 0ustar0000000000000000-- | -- Module : System.AtomicWrite.Writer.Text.Binary -- Copyright : © 2015-2019 Stack Builders Inc. -- License : MIT -- -- Maintainer : Stack Builders -- Stability : experimental -- Portability : portable -- -- Provides functionality to dump the contents of a Text -- to a file in binary mode. module System.AtomicWrite.Writer.Text.Binary (atomicWriteFile, atomicWriteFileWithMode) where import System.AtomicWrite.Internal (atomicWriteFileMaybeModeBinary) import Data.Text (Text) import Data.Text.IO (hPutStr) import System.Posix.Types (FileMode) -- | Creates a file atomically on POSIX-compliant -- systems while preserving permissions. atomicWriteFile :: FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFile = atomicWriteFileMaybeMode Nothing -- | Creates or modifies a file atomically on -- POSIX-compliant systems and updates permissions atomicWriteFileWithMode :: FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFileWithMode = atomicWriteFileMaybeMode . Just -- Helper Function atomicWriteFileMaybeMode :: Maybe FileMode -- ^ The mode to set the file to -> FilePath -- ^ The path where the file will be updated or created -> Text -- ^ The content to write to the file -> IO () atomicWriteFileMaybeMode mmode path = atomicWriteFileMaybeModeBinary mmode path hPutStr