Switch to XDG path for config; Search conf in parents
- switch to XDG path should be backwards-compatible: - new config will be written to XDG path - but existing config in ~/.brittany will be respected - looks for "brittany.yaml" not only in cwd, but in parents too. uses the first file found. fixes #45, fixes #55pull/60/head
parent
5a12b63035
commit
a348ae7fbc
|
@ -292,15 +292,38 @@ coreIO putErrorLnIO config suppressOutput inputPathM outputPathM = EitherT.runEi
|
||||||
|
|
||||||
readConfigs :: CConfig Option -> [System.IO.FilePath] -> MaybeT IO Config
|
readConfigs :: CConfig Option -> [System.IO.FilePath] -> MaybeT IO Config
|
||||||
readConfigs cmdlineConfig configPaths = do
|
readConfigs cmdlineConfig configPaths = do
|
||||||
let defLocalConfigPath = "brittany.yaml"
|
userBritPathSimple <- liftIO $ Directory.getAppUserDataDirectory "brittany"
|
||||||
userBritPath <- liftIO $ Directory.getAppUserDataDirectory "brittany"
|
userBritPathXdg <- liftIO
|
||||||
let defUserConfigPath = userBritPath FilePath.</> "config.yaml"
|
$ Directory.getXdgDirectory Directory.XdgConfig "brittany"
|
||||||
merged <- case configPaths of
|
let userConfigPathSimple = userBritPathSimple FilePath.</> "config.yaml"
|
||||||
|
let userConfigPathXdg = userBritPathXdg FilePath.</> "config.yaml"
|
||||||
|
let
|
||||||
|
findLocalConfig :: MaybeT IO (Maybe (CConfig Option))
|
||||||
|
findLocalConfig = do
|
||||||
|
cwd <- liftIO $ Directory.getCurrentDirectory
|
||||||
|
let dirParts = FilePath.splitDirectories cwd
|
||||||
|
let searchDirs =
|
||||||
|
[ FilePath.joinPath x | x <- reverse $ List.inits dirParts ]
|
||||||
|
-- when cwd is "a/b/c", searchDirs is ["a/b/c", "a/b", "a", "/"]
|
||||||
|
mFilePath <- liftIO $ Directory.findFileWith Directory.doesFileExist
|
||||||
|
searchDirs
|
||||||
|
"brittany.yaml"
|
||||||
|
case mFilePath of
|
||||||
|
Nothing -> pure Nothing
|
||||||
|
Just fp -> readConfig fp
|
||||||
|
configsRead <- case configPaths of
|
||||||
[] -> do
|
[] -> do
|
||||||
liftIO $ Directory.createDirectoryIfMissing False userBritPath
|
localConfig <- findLocalConfig
|
||||||
return cmdlineConfig
|
userConfigSimple <- readConfig userConfigPathSimple
|
||||||
>>= readMergePersConfig defLocalConfigPath False
|
userConfigXdg <- readConfig userConfigPathXdg
|
||||||
>>= readMergePersConfig defUserConfigPath True
|
let userConfig = userConfigSimple <|> userConfigXdg
|
||||||
-- TODO: ensure that paths exist ?
|
when (Data.Maybe.isNothing userConfig) $ do
|
||||||
paths -> foldl (\prev p -> prev >>= readMergePersConfig p False) (return cmdlineConfig) paths
|
liftIO $ Directory.createDirectoryIfMissing False userBritPathXdg
|
||||||
|
writeDefaultConfig userConfigPathXdg
|
||||||
|
-- rightmost has highest priority
|
||||||
|
pure $ [userConfig, localConfig]
|
||||||
|
paths -> readConfig `mapM` reverse paths
|
||||||
|
-- reverse to give highest priority to the first
|
||||||
|
merged <-
|
||||||
|
pure $ Semigroup.mconcat $ catMaybes $ configsRead ++ [Just cmdlineConfig]
|
||||||
return $ cZipWith fromOptionIdentity staticDefaultConfig merged
|
return $ cZipWith fromOptionIdentity staticDefaultConfig merged
|
||||||
|
|
|
@ -8,7 +8,8 @@ module Language.Haskell.Brittany.Internal.Config
|
||||||
, configParser
|
, configParser
|
||||||
, staticDefaultConfig
|
, staticDefaultConfig
|
||||||
, forwardOptionsSyntaxExtsEnabled
|
, forwardOptionsSyntaxExtsEnabled
|
||||||
, readMergePersConfig
|
, readConfig
|
||||||
|
, writeDefaultConfig
|
||||||
, showConfigYaml
|
, showConfigYaml
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
@ -198,29 +199,37 @@ configParser = do
|
||||||
-- , infoIntersperse = True
|
-- , infoIntersperse = True
|
||||||
-- }
|
-- }
|
||||||
|
|
||||||
readMergePersConfig
|
|
||||||
:: System.IO.FilePath -> Bool -> CConfig Option -> MaybeT IO (CConfig Option)
|
-- | Reads a config from a file. If the file does not exist, returns
|
||||||
readMergePersConfig path shouldCreate conf = do
|
-- Nothing. If the file exists and parsing fails, prints to stderr and
|
||||||
|
-- aborts the MaybeT. Otherwise succeed via Just.
|
||||||
|
-- If the second parameter is True and the file does not exist, writes the
|
||||||
|
-- staticDefaultConfig to the file.
|
||||||
|
readConfig
|
||||||
|
:: MonadIO m => System.IO.FilePath -> MaybeT m (Maybe (CConfig Option))
|
||||||
|
readConfig path = do
|
||||||
exists <- liftIO $ System.Directory.doesFileExist path
|
exists <- liftIO $ System.Directory.doesFileExist path
|
||||||
if
|
if exists
|
||||||
| exists -> do
|
then do
|
||||||
contents <- liftIO $ ByteString.readFile path -- no lazy IO, tyvm.
|
contents <- liftIO $ ByteString.readFile path -- no lazy IO, tyvm.
|
||||||
fileConf <- case Data.Yaml.decodeEither contents of
|
fileConf <- case Data.Yaml.decodeEither contents of
|
||||||
Left e -> do
|
Left e -> do
|
||||||
liftIO
|
liftIO
|
||||||
$ putStrErrLn
|
$ putStrErrLn
|
||||||
$ "error reading in brittany config from " ++ path ++ ":"
|
$ "error reading in brittany config from "
|
||||||
liftIO $ putStrErrLn e
|
++ path
|
||||||
mzero
|
++ ":"
|
||||||
Right x -> return x
|
liftIO $ putStrErrLn e
|
||||||
return $ fileConf Semigroup.<> conf
|
mzero
|
||||||
| shouldCreate -> do
|
Right x -> return x
|
||||||
liftIO $ ByteString.writeFile path
|
return $ Just fileConf
|
||||||
$ Data.Yaml.encode
|
else return $ Nothing
|
||||||
$ cMap (Option . Just . runIdentity) staticDefaultConfig
|
|
||||||
return $ conf
|
writeDefaultConfig :: MonadIO m => System.IO.FilePath -> m ()
|
||||||
| otherwise -> do
|
writeDefaultConfig path =
|
||||||
return conf
|
liftIO $ ByteString.writeFile path $ Data.Yaml.encode $ cMap
|
||||||
|
(Option . Just . runIdentity)
|
||||||
|
staticDefaultConfig
|
||||||
|
|
||||||
showConfigYaml :: Config -> String
|
showConfigYaml :: Config -> String
|
||||||
showConfigYaml = Data.ByteString.Char8.unpack
|
showConfigYaml = Data.ByteString.Char8.unpack
|
||||||
|
|
Loading…
Reference in New Issue