Parameterise modifyWith.

This commit is contained in:
Bryan O'Sullivan 2007-04-30 20:11:13 +00:00
parent 67cff2bdbe
commit aa9629005c
1 changed files with 36 additions and 19 deletions

View File

@ -1,5 +1,8 @@
{-# OPTIONS_GHC -fglasgow-exts #-}
module System.FilePath.Manip ( module System.FilePath.Manip (
renameWith Modifiable(..)
, renameWith
, modifyWith , modifyWith
, modifyWithBackup , modifyWithBackup
, modifyInPlace , modifyInPlace
@ -9,19 +12,45 @@ import Control.Exception (bracket, bracket_, handle, throwIO)
import Control.Monad (liftM) import Control.Monad (liftM)
import Data.Bits ((.&.)) import Data.Bits ((.&.))
import System.Directory (removeFile) import System.Directory (removeFile)
import System.IO (IOMode(..), hClose, openFile) import System.IO (Handle, IOMode(..), hClose, hGetContents, hPutStr, openFile)
import System.Posix.Files (fileMode, getFileStatus, rename, setFileMode) import System.Posix.Files (fileMode, getFileStatus, rename, setFileMode)
import System.Posix.Temp (mkstemp) import System.Posix.Temp (mkstemp)
import Data.ByteString.Base (ByteString, LazyByteString)
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as L import qualified Data.ByteString.Lazy.Char8 as L
renameWith :: (FilePath -> FilePath) -> FilePath -> IO () renameWith :: (FilePath -> FilePath) -> FilePath -> IO ()
renameWith f path = rename path (f path) renameWith f path = rename path (f path)
modifyWith :: (FilePath -> FilePath -> IO ()) class Modifiable a where
-> (L.ByteString -> L.ByteString) pipeline :: (a -> a) -> Handle -> Handle -> IO ()
-> FilePath
-> IO () instance Modifiable ByteString where
pipeline f ih oh = B.hGetContents ih >>= return . f >>= B.hPut oh
instance Modifiable LazyByteString where
pipeline f ih oh = L.hGetContents ih >>= return . f >>= L.hPut oh
instance Modifiable String where
pipeline f ih oh = hGetContents ih >>= return . f >>= hPutStr oh
modifyInPlace :: Modifiable a => (a -> a) -> FilePath -> IO ()
modifyInPlace = modifyWith (flip rename)
modifyWithBackup :: Modifiable a => (FilePath -> FilePath)
-> (a -> a)
-> FilePath
-> IO ()
modifyWithBackup f = modifyWith backup
where backup path tmpPath = renameWith f path >> rename tmpPath path
modifyWith :: Modifiable a => (FilePath -> FilePath -> IO ())
-> (a -> a)
-> FilePath
-> IO ()
modifyWith after transform path = modifyWith after transform path =
bracket (openFile path ReadMode) hClose $ \ih -> do bracket (openFile path ReadMode) hClose $ \ih -> do
@ -30,20 +59,8 @@ modifyWith after transform path =
nukeTmp = handle (const ignore) (removeFile tmpPath) nukeTmp = handle (const ignore) (removeFile tmpPath)
handle (\e -> nukeTmp >> throwIO e) $ do handle (\e -> nukeTmp >> throwIO e) $ do
bracket_ ignore (hClose oh) $ bracket_ ignore (hClose oh) $
transform `liftM` L.hGetContents ih >>= L.hPut oh pipeline transform ih oh
handle (const nukeTmp) $ do handle (const nukeTmp) $ do
mode <- fileMode `liftM` getFileStatus path mode <- fileMode `liftM` getFileStatus path
setFileMode tmpPath (mode .&. 0777) setFileMode tmpPath (mode .&. 0777)
after path tmpPath after path tmpPath
modifyInPlace :: (L.ByteString -> L.ByteString) -> FilePath -> IO ()
modifyInPlace = modifyWith (flip rename)
modifyWithBackup :: (FilePath -> FilePath)
-> (L.ByteString -> L.ByteString)
-> FilePath
-> IO ()
modifyWithBackup f = modifyWith backup
where backup path tmpPath = renameWith f path >> rename tmpPath path