2012-10-03 21:04:52 +00:00
|
|
|
{- git-annex command
|
|
|
|
-
|
2022-09-15 19:11:59 +00:00
|
|
|
- Copyright 2012-2022 Joey Hess <id@joeyh.name>
|
2012-10-03 21:04:52 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2012-10-03 21:04:52 +00:00
|
|
|
-}
|
|
|
|
|
2014-10-14 18:10:22 +00:00
|
|
|
{-# LANGUAGE RankNTypes #-}
|
|
|
|
|
2012-10-03 21:04:52 +00:00
|
|
|
module Command.Vicfg where
|
|
|
|
|
|
|
|
import qualified Data.Map as M
|
|
|
|
import qualified Data.Set as S
|
|
|
|
import System.Environment (getEnv)
|
|
|
|
import Data.Tuple (swap)
|
2012-10-03 23:13:21 +00:00
|
|
|
import Data.Char (isSpace)
|
2014-10-14 18:10:22 +00:00
|
|
|
import Data.Default
|
2018-04-13 19:16:07 +00:00
|
|
|
import Data.Ord
|
2012-10-03 21:04:52 +00:00
|
|
|
|
|
|
|
import Command
|
|
|
|
import Annex.Perms
|
|
|
|
import Types.TrustLevel
|
|
|
|
import Types.Group
|
|
|
|
import Logs.Trust
|
|
|
|
import Logs.Group
|
2012-10-04 19:48:59 +00:00
|
|
|
import Logs.PreferredContent
|
2013-10-07 21:11:13 +00:00
|
|
|
import Logs.Schedule
|
2017-01-30 21:08:05 +00:00
|
|
|
import Logs.Config
|
2017-01-30 19:11:26 +00:00
|
|
|
import Logs.NumCopies
|
2013-05-23 18:54:59 +00:00
|
|
|
import Types.StandardGroups
|
2013-10-07 21:11:13 +00:00
|
|
|
import Types.ScheduledActivity
|
2017-01-30 19:11:26 +00:00
|
|
|
import Types.NumCopies
|
2012-10-03 21:04:52 +00:00
|
|
|
import Remote
|
2020-06-22 15:03:28 +00:00
|
|
|
import Git.Types (fromConfigKey, fromConfigValue)
|
2020-11-24 16:38:12 +00:00
|
|
|
import qualified Utility.RawFilePath as R
|
2012-10-03 21:04:52 +00:00
|
|
|
|
2015-07-08 16:33:27 +00:00
|
|
|
cmd :: Command
|
2017-01-30 19:11:26 +00:00
|
|
|
cmd = command "vicfg" SectionSetup "edit configuration in git-annex branch"
|
2015-07-08 19:08:02 +00:00
|
|
|
paramNothing (withParams seek)
|
2012-10-03 21:04:52 +00:00
|
|
|
|
2015-07-08 19:08:02 +00:00
|
|
|
seek :: CmdParams -> CommandSeek
|
2018-10-01 18:12:06 +00:00
|
|
|
seek = withNothing (commandAction start)
|
2012-10-03 21:04:52 +00:00
|
|
|
|
|
|
|
start :: CommandStart
|
|
|
|
start = do
|
|
|
|
f <- fromRepo gitAnnexTmpCfgFile
|
2020-10-30 19:55:59 +00:00
|
|
|
let f' = fromRawFilePath f
|
2015-01-09 17:11:56 +00:00
|
|
|
createAnnexDirectory $ parentDir f
|
2012-10-03 23:13:21 +00:00
|
|
|
cfg <- getCfg
|
2012-10-13 03:11:26 +00:00
|
|
|
descs <- uuidDescriptions
|
2020-10-30 19:55:59 +00:00
|
|
|
liftIO $ writeFile f' $ genCfg cfg descs
|
|
|
|
vicfg cfg f'
|
2012-10-03 21:04:52 +00:00
|
|
|
stop
|
|
|
|
|
2012-10-03 23:13:21 +00:00
|
|
|
vicfg :: Cfg -> FilePath -> Annex ()
|
|
|
|
vicfg curcfg f = do
|
2012-10-03 21:04:52 +00:00
|
|
|
vi <- liftIO $ catchDefaultIO "vi" $ getEnv "EDITOR"
|
|
|
|
-- Allow EDITOR to be processed by the shell, so it can contain options.
|
2012-12-18 16:19:24 +00:00
|
|
|
unlessM (liftIO $ boolSystem "sh" [Param "-c", Param $ unwords [vi, shellEscape f]]) $
|
2016-11-16 01:29:54 +00:00
|
|
|
giveup $ vi ++ " exited nonzero; aborting"
|
2016-12-24 18:46:31 +00:00
|
|
|
r <- parseCfg (defCfg curcfg) <$> liftIO (readFileStrict f)
|
2020-11-24 16:38:12 +00:00
|
|
|
liftIO $ removeWhenExistsWith R.removeLink (toRawFilePath f)
|
2012-10-03 21:04:52 +00:00
|
|
|
case r of
|
|
|
|
Left s -> do
|
2016-12-24 18:46:31 +00:00
|
|
|
liftIO $ writeFile f s
|
2012-10-03 23:13:21 +00:00
|
|
|
vicfg curcfg f
|
2012-10-03 23:37:39 +00:00
|
|
|
Right newcfg -> setCfg curcfg newcfg
|
2012-10-03 21:04:52 +00:00
|
|
|
|
|
|
|
data Cfg = Cfg
|
2018-04-13 19:16:07 +00:00
|
|
|
{ cfgTrustMap :: M.Map UUID (Down TrustLevel)
|
2012-10-03 21:04:52 +00:00
|
|
|
, cfgGroupMap :: M.Map UUID (S.Set Group)
|
2014-03-15 20:17:01 +00:00
|
|
|
, cfgPreferredContentMap :: M.Map UUID PreferredContentExpression
|
2014-03-29 19:20:55 +00:00
|
|
|
, cfgRequiredContentMap :: M.Map UUID PreferredContentExpression
|
2014-03-15 20:17:01 +00:00
|
|
|
, cfgGroupPreferredContentMap :: M.Map Group PreferredContentExpression
|
2013-10-07 21:11:13 +00:00
|
|
|
, cfgScheduleMap :: M.Map UUID [ScheduledActivity]
|
2019-12-05 18:36:43 +00:00
|
|
|
, cfgGlobalConfigs :: M.Map ConfigKey ConfigValue
|
2017-01-30 19:11:26 +00:00
|
|
|
, cfgNumCopies :: Maybe NumCopies
|
2022-09-15 19:11:59 +00:00
|
|
|
, cfgMinCopies :: Maybe MinCopies
|
2012-10-03 21:04:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getCfg :: Annex Cfg
|
|
|
|
getCfg = Cfg
|
2018-04-13 19:16:07 +00:00
|
|
|
<$> (M.map Down <$> trustMapRaw) -- without local trust overrides
|
2012-10-03 21:04:52 +00:00
|
|
|
<*> (groupsByUUID <$> groupMap)
|
2012-10-04 19:48:59 +00:00
|
|
|
<*> preferredContentMapRaw
|
2014-03-29 19:20:55 +00:00
|
|
|
<*> requiredContentMapRaw
|
2014-03-15 20:17:01 +00:00
|
|
|
<*> groupPreferredContentMapRaw
|
2013-10-07 21:11:13 +00:00
|
|
|
<*> scheduleMap
|
2017-01-30 21:08:05 +00:00
|
|
|
<*> loadGlobalConfig
|
2017-01-30 19:11:26 +00:00
|
|
|
<*> getGlobalNumCopies
|
2022-09-15 19:11:59 +00:00
|
|
|
<*> getGlobalMinCopies
|
2012-10-03 21:04:52 +00:00
|
|
|
|
2012-10-03 23:37:39 +00:00
|
|
|
setCfg :: Cfg -> Cfg -> Annex ()
|
|
|
|
setCfg curcfg newcfg = do
|
2014-03-15 20:17:01 +00:00
|
|
|
let diff = diffCfg curcfg newcfg
|
2018-04-13 19:16:07 +00:00
|
|
|
mapM_ (uncurry trustSet) $ M.toList $ M.map (\(Down v) -> v) $ cfgTrustMap diff
|
2014-03-15 20:17:01 +00:00
|
|
|
mapM_ (uncurry groupSet) $ M.toList $ cfgGroupMap diff
|
|
|
|
mapM_ (uncurry preferredContentSet) $ M.toList $ cfgPreferredContentMap diff
|
2014-03-29 19:20:55 +00:00
|
|
|
mapM_ (uncurry requiredContentSet) $ M.toList $ cfgRequiredContentMap diff
|
2014-03-15 20:17:01 +00:00
|
|
|
mapM_ (uncurry groupPreferredContentSet) $ M.toList $ cfgGroupPreferredContentMap diff
|
|
|
|
mapM_ (uncurry scheduleSet) $ M.toList $ cfgScheduleMap diff
|
2017-01-30 21:08:05 +00:00
|
|
|
mapM_ (uncurry setGlobalConfig) $ M.toList $ cfgGlobalConfigs diff
|
2017-01-30 19:11:26 +00:00
|
|
|
maybe noop setGlobalNumCopies $ cfgNumCopies diff
|
2022-09-15 19:11:59 +00:00
|
|
|
maybe noop setGlobalMinCopies $ cfgMinCopies diff
|
2014-03-15 20:17:01 +00:00
|
|
|
|
2014-10-14 18:10:22 +00:00
|
|
|
{- Default config has all the keys from the input config, but with their
|
|
|
|
- default values. -}
|
|
|
|
defCfg :: Cfg -> Cfg
|
|
|
|
defCfg curcfg = Cfg
|
|
|
|
{ cfgTrustMap = mapdef $ cfgTrustMap curcfg
|
|
|
|
, cfgGroupMap = mapdef $ cfgGroupMap curcfg
|
|
|
|
, cfgPreferredContentMap = mapdef $ cfgPreferredContentMap curcfg
|
|
|
|
, cfgRequiredContentMap = mapdef $ cfgRequiredContentMap curcfg
|
|
|
|
, cfgGroupPreferredContentMap = mapdef $ cfgGroupPreferredContentMap curcfg
|
|
|
|
, cfgScheduleMap = mapdef $ cfgScheduleMap curcfg
|
2017-01-30 21:08:05 +00:00
|
|
|
, cfgGlobalConfigs = mapdef $ cfgGlobalConfigs curcfg
|
2017-01-30 19:11:26 +00:00
|
|
|
, cfgNumCopies = Nothing
|
2022-09-15 19:11:59 +00:00
|
|
|
, cfgMinCopies = Nothing
|
2014-10-14 18:10:22 +00:00
|
|
|
}
|
|
|
|
where
|
|
|
|
mapdef :: forall k v. Default v => M.Map k v -> M.Map k v
|
2014-10-14 18:20:10 +00:00
|
|
|
mapdef = M.map (const def)
|
2014-10-14 18:10:22 +00:00
|
|
|
|
2014-03-15 20:17:01 +00:00
|
|
|
diffCfg :: Cfg -> Cfg -> Cfg
|
|
|
|
diffCfg curcfg newcfg = Cfg
|
|
|
|
{ cfgTrustMap = diff cfgTrustMap
|
|
|
|
, cfgGroupMap = diff cfgGroupMap
|
|
|
|
, cfgPreferredContentMap = diff cfgPreferredContentMap
|
2014-03-29 19:20:55 +00:00
|
|
|
, cfgRequiredContentMap = diff cfgRequiredContentMap
|
2014-03-15 20:17:01 +00:00
|
|
|
, cfgGroupPreferredContentMap = diff cfgGroupPreferredContentMap
|
|
|
|
, cfgScheduleMap = diff cfgScheduleMap
|
2017-01-30 21:08:05 +00:00
|
|
|
, cfgGlobalConfigs = diff cfgGlobalConfigs
|
2017-01-30 19:11:26 +00:00
|
|
|
, cfgNumCopies = cfgNumCopies newcfg
|
2022-09-15 19:11:59 +00:00
|
|
|
, cfgMinCopies = cfgMinCopies newcfg
|
2014-03-15 20:17:01 +00:00
|
|
|
}
|
2012-11-12 05:05:04 +00:00
|
|
|
where
|
|
|
|
diff f = M.differenceWith (\x y -> if x == y then Nothing else Just x)
|
|
|
|
(f newcfg) (f curcfg)
|
2012-10-03 21:04:52 +00:00
|
|
|
|
2019-01-01 19:39:45 +00:00
|
|
|
genCfg :: Cfg -> UUIDDescMap -> String
|
2014-03-15 20:17:01 +00:00
|
|
|
genCfg cfg descs = unlines $ intercalate [""]
|
|
|
|
[ intro
|
|
|
|
, trust
|
|
|
|
, groups
|
|
|
|
, preferredcontent
|
|
|
|
, grouppreferredcontent
|
|
|
|
, standardgroups
|
2014-03-29 19:20:55 +00:00
|
|
|
, requiredcontent
|
2014-03-15 20:17:01 +00:00
|
|
|
, schedule
|
2017-01-30 21:08:05 +00:00
|
|
|
, numcopies
|
|
|
|
, globalconfigs
|
2014-03-15 20:17:01 +00:00
|
|
|
]
|
2012-11-12 05:05:04 +00:00
|
|
|
where
|
|
|
|
intro =
|
|
|
|
[ com "git-annex configuration"
|
|
|
|
, com ""
|
|
|
|
, com "Changes saved to this file will be recorded in the git-annex branch."
|
|
|
|
, com ""
|
|
|
|
, com "Lines in this file have the format:"
|
2014-03-15 20:17:01 +00:00
|
|
|
, com " setting field = value"
|
2012-11-12 05:05:04 +00:00
|
|
|
]
|
|
|
|
|
2018-04-13 19:16:07 +00:00
|
|
|
trust = settings cfg descs cfgTrustMap
|
2014-03-15 20:17:01 +00:00
|
|
|
[ com "Repository trust configuration"
|
2013-05-23 18:54:59 +00:00
|
|
|
, com "(Valid trust levels: " ++ trustlevels ++ ")"
|
2012-11-12 05:05:04 +00:00
|
|
|
]
|
2018-04-13 19:16:07 +00:00
|
|
|
(\(Down t, u) -> line "trust" u $ showTrustLevel t)
|
2014-10-14 18:20:10 +00:00
|
|
|
(\u -> lcom $ line "trust" u $ showTrustLevel def)
|
2013-05-23 18:54:59 +00:00
|
|
|
where
|
2018-04-13 19:16:07 +00:00
|
|
|
trustlevels = unwords $ reverse $
|
|
|
|
map showTrustLevel [minBound..maxBound]
|
2012-11-12 05:05:04 +00:00
|
|
|
|
2014-03-15 20:17:01 +00:00
|
|
|
groups = settings cfg descs cfgGroupMap
|
|
|
|
[ com "Repository groups"
|
2013-05-23 18:54:59 +00:00
|
|
|
, com $ "(Standard groups: " ++ grouplist ++ ")"
|
2012-11-12 05:05:04 +00:00
|
|
|
, com "(Separate group names with spaces)"
|
|
|
|
]
|
2019-01-09 19:00:43 +00:00
|
|
|
(\(s, u) -> line "group" u $ unwords $ map fromGroup $ S.toList s)
|
2012-11-12 05:05:04 +00:00
|
|
|
(\u -> lcom $ line "group" u "")
|
2013-05-23 18:54:59 +00:00
|
|
|
where
|
2019-01-09 19:00:43 +00:00
|
|
|
grouplist = unwords $ map (fromGroup . fromStandardGroup) [minBound..]
|
2012-11-12 05:05:04 +00:00
|
|
|
|
2014-03-15 20:17:01 +00:00
|
|
|
preferredcontent = settings cfg descs cfgPreferredContentMap
|
2014-07-11 18:30:36 +00:00
|
|
|
[ com "Repository preferred contents"
|
|
|
|
, com "(Set to \"standard\" to use a repository's group's preferred contents)"
|
|
|
|
]
|
2014-03-15 20:17:01 +00:00
|
|
|
(\(s, u) -> line "wanted" u s)
|
2014-07-11 18:30:36 +00:00
|
|
|
(\u -> line "wanted" u "")
|
2014-03-29 19:20:55 +00:00
|
|
|
|
|
|
|
requiredcontent = settings cfg descs cfgRequiredContentMap
|
|
|
|
[ com "Repository required contents" ]
|
|
|
|
(\(s, u) -> line "required" u s)
|
|
|
|
(\u -> line "required" u "")
|
2014-03-15 20:17:01 +00:00
|
|
|
|
|
|
|
grouppreferredcontent = settings' cfg allgroups cfgGroupPreferredContentMap
|
|
|
|
[ com "Group preferred contents"
|
|
|
|
, com "(Used by repositories with \"groupwanted\" in their preferred contents)"
|
2012-11-12 05:05:04 +00:00
|
|
|
]
|
2014-03-15 20:17:01 +00:00
|
|
|
(\(s, g) -> gline g s)
|
2014-07-11 18:30:36 +00:00
|
|
|
(\g -> gline g "")
|
2014-03-15 20:17:01 +00:00
|
|
|
where
|
2019-01-09 19:00:43 +00:00
|
|
|
gline g val = [ unwords ["groupwanted", fromGroup g, "=", val] ]
|
2014-03-15 20:17:01 +00:00
|
|
|
allgroups = S.unions $ stdgroups : M.elems (cfgGroupMap cfg)
|
|
|
|
stdgroups = S.fromList $ map fromStandardGroup [minBound..maxBound]
|
2012-11-12 05:05:04 +00:00
|
|
|
|
2014-03-15 20:17:01 +00:00
|
|
|
standardgroups =
|
|
|
|
[ com "Standard preferred contents"
|
|
|
|
, com "(Used by wanted or groupwanted expressions containing \"standard\")"
|
|
|
|
, com "(For reference only; built-in and cannot be changed!)"
|
|
|
|
]
|
|
|
|
++ map gline [minBound..maxBound]
|
|
|
|
where
|
|
|
|
gline g = com $ unwords
|
|
|
|
[ "standard"
|
2019-01-09 19:00:43 +00:00
|
|
|
, fromGroup (fromStandardGroup g), "=", standardPreferredContent g
|
2014-03-15 20:17:01 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
schedule = settings cfg descs cfgScheduleMap
|
|
|
|
[ com "Scheduled activities"
|
2013-10-07 21:11:13 +00:00
|
|
|
, com "(Separate multiple activities with \"; \")"
|
|
|
|
]
|
2013-10-13 19:40:38 +00:00
|
|
|
(\(l, u) -> line "schedule" u $ fromScheduledActivities l)
|
2013-10-07 21:11:13 +00:00
|
|
|
(\u -> line "schedule" u "")
|
|
|
|
|
2017-01-30 21:08:05 +00:00
|
|
|
globalconfigs = settings' cfg S.empty cfgGlobalConfigs
|
|
|
|
[ com "Other global configuration"
|
|
|
|
]
|
|
|
|
(\(s, g) -> gline g s)
|
2019-12-05 18:36:43 +00:00
|
|
|
(\g -> gline g mempty)
|
2017-01-30 21:08:05 +00:00
|
|
|
where
|
2019-12-05 18:36:43 +00:00
|
|
|
gline k v = [ unwords ["config", fromConfigKey k, "=", fromConfigValue v] ]
|
2017-01-30 21:08:05 +00:00
|
|
|
|
2015-07-11 00:40:30 +00:00
|
|
|
line setting u val =
|
2019-01-01 19:39:45 +00:00
|
|
|
[ com $ "(for " ++ fromUUIDDesc (fromMaybe mempty (M.lookup u descs)) ++ ")"
|
2015-07-11 00:40:30 +00:00
|
|
|
, unwords [setting, fromUUID u, "=", val]
|
2012-11-12 05:05:04 +00:00
|
|
|
]
|
2017-01-30 19:11:26 +00:00
|
|
|
|
|
|
|
line' setting Nothing = com $ unwords [setting, "default", "="]
|
|
|
|
line' setting (Just val) = unwords [setting, "default", "=", val]
|
|
|
|
|
2017-01-30 21:08:05 +00:00
|
|
|
numcopies =
|
|
|
|
[ com "Numcopies configuration"
|
2017-01-30 19:11:26 +00:00
|
|
|
, line' "numcopies" (show . fromNumCopies <$> cfgNumCopies cfg)
|
2022-09-15 19:11:59 +00:00
|
|
|
, line' "mincopies" (show . fromMinCopies <$> cfgMinCopies cfg)
|
2017-01-30 19:11:26 +00:00
|
|
|
]
|
2014-03-15 20:17:01 +00:00
|
|
|
|
2019-01-01 19:39:45 +00:00
|
|
|
settings :: Ord v => Cfg -> UUIDDescMap -> (Cfg -> M.Map UUID v) -> [String] -> ((v, UUID) -> [String]) -> (UUID -> [String]) -> [String]
|
2014-03-15 20:17:01 +00:00
|
|
|
settings cfg descs = settings' cfg (M.keysSet descs)
|
|
|
|
|
|
|
|
settings' :: (Ord v, Ord f) => Cfg -> S.Set f -> (Cfg -> M.Map f v) -> [String] -> ((v, f) -> [String]) -> (f -> [String]) -> [String]
|
|
|
|
settings' cfg s field desc showvals showdefaults = concat
|
|
|
|
[ desc
|
|
|
|
, concatMap showvals $ sort $ map swap $ M.toList $ field cfg
|
|
|
|
, concatMap (lcom . showdefaults) missing
|
|
|
|
]
|
|
|
|
where
|
|
|
|
missing = S.toList $ s `S.difference` M.keysSet (field cfg)
|
|
|
|
|
|
|
|
lcom :: [String] -> [String]
|
|
|
|
lcom = map (\l -> if "#" `isPrefixOf` l then l else '#' : l)
|
2012-10-03 21:04:52 +00:00
|
|
|
|
|
|
|
{- If there's a parse error, returns a new version of the file,
|
|
|
|
- with the problem lines noted. -}
|
2012-10-03 23:13:21 +00:00
|
|
|
parseCfg :: Cfg -> String -> Either String Cfg
|
2014-10-14 18:10:22 +00:00
|
|
|
parseCfg defcfg = go [] defcfg . lines
|
2012-11-12 05:05:04 +00:00
|
|
|
where
|
|
|
|
go c cfg []
|
2013-09-25 07:09:06 +00:00
|
|
|
| null (mapMaybe fst c) = Right cfg
|
2012-11-12 05:05:04 +00:00
|
|
|
| otherwise = Left $ unlines $
|
|
|
|
badheader ++ concatMap showerr (reverse c)
|
|
|
|
go c cfg (l:ls) = case parse (dropWhile isSpace l) cfg of
|
|
|
|
Left msg -> go ((Just msg, l):c) cfg ls
|
|
|
|
Right cfg' -> go ((Nothing, l):c) cfg' ls
|
|
|
|
|
|
|
|
parse l cfg
|
|
|
|
| null l = Right cfg
|
|
|
|
| "#" `isPrefixOf` l = Right cfg
|
2014-03-15 20:17:01 +00:00
|
|
|
| null setting || null f = Left "missing field"
|
2015-07-11 00:40:30 +00:00
|
|
|
| otherwise = parsed cfg f setting val'
|
2012-11-12 05:05:04 +00:00
|
|
|
where
|
|
|
|
(setting, rest) = separate isSpace l
|
2015-07-11 00:40:30 +00:00
|
|
|
(r, val) = separate (== '=') rest
|
|
|
|
val' = trimspace val
|
2014-03-15 20:17:01 +00:00
|
|
|
f = reverse $ trimspace $ reverse $ trimspace r
|
2012-11-12 05:05:04 +00:00
|
|
|
trimspace = dropWhile isSpace
|
|
|
|
|
2015-07-11 00:40:30 +00:00
|
|
|
parsed cfg f setting val
|
|
|
|
| setting == "trust" = case readTrustLevel val of
|
|
|
|
Nothing -> badval "trust value" val
|
2012-11-12 05:05:04 +00:00
|
|
|
Just t ->
|
2018-04-13 19:16:07 +00:00
|
|
|
let m = M.insert u (Down t) (cfgTrustMap cfg)
|
2012-11-12 05:05:04 +00:00
|
|
|
in Right $ cfg { cfgTrustMap = m }
|
|
|
|
| setting == "group" =
|
2019-01-09 19:00:43 +00:00
|
|
|
let m = M.insert u (S.fromList $ map toGroup $ words val) (cfgGroupMap cfg)
|
2012-11-12 05:05:04 +00:00
|
|
|
in Right $ cfg { cfgGroupMap = m }
|
2014-03-15 20:17:01 +00:00
|
|
|
| setting == "wanted" =
|
2015-07-11 00:40:30 +00:00
|
|
|
case checkPreferredContentExpression val of
|
2012-11-12 05:05:04 +00:00
|
|
|
Just e -> Left e
|
|
|
|
Nothing ->
|
2015-07-11 00:40:30 +00:00
|
|
|
let m = M.insert u val (cfgPreferredContentMap cfg)
|
2012-11-12 05:05:04 +00:00
|
|
|
in Right $ cfg { cfgPreferredContentMap = m }
|
2014-03-29 19:20:55 +00:00
|
|
|
| setting == "required" =
|
2015-07-11 00:40:30 +00:00
|
|
|
case checkPreferredContentExpression val of
|
2014-03-29 19:20:55 +00:00
|
|
|
Just e -> Left e
|
|
|
|
Nothing ->
|
2015-07-11 00:40:30 +00:00
|
|
|
let m = M.insert u val (cfgRequiredContentMap cfg)
|
2014-03-29 19:20:55 +00:00
|
|
|
in Right $ cfg { cfgRequiredContentMap = m }
|
2014-03-15 20:17:01 +00:00
|
|
|
| setting == "groupwanted" =
|
2015-07-11 00:40:30 +00:00
|
|
|
case checkPreferredContentExpression val of
|
2014-03-15 20:17:01 +00:00
|
|
|
Just e -> Left e
|
|
|
|
Nothing ->
|
2019-01-09 19:00:43 +00:00
|
|
|
let m = M.insert (toGroup f) val (cfgGroupPreferredContentMap cfg)
|
2014-03-15 20:17:01 +00:00
|
|
|
in Right $ cfg { cfgGroupPreferredContentMap = m }
|
2015-07-11 00:40:30 +00:00
|
|
|
| setting == "schedule" = case parseScheduledActivities val of
|
2013-10-13 19:40:38 +00:00
|
|
|
Left e -> Left e
|
|
|
|
Right l ->
|
|
|
|
let m = M.insert u l (cfgScheduleMap cfg)
|
|
|
|
in Right $ cfg { cfgScheduleMap = m }
|
2017-01-30 21:08:05 +00:00
|
|
|
| setting == "config" =
|
2021-08-11 00:45:02 +00:00
|
|
|
let m = M.insert (ConfigKey (encodeBS f)) (ConfigValue (encodeBS val)) (cfgGlobalConfigs cfg)
|
2017-01-30 21:08:05 +00:00
|
|
|
in Right $ cfg { cfgGlobalConfigs = m }
|
2017-01-30 19:11:26 +00:00
|
|
|
| setting == "numcopies" = case readish val of
|
|
|
|
Nothing -> Left "parse error (expected an integer)"
|
2022-03-28 19:19:52 +00:00
|
|
|
Just n -> Right $ cfg { cfgNumCopies = Just (configuredNumCopies n) }
|
2022-09-15 19:11:59 +00:00
|
|
|
| setting == "mincopies" = case readish val of
|
|
|
|
Nothing -> Left "parse error (expected an integer)"
|
|
|
|
Just n -> Right $ cfg { cfgMinCopies = Just (configuredMinCopies n) }
|
2012-11-12 05:05:04 +00:00
|
|
|
| otherwise = badval "setting" setting
|
2014-03-15 20:17:01 +00:00
|
|
|
where
|
|
|
|
u = toUUID f
|
2012-11-12 05:05:04 +00:00
|
|
|
|
|
|
|
showerr (Just msg, l) = [parseerr ++ msg, l]
|
|
|
|
showerr (Nothing, l)
|
|
|
|
-- filter out the header and parse error lines
|
|
|
|
-- from any previous parse failure
|
|
|
|
| any (`isPrefixOf` l) (parseerr:badheader) = []
|
|
|
|
| otherwise = [l]
|
|
|
|
|
|
|
|
badval desc val = Left $ "unknown " ++ desc ++ " \"" ++ val ++ "\""
|
|
|
|
badheader =
|
2014-03-15 20:17:01 +00:00
|
|
|
[ com "** There was a problem parsing your input!"
|
|
|
|
, com "** Search for \"Parse error\" to find the bad lines."
|
|
|
|
, com "** Either fix the bad lines, or delete them (to discard your changes)."
|
2012-11-12 05:05:04 +00:00
|
|
|
]
|
2014-03-15 20:17:01 +00:00
|
|
|
parseerr = com "** Parse error in next line: "
|
2012-10-03 23:13:21 +00:00
|
|
|
|
|
|
|
com :: String -> String
|
|
|
|
com s = "# " ++ s
|