atomic-write (empty) → 0.1.0.0
raw patch · 5 files changed
+161/−0 lines, 5 filesdep +basedep +directorydep +filepathsetup-changed
Dependencies added: base, directory, filepath, hspec, temporary, unix
Files
- LICENSE +20/−0
- Setup.hs +2/−0
- atomic-write.cabal +75/−0
- spec/Spec.hs +1/−0
- src/System/AtomicWrite.hs +63/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Justin Leitgeb++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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ atomic-write.cabal view
@@ -0,0 +1,75 @@+name: atomic-write+version: 0.1.0.0+synopsis: Atomically write to a file++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:+ .+ * <http://apidock.com/rails/File/atomic_write/class Ruby on Rails includes a similar method called atomic_write>+ * <https://github.com/chef/chef/blob/c4631816132fcfefaba3d123a1d0dfe8bc2866bb/lib/chef/file_content_management/deploy/mv_unix.rb#L23:L71 Chef includes atomic update functionality>+ * <https://github.com/sashka/atomicfile There is a python library for atomically updating a file>+ .+ Note that at this time Windows is not supported, however we would appreciate+ contributions to the <http://github.com/stackbuilders/atomic-write github repository>.+license: MIT+license-file: LICENSE+author: Justin Leitgeb+maintainer: justin@stackbuilders.com+copyright: 2015 Stack Builders Inc.+category: System+build-type: Simple+-- extra-source-files:+cabal-version: >=1.10++library+ exposed-modules: System.AtomicWrite+ -- other-modules:+ -- other-extensions:+ build-depends: base >=4.5 && <4.8+ , temporary+ , unix+ , directory+ , filepath++ hs-source-dirs: src+ default-language: Haskell2010+ ghc-options: -Wall++test-suite atomic-write-test+ type: exitcode-stdio-1.0+ hs-source-dirs: spec, src+ main-is: Spec.hs++ build-depends: base >=4.5 && <4.8+ , temporary+ , unix+ , directory+ , filepath++ , hspec++ default-language: Haskell2010+ ghc-options: -Wall+++source-repository head+ type: git+ location: https://github.com/stackbuilders/atomic-file
+ spec/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ src/System/AtomicWrite.hs view
@@ -0,0 +1,63 @@+-- |+-- Module : System.AtomicWrite+-- Copyright : (c) 2015 Stack Builders Inc.+--+-- License : MIT+-- Maintainer : justin@stackbuilders.com+-- Stability : experimental+-- Portability : GHC+--+-- A library for atomically modifying files while preserving permissions+--++module System.AtomicWrite (atomicWriteFile) where++import System.Directory (renameFile, doesFileExist)+import System.FilePath.Posix (takeDirectory)+import System.IO+ (Handle, openTempFile, openTempFileWithDefaultPermissions, hPutStr, hClose)++import System.Posix.Files (setFileMode, getFileStatus, fileMode)+++-- | Creates 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 f txt = do+ (temppath, h) <- tempFileFor f++ hPutStr h txt+ hClose h++ renameFile temppath f+++-- | 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 -> IO (FilePath, Handle)+tempFileFor originalFilePath = do+ let targetDirectory = takeDirectory originalFilePath++ doesFileExist originalFilePath >>=+ tmpFile originalFilePath targetDirectory "atomic.write"++ where++ tmpFile :: FilePath -> FilePath -> String -> Bool -> IO (FilePath, Handle)+ tmpFile originalPath workingDirectory template previousExisted =++ if previousExisted then do+ (temppath, handle) <- openTempFile workingDirectory template++ oldStat <- getFileStatus originalPath++ setFileMode temppath $ fileMode oldStat++ return (temppath, handle)++ else+ openTempFileWithDefaultPermissions workingDirectory template