{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
module CabalFmt.Monad (
MonadCabalFmt (..),
getFiles,
Contents (..),
CabalFmt,
runCabalFmt,
CabalFmtIO,
runCabalFmtIO,
) where
import Control.Exception
(IOException, catch, displayException, throwIO, try)
import Control.Monad (when)
import Control.Monad.Except (MonadError (..))
import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks, runReaderT)
import Control.Monad.Writer (WriterT, runWriterT, tell)
import Data.Bifunctor (first)
import Data.List (isPrefixOf, stripPrefix)
import Data.Maybe (mapMaybe)
import System.Exit (exitFailure)
import System.FilePath (pathSeparator, (</>))
import System.IO (hPutStrLn, stderr)
import qualified Data.ByteString as BS
import qualified Data.Map as Map
import qualified System.Directory as D
import CabalFmt.Error
import CabalFmt.Options
class (HasOptions r, MonadReader r m, MonadError Error m) => MonadCabalFmt r m | m -> r where
listDirectory :: FilePath -> m [FilePath]
doesDirectoryExist :: FilePath -> m Bool
readFileBS :: FilePath -> m Contents
displayWarning :: String -> m ()
data Contents
= Contents BS.ByteString
| NoIO
| IOError String
newtype CabalFmt a = CabalFmt { forall a.
CabalFmt a
-> ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
unCabalFmt :: ReaderT (Options, Map.Map FilePath BS.ByteString) (WriterT [String] (Either Error)) a }
deriving newtype (forall a b. a -> CabalFmt b -> CabalFmt a
forall a b. (a -> b) -> CabalFmt a -> CabalFmt b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> CabalFmt b -> CabalFmt a
$c<$ :: forall a b. a -> CabalFmt b -> CabalFmt a
fmap :: forall a b. (a -> b) -> CabalFmt a -> CabalFmt b
$cfmap :: forall a b. (a -> b) -> CabalFmt a -> CabalFmt b
Functor, Functor CabalFmt
forall a. a -> CabalFmt a
forall a b. CabalFmt a -> CabalFmt b -> CabalFmt a
forall a b. CabalFmt a -> CabalFmt b -> CabalFmt b
forall a b. CabalFmt (a -> b) -> CabalFmt a -> CabalFmt b
forall a b c.
(a -> b -> c) -> CabalFmt a -> CabalFmt b -> CabalFmt c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: forall a b. CabalFmt a -> CabalFmt b -> CabalFmt a
$c<* :: forall a b. CabalFmt a -> CabalFmt b -> CabalFmt a
*> :: forall a b. CabalFmt a -> CabalFmt b -> CabalFmt b
$c*> :: forall a b. CabalFmt a -> CabalFmt b -> CabalFmt b
liftA2 :: forall a b c.
(a -> b -> c) -> CabalFmt a -> CabalFmt b -> CabalFmt c
$cliftA2 :: forall a b c.
(a -> b -> c) -> CabalFmt a -> CabalFmt b -> CabalFmt c
<*> :: forall a b. CabalFmt (a -> b) -> CabalFmt a -> CabalFmt b
$c<*> :: forall a b. CabalFmt (a -> b) -> CabalFmt a -> CabalFmt b
pure :: forall a. a -> CabalFmt a
$cpure :: forall a. a -> CabalFmt a
Applicative, Applicative CabalFmt
forall a. a -> CabalFmt a
forall a b. CabalFmt a -> CabalFmt b -> CabalFmt b
forall a b. CabalFmt a -> (a -> CabalFmt b) -> CabalFmt b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> CabalFmt a
$creturn :: forall a. a -> CabalFmt a
>> :: forall a b. CabalFmt a -> CabalFmt b -> CabalFmt b
$c>> :: forall a b. CabalFmt a -> CabalFmt b -> CabalFmt b
>>= :: forall a b. CabalFmt a -> (a -> CabalFmt b) -> CabalFmt b
$c>>= :: forall a b. CabalFmt a -> (a -> CabalFmt b) -> CabalFmt b
Monad, MonadError Error)
instance MonadReader Options CabalFmt where
ask :: CabalFmt Options
ask = forall a.
ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
-> CabalFmt a
CabalFmt forall a b. (a -> b) -> a -> b
$ forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks forall a b. (a, b) -> a
fst
local :: forall a. (Options -> Options) -> CabalFmt a -> CabalFmt a
local Options -> Options
f (CabalFmt ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
m) = forall a.
ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
-> CabalFmt a
CabalFmt forall a b. (a -> b) -> a -> b
$ forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Options -> Options
f) ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
m
instance MonadCabalFmt Options CabalFmt where
listDirectory :: FilePath -> CabalFmt [FilePath]
listDirectory FilePath
dir = forall a.
ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
-> CabalFmt a
CabalFmt forall a b. (a -> b) -> a -> b
$ do
Map FilePath ByteString
files <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks forall a b. (a, b) -> b
snd
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe FilePath -> Maybe FilePath
f (forall k a. Map k a -> [k]
Map.keys Map FilePath ByteString
files)
where
f :: FilePath -> Maybe FilePath
f :: FilePath -> Maybe FilePath
f FilePath
fp = do
FilePath
rest <- forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix (FilePath
dir forall a. [a] -> [a] -> [a]
++ [Char
pathSeparator]) FilePath
fp
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
takeWhile (forall a. Eq a => a -> a -> Bool
/= Char
pathSeparator) FilePath
rest
doesDirectoryExist :: FilePath -> CabalFmt Bool
doesDirectoryExist FilePath
dir = forall a.
ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
-> CabalFmt a
CabalFmt forall a b. (a -> b) -> a -> b
$ do
Map FilePath ByteString
files <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks forall a b. (a, b) -> b
snd
forall (m :: * -> *) a. Monad m => a -> m a
return (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (forall a. Eq a => [a] -> [a] -> Bool
isPrefixOf (FilePath
dir forall a. [a] -> [a] -> [a]
++ [Char
pathSeparator])) (forall k a. Map k a -> [k]
Map.keys Map FilePath ByteString
files))
readFileBS :: FilePath -> CabalFmt Contents
readFileBS FilePath
p = forall a.
ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
-> CabalFmt a
CabalFmt forall a b. (a -> b) -> a -> b
$ do
Map FilePath ByteString
files <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks forall a b. (a, b) -> b
snd
forall (m :: * -> *) a. Monad m => a -> m a
return (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (FilePath -> Contents
IOError FilePath
"doesn't exist") ByteString -> Contents
Contents forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
p Map FilePath ByteString
files)
displayWarning :: FilePath -> CabalFmt ()
displayWarning FilePath
w = do
Bool
werror <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Options -> Bool
optError
if Bool
werror
then forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$ FilePath -> Error
WarningError FilePath
w
else forall a.
ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
-> CabalFmt a
CabalFmt forall a b. (a -> b) -> a -> b
$ forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell [FilePath
w]
runCabalFmt
:: Map.Map FilePath BS.ByteString -> Options
-> CabalFmt a -> Either Error (a, [String])
runCabalFmt :: forall a.
Map FilePath ByteString
-> Options -> CabalFmt a -> Either Error (a, [FilePath])
runCabalFmt Map FilePath ByteString
files Options
opts CabalFmt a
m = forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (forall a.
CabalFmt a
-> ReaderT
(Options, Map FilePath ByteString)
(WriterT [FilePath] (Either Error))
a
unCabalFmt CabalFmt a
m) (Options
opts, Map FilePath ByteString
files))
data Options' = Options'
{ Options' -> Maybe FilePath
optRootDir :: Maybe FilePath
, Options' -> Options
optOpt :: Options
}
instance HasOptions Options' where
options :: forall (f :: * -> *). Functor f => LensLike' f Options' Options
options Options -> f Options
f (Options' Maybe FilePath
mfp Options
o) = Maybe FilePath -> Options -> Options'
Options' Maybe FilePath
mfp forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Options -> f Options
f Options
o
newtype CabalFmtIO a = CabalFmtIO { forall a. CabalFmtIO a -> ReaderT Options' IO a
unCabalFmtIO :: ReaderT Options' IO a }
deriving newtype (forall a b. a -> CabalFmtIO b -> CabalFmtIO a
forall a b. (a -> b) -> CabalFmtIO a -> CabalFmtIO b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> CabalFmtIO b -> CabalFmtIO a
$c<$ :: forall a b. a -> CabalFmtIO b -> CabalFmtIO a
fmap :: forall a b. (a -> b) -> CabalFmtIO a -> CabalFmtIO b
$cfmap :: forall a b. (a -> b) -> CabalFmtIO a -> CabalFmtIO b
Functor, Functor CabalFmtIO
forall a. a -> CabalFmtIO a
forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO a
forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO b
forall a b. CabalFmtIO (a -> b) -> CabalFmtIO a -> CabalFmtIO b
forall a b c.
(a -> b -> c) -> CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO a
$c<* :: forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO a
*> :: forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO b
$c*> :: forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO b
liftA2 :: forall a b c.
(a -> b -> c) -> CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO c
$cliftA2 :: forall a b c.
(a -> b -> c) -> CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO c
<*> :: forall a b. CabalFmtIO (a -> b) -> CabalFmtIO a -> CabalFmtIO b
$c<*> :: forall a b. CabalFmtIO (a -> b) -> CabalFmtIO a -> CabalFmtIO b
pure :: forall a. a -> CabalFmtIO a
$cpure :: forall a. a -> CabalFmtIO a
Applicative, Applicative CabalFmtIO
forall a. a -> CabalFmtIO a
forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO b
forall a b. CabalFmtIO a -> (a -> CabalFmtIO b) -> CabalFmtIO b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> CabalFmtIO a
$creturn :: forall a. a -> CabalFmtIO a
>> :: forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO b
$c>> :: forall a b. CabalFmtIO a -> CabalFmtIO b -> CabalFmtIO b
>>= :: forall a b. CabalFmtIO a -> (a -> CabalFmtIO b) -> CabalFmtIO b
$c>>= :: forall a b. CabalFmtIO a -> (a -> CabalFmtIO b) -> CabalFmtIO b
Monad, Monad CabalFmtIO
forall a. IO a -> CabalFmtIO a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: forall a. IO a -> CabalFmtIO a
$cliftIO :: forall a. IO a -> CabalFmtIO a
MonadIO, MonadReader Options')
instance MonadError Error CabalFmtIO where
throwError :: forall a. Error -> CabalFmtIO a
throwError = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e a. Exception e => e -> IO a
throwIO
catchError :: forall a. CabalFmtIO a -> (Error -> CabalFmtIO a) -> CabalFmtIO a
catchError CabalFmtIO a
m Error -> CabalFmtIO a
h = forall a. ReaderT Options' IO a -> CabalFmtIO a
CabalFmtIO forall a b. (a -> b) -> a -> b
$ forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT forall a b. (a -> b) -> a -> b
$ \Options'
r ->
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch (forall {a}. Options' -> CabalFmtIO a -> IO a
unCabalFmtIO' Options'
r CabalFmtIO a
m) (forall {a}. Options' -> CabalFmtIO a -> IO a
unCabalFmtIO' Options'
r forall b c a. (b -> c) -> (a -> b) -> a -> c
. Error -> CabalFmtIO a
h)
where
unCabalFmtIO' :: Options' -> CabalFmtIO a -> IO a
unCabalFmtIO' Options'
r CabalFmtIO a
m' = forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (forall a. CabalFmtIO a -> ReaderT Options' IO a
unCabalFmtIO CabalFmtIO a
m') Options'
r
instance MonadCabalFmt Options' CabalFmtIO where
listDirectory :: FilePath -> CabalFmtIO [FilePath]
listDirectory FilePath
p = do
Maybe FilePath
rd <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Options' -> Maybe FilePath
optRootDir
case Maybe FilePath
rd of
Maybe FilePath
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return []
Just FilePath
d -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO [FilePath]
D.listDirectory (FilePath
d FilePath -> FilePath -> FilePath
</> FilePath
p))
doesDirectoryExist :: FilePath -> CabalFmtIO Bool
doesDirectoryExist FilePath
p = do
Maybe FilePath
rd <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Options' -> Maybe FilePath
optRootDir
case Maybe FilePath
rd of
Maybe FilePath
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
Just FilePath
d -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO Bool
D.doesDirectoryExist (FilePath
d FilePath -> FilePath -> FilePath
</> FilePath
p))
readFileBS :: FilePath -> CabalFmtIO Contents
readFileBS FilePath
p = do
Maybe FilePath
rd <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Options' -> Maybe FilePath
optRootDir
case Maybe FilePath
rd of
Maybe FilePath
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return Contents
NoIO
Just FilePath
d -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ IO ByteString -> IO Contents
catchIOError forall a b. (a -> b) -> a -> b
$ FilePath -> IO ByteString
BS.readFile (FilePath
d FilePath -> FilePath -> FilePath
</> FilePath
p)
displayWarning :: FilePath -> CabalFmtIO ()
displayWarning FilePath
w = do
Bool
werror <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (Options -> Bool
optError forall b c a. (b -> c) -> (a -> b) -> a -> c
. Options' -> Options
optOpt)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
Handle -> FilePath -> IO ()
hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ (if Bool
werror then FilePath
"ERROR: " else FilePath
"WARNING: ") forall a. [a] -> [a] -> [a]
++ FilePath
w
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
werror forall a. IO a
exitFailure
catchIOError :: IO BS.ByteString -> IO Contents
catchIOError :: IO ByteString -> IO Contents
catchIOError IO ByteString
m = forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Contents
Contents IO ByteString
m) IOException -> IO Contents
handler where
handler :: IOException -> IO Contents
handler :: IOException -> IO Contents
handler IOException
exc = forall (m :: * -> *) a. Monad m => a -> m a
return (FilePath -> Contents
IOError (forall e. Exception e => e -> FilePath
displayException IOException
exc))
runCabalFmtIO :: Maybe FilePath -> Options -> CabalFmtIO a -> IO (Either Error a)
runCabalFmtIO :: forall a.
Maybe FilePath -> Options -> CabalFmtIO a -> IO (Either Error a)
runCabalFmtIO Maybe FilePath
mfp Options
opts CabalFmtIO a
m = forall e a. Exception e => IO a -> IO (Either e a)
try forall a b. (a -> b) -> a -> b
$ forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (forall a. CabalFmtIO a -> ReaderT Options' IO a
unCabalFmtIO CabalFmtIO a
m) (Maybe FilePath -> Options -> Options'
Options' Maybe FilePath
mfp Options
opts)
getFiles :: MonadCabalFmt r m => FilePath -> m [FilePath]
getFiles :: forall r (m :: * -> *).
MonadCabalFmt r m =>
FilePath -> m [FilePath]
getFiles = forall (m :: * -> *) r.
MonadCabalFmt r m =>
(FilePath -> Bool) -> FilePath -> m [FilePath]
getDirectoryContentsRecursive' FilePath -> Bool
check where
check :: FilePath -> Bool
check FilePath
"dist-newstyle" = Bool
False
check (Char
'.' : FilePath
_) = Bool
False
check FilePath
_ = Bool
True
getDirectoryContentsRecursive'
:: forall m r. MonadCabalFmt r m
=> (FilePath -> Bool)
-> FilePath
-> m [FilePath]
getDirectoryContentsRecursive' :: forall (m :: * -> *) r.
MonadCabalFmt r m =>
(FilePath -> Bool) -> FilePath -> m [FilePath]
getDirectoryContentsRecursive' FilePath -> Bool
ignore' FilePath
topdir = [FilePath] -> m [FilePath]
recurseDirectories [FilePath
""]
where
recurseDirectories :: [FilePath] -> m [FilePath]
recurseDirectories :: [FilePath] -> m [FilePath]
recurseDirectories [] = forall (m :: * -> *) a. Monad m => a -> m a
return []
recurseDirectories (FilePath
dir:[FilePath]
dirs) = do
([FilePath]
files, [FilePath]
dirs') <- forall {m :: * -> *} {r}.
MonadCabalFmt r m =>
[FilePath]
-> [FilePath] -> [FilePath] -> m ([FilePath], [FilePath])
collect [] [] forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall r (m :: * -> *).
MonadCabalFmt r m =>
FilePath -> m [FilePath]
listDirectory (FilePath
topdir FilePath -> FilePath -> FilePath
</> FilePath
dir)
[FilePath]
files' <- [FilePath] -> m [FilePath]
recurseDirectories ([FilePath]
dirs' forall a. [a] -> [a] -> [a]
++ [FilePath]
dirs)
forall (m :: * -> *) a. Monad m => a -> m a
return ([FilePath]
files forall a. [a] -> [a] -> [a]
++ [FilePath]
files')
where
collect :: [FilePath]
-> [FilePath] -> [FilePath] -> m ([FilePath], [FilePath])
collect [FilePath]
files [FilePath]
dirs' [] = forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. [a] -> [a]
reverse [FilePath]
files
,forall a. [a] -> [a]
reverse [FilePath]
dirs')
collect [FilePath]
files [FilePath]
dirs' (FilePath
entry:[FilePath]
entries) | FilePath -> Bool
ignore FilePath
entry
= [FilePath]
-> [FilePath] -> [FilePath] -> m ([FilePath], [FilePath])
collect [FilePath]
files [FilePath]
dirs' [FilePath]
entries
collect [FilePath]
files [FilePath]
dirs' (FilePath
entry:[FilePath]
entries) = do
let dirEntry :: FilePath
dirEntry = FilePath
dir FilePath -> FilePath -> FilePath
</> FilePath
entry
Bool
isDirectory <- forall r (m :: * -> *). MonadCabalFmt r m => FilePath -> m Bool
doesDirectoryExist (FilePath
topdir FilePath -> FilePath -> FilePath
</> FilePath
dirEntry)
if Bool
isDirectory
then [FilePath]
-> [FilePath] -> [FilePath] -> m ([FilePath], [FilePath])
collect [FilePath]
files (FilePath
dirEntryforall a. a -> [a] -> [a]
:[FilePath]
dirs') [FilePath]
entries
else [FilePath]
-> [FilePath] -> [FilePath] -> m ([FilePath], [FilePath])
collect (FilePath
dirEntryforall a. a -> [a] -> [a]
:[FilePath]
files) [FilePath]
dirs' [FilePath]
entries
ignore :: FilePath -> Bool
ignore [Char
'.'] = Bool
True
ignore [Char
'.', Char
'.'] = Bool
True
ignore FilePath
x = Bool -> Bool
not (FilePath -> Bool
ignore' FilePath
x)