@@ -25,12 +25,15 @@ module System.Directory.Tree
2525 , extract , extractM
2626 -- **truncate tree to a maximum level
2727 , truncateAt
28+ -- **Copy, move, and remove directory trees
29+ , copyTo , moveTo , remove
2830 )where
2931
3032import System.IO.Unsafe (unsafeInterleaveIO )
3133import Unsafe.Coerce (unsafeCoerce )
32- import System.Directory (getDirectoryContents , doesDirectoryExist )
33- import System.FilePath ((</>) )
34+ import System.Directory (getDirectoryContents , doesDirectoryExist
35+ ,copyFile , renameFile , removeFile )
36+ import System.FilePath ((</>) , replaceDirectory )
3437import System.Posix.Files (getSymbolicLinkStatus , isSymbolicLink )
3538import Data.Tree (Tree (.. ), Forest )
3639import qualified Data.Tree as Tree (flatten )
@@ -43,6 +46,7 @@ import Control.Monad.Identity (runIdentity)
4346import Control.Applicative ((<$>) )
4447import Control.Arrow (second )
4548import Data.Maybe (mapMaybe )
49+ import Data.Function (on )
4650import Control.Cond (ifM , (<||>) , (<&&>) , notM )
4751
4852import Data.Default (Default (.. ))
@@ -113,6 +117,9 @@ getDir_ f Options {..} p = mkFSTree p <$> getChildren p
113117 ( f . fmap (mkFSTree c) . getChildren $ c' )
114118 ( return $ mkFSTree c [] )
115119
120+ isSymLink :: FilePath -> IO Bool
121+ isSymLink p = isSymbolicLink <$> getSymbolicLinkStatus p
122+
116123pop :: FSTree -> (FilePath , FSForest )
117124pop fs = (path, map prepend cs)
118125 where path = getL label fs
@@ -161,7 +168,6 @@ extractM_ p = foldrM extract' ([], DL.empty) . map prependPaths
161168 return (ts, FSTree t `cons` es)
162169 )
163170
164-
165171truncateAt :: TreeLens t a => Word -> [t ] -> [t ]
166172truncateAt n = mapMaybe (truncate' 0 )
167173 where
@@ -177,5 +183,19 @@ prependPaths (FSTree t) = modL children (map (prepend' root)) t
177183 prepend' parentPath = modL label (parentPath </> ) . prependChildren
178184 prependChildren fs = modL children (map (prepend' (rootLabel fs))) fs
179185
180- isSymLink :: FilePath -> IO Bool
181- isSymLink p = isSymbolicLink <$> getSymbolicLinkStatus p
186+
187+ copyTo :: FilePath -> FSTree -> IO FSTree
188+ copyTo = zipWithDestM copyFile
189+
190+ moveTo :: FilePath -> FSTree -> IO FSTree
191+ moveTo = zipWithDestM renameFile
192+
193+ remove :: FSTree -> IO ()
194+ remove = mapM_ removeFile . flatten
195+
196+ zipWithDestM :: Monad m =>
197+ (FilePath -> FilePath -> m () ) -> FilePath -> FSTree -> m FSTree
198+ zipWithDestM f dest fs = do
199+ sequence_ $ (zipWith f `on` flatten) fs destFs
200+ return destFs
201+ where destFs = modL label (`replaceDirectory` dest) fs
0 commit comments