Glob 0.6 → 0.6.1
raw patch · 3 files changed
+70/−14 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.txt +7/−0
- Glob.cabal +1/−1
- System/FilePath/Glob/Directory.hs +62/−13
CHANGELOG.txt view
@@ -1,3 +1,10 @@+0.6.1, 2011-09-14:+ Bug fix: globDir should now ignore the given directory when given an+ absolute path on Windows.++ Doc fix: noted that globDir doesn't actually fully ignore the given+ directory if the Pattern starts with a path separator.+ 0.6, 2011-09-12: New functions: System.FilePath.Glob.glob :: Pattern -> IO [FilePath]
Glob.cabal view
@@ -1,7 +1,7 @@ Cabal-Version: >= 1.6 Name: Glob-Version: 0.6+Version: 0.6.1 Homepage: http://iki.fi/matti.niemenmaa/glob/ Synopsis: Globbing library Category: System
System/FilePath/Glob/Directory.hs view
@@ -10,15 +10,15 @@ import qualified Data.DList as DL import Data.DList (DList) import Data.List ((\\))-import Data.Maybe (listToMaybe) import System.Directory ( doesDirectoryExist, getDirectoryContents , getCurrentDirectory )-import System.FilePath ( (</>), extSeparator, isExtSeparator, pathSeparator- , takeDrive+import System.FilePath ( (</>), takeDrive, splitDrive+ , extSeparator, isExtSeparator+ , pathSeparator, isPathSeparator ) -import System.FilePath.Glob.Base ( Pattern(..), Token(..), liftP+import System.FilePath.Glob.Base ( Pattern(..), Token(..) , MatchOptions, matchDefault ) import System.FilePath.Glob.Match (matchWith)@@ -67,8 +67,15 @@ -- -- If the given 'FilePath' is @[]@, 'getCurrentDirectory' will be used. ----- If the given 'Pattern' starts with a path separator, it is not relative to--- the given directory and the @dir@ parameter is completely ignored!+-- If the given 'Pattern' starts with a drive (as defined by+-- 'System.FilePath'), it is not relative to the given directory and the+-- 'FilePath' parameter is completely ignored! Similarly, if the given+-- 'Pattern' starts with a path separator, only the drive part of the+-- 'FilePath' is used. On Posix systems these behaviours are equivalent:+-- 'Pattern's starting with @\/@ work relative to @\/@. On Windows, 'Pattern's+-- starting with @\/@ or @\\@ work relative only to the drive part of+-- 'FilePath' and 'Pattern's starting with absolute paths ignore the+-- 'FilePath'. -- -- Note that in some cases results outside the given directory may be returned: -- for instance the @.*@ pattern matches the @..@ directory.@@ -114,13 +121,11 @@ globDir'0 :: MatchOptions -> Pattern -> FilePath -> IO (DList FilePath, DList FilePath) globDir'0 opts pat dir = do- (dir',pat') <-- if maybe False (==PathSeparator) . listToMaybe . unPattern $ pat- then do- curDir <- getCurrentDirectory- return (takeDrive curDir, liftP (dropWhile (==PathSeparator)) pat)- else fmap (flip (,) pat) $- if null dir then getCurrentDirectory else return dir+ let (pat', drive) = driveSplit pat+ dir' <- case drive of+ Just "" -> fmap takeDrive getCurrentDirectory+ Just d -> return d+ Nothing -> if null dir then getCurrentDirectory else return dir globDir' opts (separate pat') dir' globDir' :: MatchOptions -> [TypedPattern] -> FilePath@@ -219,6 +224,50 @@ f (Any p) ts = u p ++ ts u = unPattern++-- Note that we consider "/foo" to specify a drive on Windows, even though it's+-- relative to the current drive.+--+-- Returns the [TypedPattern] of the Pattern (with the drive dropped if+-- appropriate) and, if the Pattern specified a drive, a Maybe representing the+-- drive to use. If it's a Just "", use the drive of the current working+-- directory.+driveSplit :: Pattern -> (Pattern, Maybe FilePath)+driveSplit = check . split . unPattern+ where+ -- We can't just use something like commonDirectory because of Windows+ -- drives being possibly longer than one "directory", like "//?/foo/bar/".+ -- So just take as much as possible.+ split (LongLiteral _ l : xs) = first (l++) (split xs)+ split ( Literal l : xs) = first (l:) (split xs)+ split (PathSeparator : xs) = first (pathSeparator:) (split xs)+ split ( ExtSeparator : xs) = first ( extSeparator:) (split xs)+ split xs = ([],xs)++ -- The isPathSeparator check is interesting in two ways:+ --+ -- 1. It's correct to return simply Just "" because there can't be more than+ -- one path separator if splitDrive gave a null drive: "//x" is a shared+ -- "drive" in Windows and starts with the root "drive" in Posix.+ --+ -- 2. The 'head' is safe because we have not (null d) && null drive.+ check (d,ps)+ | null d = (Pattern ps, Nothing)+ | not (null drive) = (dirify rest ps, Just drive)+ | isPathSeparator (head rest) = (Pattern ps, Just "")+ | otherwise = (dirify d ps, Nothing)+ where+ (drive, rest) = splitDrive d++ dirify path = Pattern . (comp path++)++ comp s = let (p,l) = foldr f ([],[]) s in if null l then p else ll l p+ where+ f c (p,l) | isExtSeparator c = (ExtSeparator : ll l p, [])+ | isPathSeparator c = (PathSeparator : ll l p, [])+ | otherwise = (p, c:l)++ ll l p = if null l then p else LongLiteral (length l) l : p -- |Factors out the directory component of a 'Pattern'. Useful in conjunction -- with 'globDir'.