packages feed

argon-0.4.2.0: src/Argon/Walker.hs

{-# LANGUAGE OverloadedStrings #-}
module Argon.Walker (allFiles)
    where

import           Data.DirStream            (childOf)
import           Data.List                 (isSuffixOf)
import           Filesystem.Path.CurrentOS (decodeString, encodeString)
import           Pipes                     (ListT, MonadIO, Producer, each,
                                            every, liftIO, (>->))
import qualified Pipes.Prelude             as P
import           Pipes.Safe
import           System.Directory          (doesDirectoryExist, doesFileExist,
                                            pathIsSymbolicLink)
import           System.FilePath           (takeExtension)

-- | Starting from a path, generate a sequence of paths corresponding
--   to Haskell files. The filesystem is traversed depth-first.
allFiles :: (MonadIO m, MonadSafe m) => FilePath -> Producer FilePath m ()
allFiles path = do
    isFile <- liftIO $ doesFileExist path
    if isFile then each [path] >-> P.filter (".hs" `isSuffixOf`)
              else every $ hsFilesIn path

-- | List the regular files in a directory.
hsFilesIn :: MonadSafe m => FilePath -> ListT m FilePath
hsFilesIn path = do
  child <- encodeString <$> childOf (decodeString path)
  isDir <- liftIO $ doesDirectoryExist child
  isSymLink <- liftIO $ pathIsSymbolicLink child
  if isDir && not isSymLink
    then hsFilesIn child
    else if not isSymLink && takeExtension child == ".hs"
         then return child
         else mempty