module Data.Conduit.Filesystem
( traverse
, sourceFile
, sinkFile
) where
import Prelude hiding (FilePath)
import Control.Monad.IO.Class (MonadIO, liftIO)
import qualified Data.Conduit as C
import qualified Data.Conduit.Binary as CB
import Filesystem
import Filesystem.Path.CurrentOS (FilePath, encodeString)
import qualified Data.ByteString as S
#ifdef CABAL_OS_WINDOWS
#else
import qualified System.Posix as Posix
#endif
traverse :: C.ResourceIO m
=> Bool
-> FilePath
-> C.Source m FilePath
traverse followSymlinks root = C.Source
{ C.sourcePull = do
seq0 <- liftIO $ listDirectory root
pull seq0
, C.sourceClose = return ()
}
where
mkSrc ps = C.Source (pull ps) (return ())
pull [] = return C.Closed
pull (p:ps) = do
isFile' <- liftIO $ isFile p
if isFile'
then return $ C.Open (mkSrc ps) p
else do
follow' <- liftIO $ follow p
if follow'
then do
ps' <- liftIO $ listDirectory p
pull $ ps ++ ps'
else pull ps
follow :: FilePath -> IO Bool
#ifdef CABAL_OS_WINDOWS
follow = isDirectory
#else
follow p = do
let path = encodeString p
stat <- if followSymlinks
then Posix.getFileStatus path
else Posix.getSymbolicLinkStatus path
return (Posix.isDirectory stat)
#endif
sourceFile :: C.ResourceIO m
=> FilePath
-> C.Source m S.ByteString
sourceFile = CB.sourceFile . encodeString
sinkFile :: C.ResourceIO m
=> FilePath
-> C.Sink S.ByteString m ()
sinkFile = CB.sinkFile . encodeString