git-annex/Types/FileMatcher.hs
2023-03-17 15:14:58 -04:00

104 lines
3.2 KiB
Haskell

{- git-annex file matcher types
-
- Copyright 2013-2021 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
module Types.FileMatcher where
import Types.UUID (UUID)
import Types.Key (Key)
import Types.Link (LinkType)
import Types.Mime
import Utility.Matcher (Matcher, Token)
import Utility.FileSize
import Utility.FileSystemEncoding
import Control.Monad.IO.Class
import qualified Data.Map as M
import qualified Data.Set as S
-- Information about a file and/or a key that can be matched on.
data MatchInfo
= MatchingFile FileInfo
| MatchingInfo ProvidedInfo
| MatchingUserInfo UserProvidedInfo
data FileInfo = FileInfo
{ contentFile :: RawFilePath
-- ^ path to a file containing the content, for operations
-- that examine it
, matchFile :: RawFilePath
-- ^ filepath to match on; may be relative to top of repo or cwd,
-- depending on how globs in preferred content expressions
-- are intended to be matched
, matchKey :: Maybe Key
-- ^ provided if a key is already known
}
data ProvidedInfo = ProvidedInfo
{ providedFilePath :: Maybe RawFilePath
-- ^ filepath to match on, should not be accessed from disk.
, providedKey :: Maybe Key
, providedFileSize :: Maybe FileSize
, providedMimeType :: Maybe MimeType
, providedMimeEncoding :: Maybe MimeEncoding
, providedLinkType :: Maybe LinkType
}
keyMatchInfoWithoutContent :: Key -> RawFilePath -> MatchInfo
keyMatchInfoWithoutContent key file = MatchingInfo $ ProvidedInfo
{ providedFilePath = Just file
, providedKey = Just key
, providedFileSize = Nothing
, providedMimeType = Nothing
, providedMimeEncoding = Nothing
, providedLinkType = Nothing
}
-- This is used when testing a matcher, with values to match against
-- provided by the user.
data UserProvidedInfo = UserProvidedInfo
{ userProvidedFilePath :: UserInfo FilePath
, userProvidedKey :: UserInfo Key
, userProvidedFileSize :: UserInfo FileSize
, userProvidedMimeType :: UserInfo MimeType
, userProvidedMimeEncoding :: UserInfo MimeEncoding
}
-- This may fail if the user did not provide the information.
type UserInfo a = Either (IO a) a
-- If the UserInfo is not available, accessing it may result in eg an
-- exception being thrown.
getUserInfo :: MonadIO m => UserInfo a -> m a
getUserInfo (Right i) = return i
getUserInfo (Left e) = liftIO e
type FileMatcherMap a = M.Map UUID (FileMatcher a)
type MkLimit a = String -> Either String (MatchFiles a)
type AssumeNotPresent = S.Set UUID
data MatchFiles a = MatchFiles
{ matchAction :: AssumeNotPresent -> MatchInfo -> a Bool
, matchNeedsFileName :: Bool
-- ^ does the matchAction need a filename in order to match?
, matchNeedsFileContent :: Bool
-- ^ does the matchAction need the file content to be present in
-- order to succeed?
, matchNeedsKey :: Bool
-- ^ does the matchAction look at information about the key?
, matchNeedsLocationLog :: Bool
-- ^ does the matchAction look at the location log?
}
type FileMatcher a = Matcher (MatchFiles a)
-- This is a matcher that can have tokens added to it while it's being
-- built, and once complete is compiled to an unchangeable matcher.
data ExpandableMatcher a
= BuildingMatcher [Token (MatchFiles a)]
| CompleteMatcher (Matcher (MatchFiles a))