directory-ospath-streaming 0.2.1 → 0.2.2
raw patch · 5 files changed
+61/−6 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ System.Directory.OsPath.Streaming: getDirectoryContentsWithFilterRecursive :: (Basename OsPath -> SymlinkType -> Bool) -> (Basename OsPath -> Bool) -> OsPath -> IO [(OsPath, FileType)]
Files
- Changelog.md +4/−0
- directory-ospath-streaming.cabal +1/−1
- src/System/Directory/OsPath/Contents.hs +37/−1
- src/System/Directory/OsPath/Streaming.hs +1/−0
- test/TestMain.hs +18/−4
Changelog.md view
@@ -1,3 +1,7 @@+# 0.2.2++- Add `getDirectoryContentsWithFilterRecursive` for recursively listing directory contents with commonly needed filtering+ # 0.2.1 - Fix `listContentsRecFold` to not mask exceptions unnecessarily which could cause hangups. The `getDirectoryContentsRecursive` gets the fix as well
directory-ospath-streaming.cabal view
@@ -5,7 +5,7 @@ name: directory-ospath-streaming version:- 0.2.1+ 0.2.2 synopsis: Stream directory entries in constant memory in vanilla IO description:
src/System/Directory/OsPath/Contents.hs view
@@ -11,6 +11,7 @@ module System.Directory.OsPath.Contents ( getDirectoryContentsRecursive+ , getDirectoryContentsWithFilterRecursive , listContentsRecFold ) where@@ -43,6 +44,41 @@ (\_ _ (Relative path) _ ft -> pure (Just (path, ft))) (Just root) +-- | Recursively list all the files and directories that satisfy given+-- predicate in a directory and all subdirectories. Descending into+-- some subdirectories may be avoided by filtering them out with a+-- visiting predicate.+--+-- Not visited directory entry may still be reported depending on the+-- collection predicate.+--+-- The directory structure is traversed depth-first.+--+-- The result is generated lazily so is not well defined if the source+-- directory structure changes before the list is fully consumed.+--+-- Symlinks within directory structure may cause result to be infinitely long, but+-- they can be filtered out with a suitable directory visiting predicate.+getDirectoryContentsWithFilterRecursive+ :: (Basename OsPath -> SymlinkType -> Bool) -- ^ Whether to visit a directory+ -> (Basename OsPath -> Bool) -- ^ Whether to collect given directory element, either file or directory.+ -> OsPath+ -> IO [(OsPath, FileType)]+getDirectoryContentsWithFilterRecursive visitPred collectPred root =+ listContentsRecFold'+ Nothing+ (\_ _ (Relative path) basename ft symlink cons prependSubdir rest ->+ (if collectPred basename then cons (path, ft) else id) $+ if visitPred basename symlink+ then prependSubdir rest+ else rest)+ (\_ _ (Relative path) basename ft ->+ pure $+ if collectPred basename+ then Just (path, ft)+ else Nothing)+ (Just root)+ {-# INLINE listContentsRecFold #-} -- | The most general form of gathering directory contents. --@@ -90,7 +126,7 @@ {-# INLINE listContentsRecFold' #-} -- Actual worker with slightly worse type signature that we don’t want to expose to the users.--- But it’s better candidate for implementing getDirectoryContentsRecursive here that+-- But it’s better candidate for implementing getDirectoryContentsRecursive here than -- listContentsRecFold. listContentsRecFold' :: forall f a b. (Foldable f, Coercible b OsPath)
src/System/Directory/OsPath/Streaming.hs view
@@ -23,6 +23,7 @@ -- * Get directory contents , getDirectoryContentsRecursive+ , getDirectoryContentsWithFilterRecursive , listContentsRecFold
test/TestMain.hs view
@@ -52,17 +52,31 @@ getFileType [osp|test|] >>= (@?= Directory Regular) ] - , testCase "getDirectoryContentsRecursive" $ do- res <- L.sort <$> getDirectoryContentsRecursive [osp|test/filesystem|]- res @?= [([osp|bar.txt|], File Regular), ([osp|baz.txt|], File Regular), ([osp|bin|], Directory Regular), ([osp|bin|] </> [osp|bin.txt|], File Regular), ([osp|foo.txt|], File Regular)]+ , testGroup "contents"+ [ testCase "getDirectoryContentsRecursive" $ do+ res <- L.sort <$> getDirectoryContentsRecursive [osp|test/filesystem|]+ res @?= [([osp|bar.txt|], File Regular), ([osp|baz.txt|], File Regular), ([osp|bin|], Directory Regular), ([osp|bin|] </> [osp|bin.txt|], File Regular), ([osp|foo.txt|], File Regular)] + , testCase "getDirectoryContentsWithFilterRecursive 1" $ do+ res <- L.sort <$> getDirectoryContentsWithFilterRecursive (\_ _ -> True) (const True) [osp|test/filesystem|]+ res @?= [([osp|bar.txt|], File Regular), ([osp|baz.txt|], File Regular), ([osp|bin|], Directory Regular), ([osp|bin|] </> [osp|bin.txt|], File Regular), ([osp|foo.txt|], File Regular)]++ , testCase "getDirectoryContentsWithFilterRecursive 2" $ do+ res <- L.sort <$> getDirectoryContentsWithFilterRecursive (\x _ -> x /= Basename [osp|bin|]) (const True) [osp|test/filesystem|]+ res @?= [([osp|bar.txt|], File Regular), ([osp|baz.txt|], File Regular), ([osp|bin|], Directory Regular), ([osp|foo.txt|], File Regular)]++ , testCase "getDirectoryContentsWithFilterRecursive 3" $ do+ res <- L.sort <$> getDirectoryContentsWithFilterRecursive (\_ _ -> True) (`elem` [Basename [osp|foo.txt|], Basename [osp|bin|], Basename [osp|bin.txt|]]) [osp|test/filesystem|]+ res @?= [([osp|bin|], Directory Regular), ([osp|bin|] </> [osp|bin.txt|], File Regular), ([osp|foo.txt|], File Regular)]+ ]+ #ifndef mingw32_HOST_OS , withResource (do tmp <- getTemporaryDirectory >>= canonicalizePath createFreshTempDir tmp [osp|test|]) removeDirectoryRecursive- $ \mkTmpDir -> testGroup "getFileType unix"+ $ \mkTmpDir -> testGroup "getFileType unix" [ testCase "file symlink" $ do tmp <- mkTmpDir currDir <- getCurrentDirectory