{- git-annex remote config types - - Copyright 2020 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} {-# LANGUAGE GADTs #-} module Types.RemoteConfig where import qualified Data.Map as M import qualified Data.Set as S import Data.Typeable import Types.ProposedAccepted type RemoteConfigField = ProposedAccepted String {- What the user provides to configure the remote, and what is stored for - later; a bunch of fields and values. -} type RemoteConfig = M.Map RemoteConfigField (ProposedAccepted String) {- Before being used a RemoteConfig has to be parsed. -} data ParsedRemoteConfig = ParsedRemoteConfig { parsedRemoteConfigMap :: M.Map RemoteConfigField RemoteConfigValue , unparsedRemoteConfig :: RemoteConfig } {- Remotes can have configuration values of many types, so use Typeable - to let them all be stored in here. -} data RemoteConfigValue where RemoteConfigValue :: Typeable v => v -> RemoteConfigValue {- Parse a field's value provided by the user into a RemoteConfigValue. - - The RemoteConfig is provided to the parser function for cases - where multiple fields need to be looked at. However, it's important - that, when a parser looks at an additional field in that way, the - parser list contains a dedicated parser for that field as well. - Presence of fields that are not included in this list will cause - a parse failure. -} data RemoteConfigFieldParser = RemoteConfigFieldParser { parserForField :: RemoteConfigField , valueParser :: Maybe (ProposedAccepted String) -> RemoteConfig -> Either String (Maybe RemoteConfigValue) , fieldDesc :: FieldDesc , valueDesc :: Maybe ValueDesc } data FieldDesc = FieldDesc String | HiddenField | DeprecatedField deriving (Eq) newtype ValueDesc = ValueDesc String data RemoteConfigParser = RemoteConfigParser { remoteConfigFieldParsers :: [RemoteConfigFieldParser] , remoteConfigRestPassthrough :: Maybe (RemoteConfigField -> Bool, [(String, FieldDesc)]) } mkRemoteConfigParser :: Monad m => [RemoteConfigFieldParser] -> RemoteConfig -> m RemoteConfigParser mkRemoteConfigParser l _ = pure (RemoteConfigParser l Nothing) addRemoteConfigParser :: [RemoteConfigFieldParser] -> RemoteConfigParser -> RemoteConfigParser addRemoteConfigParser l rpc = rpc { remoteConfigFieldParsers = remoteConfigFieldParsers rpc ++ filter isnew l } where s = S.fromList (map parserForField (remoteConfigFieldParsers rpc)) isnew p = not (S.member (parserForField p) s)