Windows: include= and exclude= containing '/' will also match filenames that are written using '\'

And vice-versa, but it's better to use '/' for portability.

Notably, standardPreferredContent contains "archive/*" and that might not
match if the filename ends up coming in with the slashes the other way
around.
This commit is contained in:
Joey Hess 2020-12-15 12:39:34 -04:00
parent e914cb0777
commit 6b13574827
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
7 changed files with 49 additions and 17 deletions

View file

@ -1,15 +1,17 @@
{-# LANGUAGE PackageImports #-}
{- file globbing
-
- Copyright 2014 Joey Hess <id@joeyh.name>
- Copyright 2014-2020 Joey Hess <id@joeyh.name>
-
- License: BSD-2-clause
-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE PackageImports #-}
module Utility.Glob (
Glob,
GlobCase(..),
GlobFilePath(..),
compileGlob,
matchGlob
) where
@ -24,26 +26,42 @@ newtype Glob = Glob Regex
data GlobCase = CaseSensative | CaseInsensative
-- Is the glob being used to match filenames?
--
-- When matching filenames,
-- a single path separator (eg /) in the glob will match any
-- number of path separators in the filename.
-- And on Windows, both / and \ are used as path separators, so compile
-- the glob to a regexp that matches either path separator.
newtype GlobFilePath = GlobFilePath Bool
{- Compiles a glob to a regex, that can be repeatedly used. -}
compileGlob :: String -> GlobCase -> Glob
compileGlob glob globcase = Glob $
compileGlob :: String -> GlobCase -> GlobFilePath -> Glob
compileGlob glob globcase globfilepath = Glob $
case compile (defaultCompOpt {caseSensitive = casesentitive}) defaultExecOpt regex of
Right r -> r
Left _ -> giveup $ "failed to compile regex: " ++ regex
where
regex = '^' : wildToRegex glob ++ "$"
regex = '^' : wildToRegex globfilepath glob ++ "$"
casesentitive = case globcase of
CaseSensative -> True
CaseInsensative -> False
wildToRegex :: String -> String
wildToRegex = concat . go
wildToRegex :: GlobFilePath -> String -> String
wildToRegex (GlobFilePath globfile) = concat . go
where
go [] = []
go ('*':xs) = ".*" : go xs
go ('?':xs) = "." : go xs
go ('[':'!':xs) = "[^" : inpat xs
go ('[':xs) = "[" : inpat xs
#ifdef mingw32_HOST_OS
go ('/':xs) | globfile = "[/\\]+" : go xs
go ('\\':xs) | globfile = "[/\\]+" : go xs
#else
go ('/':xs) | globfile = "[/]+" : go xs
go ('\\':xs) | globfile = "[\\]+" : go xs
#endif
go (x:xs)
| isDigit x || isAlpha x = [x] : go xs
| otherwise = esc x : go xs