ribosome-0.9.9.9: lib/Ribosome/Interpreter/PersistPath.hs
-- |Interpreters for 'PersistPath'
module Ribosome.Interpreter.PersistPath where
import Path (Abs, Dir, Path, Rel, parseRelDir, (</>))
import Path.IO (XdgDirectory (XdgCache), createDirIfMissing, getXdgDir)
import Ribosome.Data.PersistPathError (PersistPathError (Permissions, Undefined))
import Ribosome.Data.PluginName (PluginName (unPluginName))
import Ribosome.Data.SettingError (SettingError)
import qualified Ribosome.Effect.PersistPath as PersistPath
import Ribosome.Effect.PersistPath (PersistPath (PersistPath))
import qualified Ribosome.Effect.Settings as Settings
import Ribosome.Effect.Settings (Settings)
import Ribosome.Host.Data.BootError (BootError)
import Ribosome.PluginName (pluginName)
-- |Append an optional subdir to a dir.
maybeSubdir :: Path b Dir -> Maybe (Path Rel Dir) -> Path b Dir
maybeSubdir root = \case
Just sub ->
root </> sub
Nothing ->
root
-- |Append an optional subdir to a dir and ensure existence of the resulting directory if 'True' is given.
persistPath ::
Members [Stop PersistPathError, Embed IO] r =>
Bool ->
Path Abs Dir ->
Maybe (Path Rel Dir) ->
Sem r (Path Abs Dir)
persistPath create base sub = do
when create (stopTryAny (const (Permissions path)) (createDirIfMissing True path))
pure path
where
path =
maybeSubdir base sub
-- |Interpret 'PersistPath' by using the specified root directory.
interpretPersistPathAt ::
Member (Embed IO) r =>
Bool ->
Path Abs Dir ->
InterpreterFor (PersistPath !! PersistPathError) r
interpretPersistPathAt create base =
interpretResumable \case
PersistPath sub ->
persistPath create base sub
-- |Look up the XDG cache directory, returning 'Nothing' if it is unavailable.
xdgCache ::
Member (Embed IO) r =>
Sem r (Maybe (Path Abs Dir))
xdgCache =
rightToMaybe <$> tryAny (getXdgDir XdgCache Nothing)
-- |Interpret 'PersistPath' by reading the global setting for the root directory, or using the given directory if the
-- variable is unset.
--
-- The given @name@ is appended to the root, which usually identifies the plugin.
interpretPersistPathSetting ::
Members [Settings !! SettingError, Embed IO] r =>
Bool ->
Maybe (Path Abs Dir) ->
Path Rel Dir ->
InterpreterFor (PersistPath !! PersistPathError) r
interpretPersistPathSetting create fallback name =
interpretResumable \case
PersistPath sub -> do
base <- stopNote Undefined . (<|> fallback) =<< Settings.maybe PersistPath.setting
persistPath create (base </> name) sub
-- |Interpret 'PersistPath' by reading the global setting for the root directory, or using the XDG cache directory if
-- the variable is unset.
--
-- The plugin name is used as a subdir of the root.
--
-- This uses 'Resumable', see [Errors]("Ribosome#errors").
interpretPersistPath ::
Members [Settings !! SettingError, Reader PluginName, Error BootError, Embed IO] r =>
Bool ->
InterpreterFor (PersistPath !! PersistPathError) r
interpretPersistPath create sem = do
xdg <- xdgCache
name <- note "plugin name not suitable for file system paths" . parseRelDir . toString . unPluginName =<< pluginName
interpretPersistPathSetting create xdg name sem