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.
('>':v) -> checkcmp (>) v
_ -> checkglob ""
checkglob v =
- let cglob = compileGlob v CaseInsensative
+ let cglob = compileGlob v CaseInsensative (GlobFilePath False)
in matchGlob cglob . decodeBS . fromMetaValue
checkcmp cmp v v' = case (doubleval v, doubleval (decodeBS (fromMetaValue v'))) of
(Just d, Just d') -> d' `cmp` d
combineViewFilter (FilterValues _) newglob@(FilterGlob _) =
(newglob, Widening)
combineViewFilter (FilterGlob oldglob) new@(FilterValues s)
- | all (matchGlob (compileGlob oldglob CaseInsensative) . decodeBS . fromMetaValue) (S.toList s) = (new, Narrowing)
+ | all (matchGlob (compileGlob oldglob CaseInsensative (GlobFilePath False)) . decodeBS . fromMetaValue) (S.toList s) = (new, Narrowing)
| otherwise = (new, Widening)
combineViewFilter (FilterGlob old) newglob@(FilterGlob new)
| old == new = (newglob, Unchanged)
- | matchGlob (compileGlob old CaseInsensative) new = (newglob, Narrowing)
+ | matchGlob (compileGlob old CaseInsensative (GlobFilePath False)) new = (newglob, Narrowing)
| otherwise = (newglob, Widening)
combineViewFilter (FilterGlob _) new@(ExcludeValues _) = (new, Narrowing)
combineViewFilter (ExcludeValues _) new@(FilterGlob _) = (new, Widening)
FilterValues s -> \values -> setmatches $
S.intersection s values
FilterGlob glob ->
- let cglob = compileGlob glob CaseInsensative
+ let cglob = compileGlob glob CaseInsensative (GlobFilePath False)
in \values -> setmatches $
S.filter (matchGlob cglob . decodeBS . fromMetaValue) values
ExcludeValues excludes -> \values ->
enclosure, but only a link to an url which youtube-dl does not support.
* initremote: Prevent enabling encryption with exporttree=yes or
importtree=yes.
+ * Windows: include= and exclude= containing '/' will also match filenames
+ that are written using '\'. (And vice-versa, but it's better to use '/'
+ for portability.)
-- Joey Hess <id@joeyh.name> Mon, 30 Nov 2020 12:55:49 -0400
matchGlobFile :: String -> MatchInfo -> Annex Bool
matchGlobFile glob = go
where
- cglob = compileGlob glob CaseSensative -- memoized
+ cglob = compileGlob glob CaseSensative (GlobFilePath True) -- memoized
go (MatchingFile fi) = pure $ matchGlob cglob (fromRawFilePath (matchFile fi))
go (MatchingInfo p) = pure $ matchGlob cglob (fromRawFilePath (providedFilePath p))
go (MatchingUserInfo p) = matchGlob cglob <$> getUserInfo (userProvidedFilePath p)
, matchNeedsLocationLog = False
}
where
- cglob = compileGlob glob CaseSensative -- memoized
+ cglob = compileGlob glob CaseSensative (GlobFilePath False) -- memoized
go (MatchingKey _ _) = pure False
go (MatchingFile fi) = case contentFile fi of
Just f -> catchBoolIO $
| RemoveMatching Glob
allRefSpec :: RefSpec
-allRefSpec = [AddMatching $ compileGlob "*" CaseSensative]
+allRefSpec = [AddMatching $ compileGlob "*" CaseSensative (GlobFilePath False)]
parseRefSpec :: String -> Either String RefSpec
parseRefSpec v = case partitionEithers (map mk $ splitc ':' v) of
where
mk ('+':s)
| any (`elem` s) "*?" =
- Right $ AddMatching $ compileGlob s CaseSensative
+ Right $ AddMatching $ compileGlob s CaseSensative (GlobFilePath False)
| otherwise = Right $ AddRef $ Ref $ encodeBS s
- mk ('-':s) = Right $ RemoveMatching $ compileGlob s CaseSensative
+ mk ('-':s) = Right $ RemoveMatching $ compileGlob s CaseSensative (GlobFilePath False)
mk "reflog" = Right AddRefLog
mk s = Left $ "bad refspec item \"" ++ s ++ "\" (expected + or - prefix)"
-{-# 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
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
--- /dev/null
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2020-12-15T16:16:21Z"
+ content="""
+Hmm, yes preferred content expressions on windows ought
+to let `/` be used and still match on `\`. (And vice-versa, although then
+the preferred content expression is windows-specific.)
+
+I've implemented that now.
+"""]]