From c5ccd0a6ab0a87359b6adf87fbda2faf50d57554 Mon Sep 17 00:00:00 2001 From: Bryan O'Sullivan Date: Mon, 30 Apr 2007 20:11:13 +0000 Subject: [PATCH] Parameterise modifyWith. --HG-- extra : convert_revision : 719d7cb72f1ba1a11228a2ee65a41f47a2d04de7 --- System/FilePath/Manip.hs | 55 ++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/System/FilePath/Manip.hs b/System/FilePath/Manip.hs index 0883be2..f1cfc59 100644 --- a/System/FilePath/Manip.hs +++ b/System/FilePath/Manip.hs @@ -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