aboutsummaryrefslogtreecommitdiff
path: root/Utility/Directory.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2012-06-18 12:53:57 -0400
committerGravatar Joey Hess <joey@kitenet.net>2012-06-18 12:53:57 -0400
commitdc3d9d1e982f7342dd3e2b3fc14fbbe85e7acd3e (patch)
tree12644c4de83a7007eaa66a55f7ccf60ad5102c6d /Utility/Directory.hs
parent3c8a9043b6fc8fafbeac16e8f9199a0d12870549 (diff)
added dirTree
Diffstat (limited to 'Utility/Directory.hs')
-rw-r--r--Utility/Directory.hs29
1 files changed, 28 insertions, 1 deletions
diff --git a/Utility/Directory.hs b/Utility/Directory.hs
index 78bb6e701..b8ed63a36 100644
--- a/Utility/Directory.hs
+++ b/Utility/Directory.hs
@@ -34,7 +34,7 @@ dirCruft _ = False
dirContents :: FilePath -> IO [FilePath]
dirContents d = map (d </>) . filter (not . dirCruft) <$> getDirectoryContents d
-{- Gets contents of directory, and then its subdirectories, recursively,
+{- Gets files in a directory, and then its subdirectories, recursively,
- and lazily. -}
dirContentsRecursive :: FilePath -> IO [FilePath]
dirContentsRecursive topdir = dirContentsRecursive' topdir [""]
@@ -56,6 +56,33 @@ dirContentsRecursive' topdir (dir:dirs) = unsafeInterleaveIO $ do
, collect (dirEntry:files) dirs' entries
)
+{- Gets the subdirectories in a directory, and their subdirectories,
+ - recursively, and lazily. Prunes sections of the tree matching a
+ - condition. -}
+dirTree :: FilePath -> (FilePath -> Bool) -> IO [FilePath]
+dirTree topdir prune
+ | prune topdir = return []
+ | otherwise = (:) topdir <$> dirTree' topdir prune [""]
+
+dirTree' :: FilePath -> (FilePath -> Bool) -> [FilePath] -> IO [FilePath]
+dirTree' _ _ [] = return []
+dirTree' topdir prune (dir:dirs)
+ | prune dir = dirTree' topdir prune dirs
+ | otherwise = unsafeInterleaveIO $ do
+ subdirs <- collect [] =<< dirContents (topdir </> dir)
+ subdirs' <- dirTree' topdir prune (subdirs ++ dirs)
+ return $ subdirs ++ subdirs'
+ where
+ collect dirs' [] = return dirs'
+ collect dirs' (entry:entries)
+ | dirCruft entry || prune entry = collect dirs' entries
+ | otherwise = do
+ let dirEntry = dir </> entry
+ ifM (doesDirectoryExist $ topdir </> dirEntry)
+ ( collect (dirEntry:dirs') entries
+ , collect dirs' entries
+ )
+
{- Moves one filename to another.
- First tries a rename, but falls back to moving across devices if needed. -}
moveFile :: FilePath -> FilePath -> IO ()