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