-- | Maintainer: Sean Whitton module Propellor.Property.Locale where import Propellor.Base import Propellor.Property.File import qualified Propellor.Property.Apt as Apt import Data.List (isPrefixOf) type Locale = String type LocaleVariable = String -- | Select a locale for a list of global locale variables. -- -- A locale variable is of the form @LC_BLAH@, @LANG@ or @LANGUAGE@. See -- @locale(5)@. One might say -- -- > & "en_GB.UTF-8" `Locale.selectedFor` ["LC_PAPER", "LC_MONETARY"] -- -- to select the British English locale for paper size and currency conventions. -- -- Note that reverting this property does not make a locale unavailable. That's -- because it might be required for other Locale.selectedFor statements. selectedFor :: Locale -> [LocaleVariable] -> RevertableProperty DebianLike DebianLike locale `selectedFor` vars = select deselect where select = tightenTargets $ check (not <$> isselected) (cmdProperty "update-locale" selectArgs) `requires` available locale `describe` (locale ++ " locale selected") deselect = tightenTargets $ check isselected (cmdProperty "update-locale" vars) `describe` (locale ++ " locale deselected") selectArgs = zipWith (++) vars (repeat ('=':locale)) isselected = locale `isSelectedFor` vars isSelectedFor :: Locale -> [LocaleVariable] -> IO Bool locale `isSelectedFor` vars = do ls <- catchDefaultIO [] $ lines <$> readFile "/etc/default/locale" return $ and $ map (\v -> v ++ "=" ++ locale `elem` ls) vars -- | Ensures a locale is generated (or, if reverted, ensure it's not). -- -- Fails if a locale is not available to be generated. That is, a commented out -- entry for the locale and an accompanying charset must be present in -- /etc/locale.gen. -- -- Per Debian bug #684134 we cannot ensure a locale is generated by means of -- Apt.reConfigure. So localeAvailable edits /etc/locale.gen manually. available :: Locale -> RevertableProperty DebianLike DebianLike available locale = ensureAvailable `requires` Apt.installed ["locales"] ensureUnavailable where f = "/etc/locale.gen" desc = (locale ++ " locale generated") ensureAvailable :: Property DebianLike ensureAvailable = property' desc $ \w -> do locales <- lines <$> (liftIO $ readFile f) if locale `presentIn` locales then ensureProperty w $ fileProperty desc (foldr uncomment []) f `onChange` regenerate else error $ "locale " ++ locale ++ " is not present in /etc/locale.gen, even in commented out form; cannot generate" ensureUnavailable :: Property DebianLike ensureUnavailable = tightenTargets $ fileProperty (locale ++ " locale not generated") (foldr comment []) f `onChange` regenerate uncomment l ls = if ("# " ++ locale) `isPrefixOf` l then drop 2 l : ls else l:ls comment l ls = if locale `isPrefixOf` l then ("# " ++ l) : ls else l:ls l `presentIn` ls = any (l `isPrefix`) ls l `isPrefix` x = (l `isPrefixOf` x) || (("# " ++ l) `isPrefixOf` x) regenerate = cmdProperty "locale-gen" [] `assume` MadeChange