Blame Data/Conduit/Filesystem.hs

Packit 4b2029
{-# LANGUAGE RankNTypes #-}
Packit 4b2029
module Data.Conduit.Filesystem
Packit 4b2029
    ( sourceDirectory
Packit 4b2029
    , sourceDirectoryDeep
Packit 4b2029
    ) where
Packit 4b2029
Packit 4b2029
import Data.Conduit
Packit 4b2029
import Control.Monad.Trans.Resource (MonadResource)
Packit 4b2029
import Control.Monad.IO.Class (liftIO)
Packit 4b2029
import System.FilePath (())
Packit 4b2029
import qualified Data.Streaming.Filesystem as F
Packit 4b2029
Packit 4b2029
-- | Stream the contents of the given directory, without traversing deeply.
Packit 4b2029
--
Packit 4b2029
-- This function will return /all/ of the contents of the directory, whether
Packit 4b2029
-- they be files, directories, etc.
Packit 4b2029
--
Packit 4b2029
-- Note that the generated filepaths will be the complete path, not just the
Packit 4b2029
-- filename. In other words, if you have a directory @foo@ containing files
Packit 4b2029
-- @bar@ and @baz@, and you use @sourceDirectory@ on @foo@, the results will be
Packit 4b2029
-- @foo/bar@ and @foo/baz@.
Packit 4b2029
--
Packit 4b2029
-- Since 1.1.0
Packit 4b2029
sourceDirectory :: MonadResource m => FilePath -> Producer m FilePath
Packit 4b2029
sourceDirectory dir =
Packit 4b2029
    bracketP (F.openDirStream dir) F.closeDirStream go
Packit 4b2029
  where
Packit 4b2029
    go ds =
Packit 4b2029
        loop
Packit 4b2029
      where
Packit 4b2029
        loop = do
Packit 4b2029
            mfp <- liftIO $ F.readDirStream ds
Packit 4b2029
            case mfp of
Packit 4b2029
                Nothing -> return ()
Packit 4b2029
                Just fp -> do
Packit 4b2029
                    yield $ dir  fp
Packit 4b2029
                    loop
Packit 4b2029
Packit 4b2029
-- | Deeply stream the contents of the given directory.
Packit 4b2029
--
Packit 4b2029
-- This works the same as @sourceDirectory@, but will not return directories at
Packit 4b2029
-- all. This function also takes an extra parameter to indicate whether
Packit 4b2029
-- symlinks will be followed.
Packit 4b2029
--
Packit 4b2029
-- Since 1.1.0
Packit 4b2029
sourceDirectoryDeep :: MonadResource m
Packit 4b2029
                    => Bool -- ^ Follow directory symlinks
Packit 4b2029
                    -> FilePath -- ^ Root directory
Packit 4b2029
                    -> Producer m FilePath
Packit 4b2029
sourceDirectoryDeep followSymlinks =
Packit 4b2029
    start
Packit 4b2029
  where
Packit 4b2029
    start :: MonadResource m => FilePath -> Producer m FilePath
Packit 4b2029
    start dir = sourceDirectory dir =$= awaitForever go
Packit 4b2029
Packit 4b2029
    go :: MonadResource m => FilePath -> Producer m FilePath
Packit 4b2029
    go fp = do
Packit 4b2029
        ft <- liftIO $ F.getFileType fp
Packit 4b2029
        case ft of
Packit 4b2029
            F.FTFile -> yield fp
Packit 4b2029
            F.FTFileSym -> yield fp
Packit 4b2029
            F.FTDirectory -> start fp
Packit 4b2029
            F.FTDirectorySym
Packit 4b2029
                | followSymlinks -> start fp
Packit 4b2029
                | otherwise -> return ()
Packit 4b2029
            F.FTOther -> return ()