git-annex/Config/RemoteConfig.hs
Joey Hess 71f78fe45d
wip separate RemoteConfig parsing
Remote now contains a ParsedRemoteConfig. The parsing happens when the
Remote is constructed, rather than when individual configs are used.

This is more efficient, and it lets initremote/enableremote
reject configs that have unknown fields or unparsable values.

It also allows for improved type safety, as shown in
Remote.Helper.Encryptable where things that used to match on string
configs now match on data types.

This is a work in progress, it does not build yet.

The main risk in this conversion is forgetting to add a field to
RemoteConfigParser. That will prevent using that field with
initremote/enableremote, and will prevent remotes that already are set
up from seeing that configuration. So will need to check carefully that
every field that getRemoteConfigValue is called on has been added to
RemoteConfigParser.

(One such case I need to remember is that credPairRemoteField needs to be
included in the RemoteConfigParser.)
2020-01-13 12:39:21 -04:00

44 lines
1.3 KiB
Haskell

{- git-annex remote config parsing
-
- Copyright 2020 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
module Config.RemoteConfig where
import qualified Data.Map as M
import Data.Typeable
import Types.RemoteConfig
import Types.ProposedAccepted
import Config
parseRemoteConfig :: RemoteConfig -> [RemoteConfigParser] -> Either String ParsedRemoteConfig
parseRemoteConfig c = go [] (M.filterWithKey notaccepted c)
where
go l c' []
| M.null c' = Right (M.fromList l)
| otherwise = Left $ "Unexpected fields: " ++
unwords (map fromProposedAccepted (M.keys c'))
go l c' ((f, p):rest) = do
v <- p (M.lookup f c) c
go ((f,v):l) (M.delete f c') rest
notaccepted (Proposed _) _ = True
notaccepted (Accepted _) _ = False
yesNoParser :: RemoteConfigField -> Bool -> RemoteConfigParser
yesNoParser f fallback = (f, p)
where
p v _c = case v of
Nothing -> Right (RemoteConfigValue fallback)
Just v' -> case yesNo (fromProposedAccepted v') of
Just b -> Right (RemoteConfigValue b)
Nothing -> case v' of
Accepted _ -> Right (RemoteConfigValue fallback)
Proposed _ -> Left $
"bad " ++ fromProposedAccepted f ++
" value (expected yes or no)"
optStringParser :: RemoteConfigField -> RemoteConfigParser
optStringParser f = (f, \v _c -> Right (RemoteConfigValue v))