packages feed

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 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