module System where
import Control.Monad
import qualified Control.Monad.Parallel as P
import Data.List
import System.Directory
import System.FilePath.Posix
type FilesPredicate = [FilePath] -> Bool
type StopSearchingPredicate = [FilePath] -> Bool
listDirectoriesRecursive :: FilesPredicate -> StopSearchingPredicate -> FilePath -> IO [FilePath]
listDirectoriesRecursive predicate stopSearchingPredicate absPath =
do let path = appendSeparatorIfNeeded absPath
subDirectories <- listDirectories path
let predicateMatch = predicate subDirectories
let stopSearchingMatch = stopSearchingPredicate subDirectories
if null subDirectories then return []
else if predicateMatch then return [path]
else if stopSearchingMatch then return []
else do restOfDirectories <- mapM (listDirectoriesRecursive predicate stopSearchingPredicate) subDirectories
if predicateMatch then do let restOfGitDirectories = concat restOfDirectories
return (path : restOfGitDirectories)
else return (concat restOfDirectories)
listDirectories :: FilePath -> IO [FilePath]
listDirectories path = do subFilesAndSubDirectories <- listDirectory path
let absolutePath = map (\sub -> path ++ sub) subFilesAndSubDirectories
absPathsWithSeparators = map appendSeparatorIfNeeded absolutePath
filterM isDirectory absPathsWithSeparators
isDirectory :: FilePath -> IO Bool
isDirectory absolutePath = do let isHidden = "." `isPrefixOf` absolutePath
isDirectory <- doesDirectoryExist absolutePath
return (isDirectory && not isHidden)
appendSeparatorIfNeeded :: String -> String
appendSeparatorIfNeeded absPath
| last absPath == pathSeparator = absPath
| otherwise = absPath ++ separator
separator = [pathSeparator]