filesystem-enumerator 0.1 → 0.1.1
raw patch · 3 files changed
+116/−109 lines, 3 filesdep ~basedep ~transformers
Dependency ranges changed: base, transformers
Files
- Filesystem/Enumerator.hs +0/−100
- filesystem-enumerator.cabal +16/−9
- lib/Filesystem/Enumerator.hs +100/−0
− Filesystem/Enumerator.hs
@@ -1,100 +0,0 @@-{-# LANGUAGE CPP #-}---- |--- Module: Filesystem.Enumerator--- Copyright: 2011 John Millikin--- 2011 Michael Snoyman--- License: MIT------ Maintainer: jmillikin@gmail.com--- Portability: portable------ Enumerator-based API for manipulating the filesystem.-module Filesystem.Enumerator- ( traverse- , enumDirectory- ) where--import Prelude hiding (FilePath)--import Control.Exception (finally)-import Control.Monad.IO.Class (MonadIO)-import Data.Enumerator-import Filesystem-import Filesystem.Path ((</>))-import Filesystem.Path.CurrentOS (FilePath, encodeString, decodeString)--#ifdef CABAL_OS_WINDOWS-import qualified System.Win32 as Win32-#else-import qualified System.Posix as Posix-#endif---- | Starting at some root directory, traverse the filesystem and enumerate--- every file (or symlink to a file) found.------ Note: the option of whether to follow symlinks is currently only checked--- on POSIX platforms, as the @Win32@ package does not support querying--- symlink status. On Windows, symlinks will always be followed.-traverse :: MonadIO m- => Bool -- ^ Follow directory symlinks (only used on POSIX platforms)- -> FilePath -- ^ Root directory- -> Enumerator FilePath m a-traverse followSymlinks root s = tryIO (listDirectory root) >>= (\ps -> loop ps s) where- loop (p:ps) step@(Continue k) = do- isFile' <- tryIO (isFile p)- if isFile'- then k (Chunks [p]) >>== loop ps- else do- follow' <- tryIO (follow p)- if follow'- then traverse followSymlinks p step >>== loop ps- else loop ps step- loop _ step = returnI step-- 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---- | Enumerate entries in a directory. Entries are returned with their full--- path. Entries are read from the directory handle as needed, so this is safe--- to use with very large directories.-enumDirectory :: FilePath -> Enumerator FilePath IO a-enumDirectory root step = do- let boring str = str == "." || str == ".."- -#ifdef CABAL_OS_WINDOWS- let search = root </> decodeString "*"- (h, findData) <- tryIO (Win32.findFirstFile (encodeString search))- let close = Win32.findClose h- let iter = checkContinue0 $ \loop k -> do- raw <- tryIO (Win32.getFindDataFileName findData)- let path = root </> decodeString raw- let checkNext s = do- hasNext <- tryIO (Win32.findNextFile h findData)- if hasNext- then loop s- else returnI s- if boring raw- then checkNext (Continue k)- else k (Chunks [path]) >>== checkNext-#else- dir <- tryIO (Posix.openDirStream (encodeString root))- let close = Posix.closeDirStream dir- let iter = checkContinue0 $ \loop k -> do- raw <- tryIO (Posix.readDirStream dir)- let path = root </> decodeString raw- case raw of- "" -> continue k- _ | boring raw -> loop (Continue k)- _ -> k (Chunks [path]) >>== loop-#endif- Iteratee (finally (runIteratee (iter step)) close)
filesystem-enumerator.cabal view
@@ -1,31 +1,38 @@ name: filesystem-enumerator-version: 0.1-synopsis: Enumerator-based API for manipulating the filesystem.+version: 0.1.1 license: MIT license-file: license.txt author: John Millikin <jmillikin@gmail.com>, Michael Snoyman <michael@snoyman.com>-maintainer: jmillikin@gmail.com+maintainer: John Millikin< jmillikin@gmail.com> build-type: Simple cabal-version: >= 1.6 category: System, Enumerator stability: experimental+homepage: https://john-millikin.com/software/haskell-filesystem/ bug-reports: mailto:jmillikin@gmail.com-homepage: https://john-millikin.com/software/filesystem-enumerator/-tested-with: GHC==6.12.1 +synopsis: Enumerator-based API for manipulating the filesystem.+description:+ source-repository head type: bazaar- location: https://john-millikin.com/software/filesystem-enumerator/+ location: https://john-millikin.com/branches/filesystem-enumerator/0.1/ +source-repository this+ type: bazaar+ location: https://john-millikin.com/branches/filesystem-enumerator/0.1/+ tag: filesystem-enumerator_0.1.1+ library- ghc-options: -Wall+ ghc-options: -Wall -O2+ hs-source-dirs: lib build-depends:- base >= 3 && < 5+ base >= 4.1 && < 5.0 , enumerator >= 0.4 && < 0.5 , system-filepath >= 0.4 && < 0.5 , system-fileio >= 0.3 && < 0.4- , transformers >= 0.2 && < 0.3+ , transformers >= 0.2 if os(windows) cpp-options: -DCABAL_OS_WINDOWS
+ lib/Filesystem/Enumerator.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE CPP #-}++-- |+-- Module: Filesystem.Enumerator+-- Copyright: 2011 John Millikin+-- 2011 Michael Snoyman+-- License: MIT+--+-- Maintainer: jmillikin@gmail.com+-- Portability: portable+--+-- Enumerator-based API for manipulating the filesystem.+module Filesystem.Enumerator+ ( traverse+ , enumDirectory+ ) where++import Prelude hiding (FilePath)++import Control.Exception (finally)+import Control.Monad.IO.Class (MonadIO)+import Data.Enumerator+import Filesystem+import Filesystem.Path ((</>))+import Filesystem.Path.CurrentOS (FilePath, encodeString, decodeString)++#ifdef CABAL_OS_WINDOWS+import qualified System.Win32 as Win32+#else+import qualified System.Posix as Posix+#endif++-- | Starting at some root directory, traverse the filesystem and enumerate+-- every file (or symlink to a file) found.+--+-- Note: the option of whether to follow symlinks is currently only checked+-- on POSIX platforms, as the @Win32@ package does not support querying+-- symlink status. On Windows, symlinks will always be followed.+traverse :: MonadIO m+ => Bool -- ^ Follow directory symlinks (only used on POSIX platforms)+ -> FilePath -- ^ Root directory+ -> Enumerator FilePath m a+traverse followSymlinks root s = tryIO (listDirectory root) >>= (\ps -> loop ps s) where+ loop (p:ps) step@(Continue k) = do+ isFile' <- tryIO (isFile p)+ if isFile'+ then k (Chunks [p]) >>== loop ps+ else do+ follow' <- tryIO (follow p)+ if follow'+ then traverse followSymlinks p step >>== loop ps+ else loop ps step+ loop _ step = returnI step++ 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++-- | Enumerate entries in a directory. Entries are returned with their full+-- path. Entries are read from the directory handle as needed, so this is safe+-- to use with very large directories.+enumDirectory :: FilePath -> Enumerator FilePath IO a+enumDirectory root step = do+ let boring str = str == "." || str == ".."+ +#ifdef CABAL_OS_WINDOWS+ let search = root </> decodeString "*"+ (h, findData) <- tryIO (Win32.findFirstFile (encodeString search))+ let close = Win32.findClose h+ let iter = checkContinue0 $ \loop k -> do+ raw <- tryIO (Win32.getFindDataFileName findData)+ let path = root </> decodeString raw+ let checkNext s = do+ hasNext <- tryIO (Win32.findNextFile h findData)+ if hasNext+ then loop s+ else returnI s+ if boring raw+ then checkNext (Continue k)+ else k (Chunks [path]) >>== checkNext+#else+ dir <- tryIO (Posix.openDirStream (encodeString root))+ let close = Posix.closeDirStream dir+ let iter = checkContinue0 $ \loop k -> do+ raw <- tryIO (Posix.readDirStream dir)+ let path = root </> decodeString raw+ case raw of+ "" -> continue k+ _ | boring raw -> loop (Continue k)+ _ -> k (Chunks [path]) >>== loop+#endif+ Iteratee (finally (runIteratee (iter step)) close)