summaryrefslogtreecommitdiff
path: root/Utility/Directory.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2012-06-03 14:33:35 -0400
committerGravatar Joey Hess <joey@kitenet.net>2012-06-03 14:33:35 -0400
commitc74f39843bd07fa86cfa2b1261912013caa05f55 (patch)
tree3e7b9da0aac366371f49e2c422587db439fb5059 /Utility/Directory.hs
parentc5412ca7fed26dcc294c5873a07a28f174b255ce (diff)
parent0064fc0beb98e7254dc026b614bad2e5518ea5dc (diff)
Merge branch 'master' of ssh://git-annex.branchable.com
Conflicts: doc/tips/using_Amazon_S3.mdwn
Diffstat (limited to 'Utility/Directory.hs')
-rw-r--r--Utility/Directory.hs32
1 files changed, 28 insertions, 4 deletions
diff --git a/Utility/Directory.hs b/Utility/Directory.hs
index 3041361df..5bfd49a9c 100644
--- a/Utility/Directory.hs
+++ b/Utility/Directory.hs
@@ -17,6 +17,7 @@ import System.FilePath
import Control.Applicative
import Control.Exception (bracket_)
import System.Posix.Directory
+import System.IO.Unsafe (unsafeInterleaveIO)
import Utility.SafeCommand
import Utility.TempFile
@@ -24,14 +25,37 @@ import Utility.Exception
import Utility.Monad
import Utility.Path
+dirCruft :: FilePath -> Bool
+dirCruft "." = True
+dirCruft ".." = True
+dirCruft _ = False
+
{- Lists the contents of a directory.
- Unlike getDirectoryContents, paths are not relative to the directory. -}
dirContents :: FilePath -> IO [FilePath]
-dirContents d = map (d </>) . filter notcruft <$> getDirectoryContents d
+dirContents d = map (d </>) . filter (not . dirCruft) <$> getDirectoryContents d
+
+{- Gets contents of directory, and then its subdirectories, recursively,
+ - and lazily. -}
+dirContentsRecursive :: FilePath -> IO [FilePath]
+dirContentsRecursive topdir = dirContentsRecursive' topdir [""]
+
+dirContentsRecursive' :: FilePath -> [FilePath] -> IO [FilePath]
+dirContentsRecursive' _ [] = return []
+dirContentsRecursive' topdir (dir:dirs) = unsafeInterleaveIO $ do
+ (files, dirs') <- collect [] [] =<< dirContents (topdir </> dir)
+ files' <- dirContentsRecursive' topdir (dirs' ++ dirs)
+ return (files ++ files')
where
- notcruft "." = False
- notcruft ".." = False
- notcruft _ = True
+ collect files dirs' [] = return (reverse files, reverse dirs')
+ collect files dirs' (entry:entries)
+ | dirCruft entry = collect files dirs' entries
+ | otherwise = do
+ let dirEntry = dir </> entry
+ ifM (doesDirectoryExist $ topdir </> dirEntry)
+ ( collect files (dirEntry:dirs') entries
+ , collect (dirEntry:files) dirs' entries
+ )
{- Moves one filename to another.
- First tries a rename, but falls back to moving across devices if needed. -}