Parameterise modifyWith.

--HG--
extra : convert_revision : 719d7cb72f1ba1a11228a2ee65a41f47a2d04de7
This commit is contained in:
Bryan O'Sullivan 2007-04-30 20:11:13 +00:00
parent ec2fcb2c4a
commit c5ccd0a6ab
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