Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 641e23c3ef | |||
| 82ea75cc88 | |||
| abf043be14 | |||
| 10adc4be27 | |||
| a176e4970b | |||
| 08de2ebefb | |||
| d15d7761c1 | |||
| 7e924d3386 | |||
| 21fccc9ca9 | |||
| 79dbcd8b55 |
@@ -9,8 +9,10 @@ matrix:
|
||||
include:
|
||||
- env: CABALVER=1.22 GHCVER=7.8.4
|
||||
addons: {apt: {packages: [cabal-install-1.22,ghc-7.8.4], sources: [hvr-ghc]}}
|
||||
- env: CABALVER=1.22 GHCVER=7.10.2
|
||||
addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2], sources: [hvr-ghc]}}
|
||||
- env: CABALVER=1.24 GHCVER=7.10.2
|
||||
addons: {apt: {packages: [cabal-install-1.24,ghc-7.10.2], sources: [hvr-ghc]}}
|
||||
- env: CABALVER=1.24 GHCVER=8.0.1
|
||||
addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}}
|
||||
- env: CABALVER=head GHCVER=head
|
||||
addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
0.7.3:
|
||||
* don't expose HPath.Internal
|
||||
0.7.2:
|
||||
* fix tests, so they work with the sdist tarball too
|
||||
* added the following function to HPath.IO: createSymlink
|
||||
|
||||
23
README.md
23
README.md
@@ -62,3 +62,26 @@ Note: this library was written for __posix__ systems and it will probably not su
|
||||
* has a custom versions of `openFd` which allows more control over the flags than its unix package counterpart
|
||||
* adds a `getDirectoryContents'` version that works on Fd
|
||||
|
||||
## Examples in ghci
|
||||
|
||||
Start ghci via `cabal repl`:
|
||||
|
||||
```hs
|
||||
-- enable OverloadedStrings
|
||||
:set -XOverloadedStrings
|
||||
-- import HPath.IO
|
||||
import HPath.IO
|
||||
-- parse an absolute path
|
||||
abspath <- parseAbs "/home"
|
||||
-- parse a relative path (e.g. user users home directory)
|
||||
relpath <- parseRel "jule"
|
||||
-- concatenate paths
|
||||
let newpath = abspath </> relpath
|
||||
-- get file type
|
||||
getFileType newpath
|
||||
-- return all contents of that directory
|
||||
getDirsFiles newpath
|
||||
-- return all contents of the parent directory
|
||||
getDirsFiles (dirname newpath)
|
||||
```
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TupleSections #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
|
||||
{-# OPTIONS_GHC -Wall #-}
|
||||
import Control.Applicative
|
||||
import Control.Monad
|
||||
import System.Directory
|
||||
import System.FilePath ((</>))
|
||||
import System.Posix.ByteString.FilePath
|
||||
import System.Posix.Directory.ByteString as PosixBS
|
||||
import System.Posix.Directory.Traversals
|
||||
import qualified System.Posix.FilePath as PosixBS
|
||||
import System.Posix.Files.ByteString
|
||||
|
||||
import Control.Exception
|
||||
import qualified Data.ByteString.Char8 as BS
|
||||
|
||||
import System.Environment (getArgs, withArgs)
|
||||
import System.IO.Error
|
||||
import System.IO.Unsafe
|
||||
import System.Process (system)
|
||||
import Criterion.Main
|
||||
|
||||
|
||||
-- | Based on code from 'Real World Haskell', at
|
||||
-- http://book.realworldhaskell.org/read/io-case-study-a-library-for-searching-the-filesystem.html#id620419
|
||||
listFilesRecursive :: FilePath -> IO [FilePath]
|
||||
listFilesRecursive topdir = do
|
||||
names <- System.Directory.getDirectoryContents topdir
|
||||
let properNames = filter (`notElem` [".", ".."]) names
|
||||
paths <- forM properNames $ \name -> do
|
||||
let path = topdir </> name
|
||||
isDir <- doesDirectoryExist path
|
||||
if isDir
|
||||
then listFilesRecursive path
|
||||
else return [path]
|
||||
return (topdir : concat paths)
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
getDirectoryContentsBS :: RawFilePath -> IO [RawFilePath]
|
||||
getDirectoryContentsBS path =
|
||||
modifyIOError ((`ioeSetFileName` (BS.unpack path)) .
|
||||
(`ioeSetLocation` "getDirectoryContentsBS")) $ do
|
||||
bracket
|
||||
(PosixBS.openDirStream path)
|
||||
PosixBS.closeDirStream
|
||||
loop
|
||||
where
|
||||
loop dirp = do
|
||||
e <- PosixBS.readDirStream dirp
|
||||
if BS.null e then return [] else do
|
||||
es <- loop dirp
|
||||
return (e:es)
|
||||
|
||||
|
||||
-- | similar to 'listFilesRecursive, but uses RawFilePaths
|
||||
listFilesRecursiveBS :: RawFilePath -> IO [RawFilePath]
|
||||
listFilesRecursiveBS topdir = do
|
||||
names <- getDirectoryContentsBS topdir
|
||||
let properNames = filter (`notElem` [".", ".."]) names
|
||||
paths <- forM properNames $ \name -> unsafeInterleaveIO $ do
|
||||
let path = PosixBS.combine topdir name
|
||||
isDir <- isDirectory <$> getFileStatus path
|
||||
if isDir
|
||||
then listFilesRecursiveBS path
|
||||
else return [path]
|
||||
return (topdir : concat paths)
|
||||
----------------------------------------------------------
|
||||
|
||||
|
||||
benchTraverse :: RawFilePath -> IO ()
|
||||
benchTraverse = traverseDirectory (\() p -> BS.putStrLn p) ()
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
let (d,otherArgs) = case args of
|
||||
[] -> ("/usr/local",[])
|
||||
x:xs -> (x,xs)
|
||||
withArgs otherArgs $ defaultMain
|
||||
[ bench "traverse (FilePath)" $ nfIO $ listFilesRecursive d >>= mapM_ putStrLn
|
||||
, bench "traverse (RawFilePath)" $ nfIO $ listFilesRecursiveBS (BS.pack d) >>= mapM_ BS.putStrLn
|
||||
, bench "allDirectoryContents" $ nfIO $ allDirectoryContents (BS.pack d) >>= mapM_ BS.putStrLn
|
||||
, bench "allDirectoryContents'" $ nfIO $ allDirectoryContents' (BS.pack d) >>= mapM_ BS.putStrLn
|
||||
, bench "traverseDirectory" $ nfIO $ benchTraverse (BS.pack d)
|
||||
, bench "unix find" $ nfIO $ void $ system ("find " ++ d)
|
||||
]
|
||||
22
hpath.cabal
22
hpath.cabal
@@ -1,5 +1,5 @@
|
||||
name: hpath
|
||||
version: 0.7.2
|
||||
version: 0.7.3
|
||||
synopsis: Support for well-typed paths
|
||||
description: Support for well-typed paths, utilizing ByteString under the hood.
|
||||
license: GPL-2
|
||||
@@ -12,7 +12,6 @@ build-type: Simple
|
||||
cabal-version: >=1.14
|
||||
extra-source-files: README.md
|
||||
CHANGELOG
|
||||
benchmarks/*.hs
|
||||
cbits/dirutils.h
|
||||
doctests-hpath.hs
|
||||
doctests-posix.hs
|
||||
@@ -26,11 +25,11 @@ library
|
||||
HPath.IO,
|
||||
HPath.IO.Errors,
|
||||
HPath.IO.Utils,
|
||||
HPath.Internal,
|
||||
System.Posix.Directory.Foreign,
|
||||
System.Posix.Directory.Traversals,
|
||||
System.Posix.FD,
|
||||
System.Posix.FilePath
|
||||
other-modules: HPath.Internal
|
||||
build-depends: base >= 4.2 && <5
|
||||
, bytestring >= 0.9.2.0
|
||||
, deepseq
|
||||
@@ -103,23 +102,6 @@ test-suite spec
|
||||
, unix-bytestring
|
||||
, utf8-string
|
||||
|
||||
benchmark bench.hs
|
||||
default-language: Haskell2010
|
||||
type: exitcode-stdio-1.0
|
||||
hs-source-dirs: benchmarks
|
||||
main-is: Bench.hs
|
||||
|
||||
build-depends:
|
||||
base,
|
||||
hpath,
|
||||
bytestring,
|
||||
unix,
|
||||
directory >= 1.1 && < 1.3,
|
||||
filepath >= 1.2 && < 1.5,
|
||||
process >= 1.0 && < 1.3,
|
||||
criterion >= 0.6 && < 1.2
|
||||
ghc-options: -O2
|
||||
|
||||
source-repository head
|
||||
type: git
|
||||
location: https://github.com/hasufell/hpath
|
||||
|
||||
@@ -24,6 +24,7 @@ module HPath
|
||||
,Fn
|
||||
,PathParseException
|
||||
,PathException
|
||||
,RelC
|
||||
-- * PatternSynonyms/ViewPatterns
|
||||
,pattern Path
|
||||
-- * Path Parsing
|
||||
@@ -89,12 +90,17 @@ data PathException = RootDirHasNoBasename
|
||||
deriving (Show,Typeable)
|
||||
instance Exception PathException
|
||||
|
||||
class RelC m
|
||||
|
||||
instance RelC Rel
|
||||
instance RelC Fn
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- PatternSynonyms
|
||||
|
||||
#if __GLASGOW_HASKELL__ >= 710
|
||||
pattern Path :: ByteString -> Path a
|
||||
#endif
|
||||
pattern Path x <- (MkPath x)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
-- | Internal types and functions.
|
||||
|
||||
module HPath.Internal
|
||||
(Path(..)
|
||||
,RelC)
|
||||
(Path(..))
|
||||
where
|
||||
|
||||
import Control.DeepSeq (NFData (..))
|
||||
@@ -13,7 +12,7 @@ import Data.Data
|
||||
|
||||
-- | Path of some base and type.
|
||||
--
|
||||
-- Internally is a string. The string can be of two formats only:
|
||||
-- Internally is a ByteString. The ByteString can be of two formats only:
|
||||
--
|
||||
-- 1. without trailing path separator: @file.txt@, @foo\/bar.txt@, @\/foo\/bar.txt@
|
||||
-- 2. with trailing path separator: @foo\/@, @\/foo\/bar\/@
|
||||
@@ -23,7 +22,7 @@ import Data.Data
|
||||
data Path b = MkPath ByteString
|
||||
deriving (Typeable)
|
||||
|
||||
-- | String equality.
|
||||
-- | ByteString equality.
|
||||
--
|
||||
-- The following property holds:
|
||||
--
|
||||
@@ -31,7 +30,7 @@ data Path b = MkPath ByteString
|
||||
instance Eq (Path b) where
|
||||
(==) (MkPath x) (MkPath y) = x == y
|
||||
|
||||
-- | String ordering.
|
||||
-- | ByteString ordering.
|
||||
--
|
||||
-- The following property holds:
|
||||
--
|
||||
@@ -39,7 +38,7 @@ instance Eq (Path b) where
|
||||
instance Ord (Path b) where
|
||||
compare (MkPath x) (MkPath y) = compare x y
|
||||
|
||||
-- | Same as 'Path.toFilePath'.
|
||||
-- | Same as 'HPath.toFilePath'.
|
||||
--
|
||||
-- The following property holds:
|
||||
--
|
||||
@@ -50,6 +49,3 @@ instance Show (Path b) where
|
||||
instance NFData (Path b) where
|
||||
rnf (MkPath x) = rnf x
|
||||
|
||||
|
||||
class RelC m
|
||||
|
||||
|
||||
Reference in New Issue
Block a user