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 (
renameWith
Modifiable(..)
, renameWith
, modifyWith
, modifyWithBackup
, modifyInPlace
@ -9,19 +12,45 @@ import Control.Exception (bracket, bracket_, handle, throwIO)
import Control.Monad (liftM)
import Data.Bits ((.&.))
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.Temp (mkstemp)
import Data.ByteString.Base (ByteString, LazyByteString)
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as L
renameWith :: (FilePath -> FilePath) -> FilePath -> IO ()
renameWith f path = rename path (f path)
modifyWith :: (FilePath -> FilePath -> IO ())
-> (L.ByteString -> L.ByteString)
-> FilePath
-> IO ()
class Modifiable a where
pipeline :: (a -> a) -> Handle -> Handle -> 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 =
bracket (openFile path ReadMode) hClose $ \ih -> do
@ -30,20 +59,8 @@ modifyWith after transform path =
nukeTmp = handle (const ignore) (removeFile tmpPath)
handle (\e -> nukeTmp >> throwIO e) $ do
bracket_ ignore (hClose oh) $
transform `liftM` L.hGetContents ih >>= L.hPut oh
pipeline transform ih oh
handle (const nukeTmp) $ do
mode <- fileMode `liftM` getFileStatus path
setFileMode tmpPath (mode .&. 0777)
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