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 $ do
seq0 <- liftIO $ listDirectory root
C.prepareSource $ C.sourceState seq0 pull
where
pull [] = return ([], C.Closed)
pull (p:ps) = do
isFile' <- liftIO $ isFile p
if isFile'
then return (ps, C.Open 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