module HBS2Git.Config ( module HBS2Git.Config , module Data.Config.Suckless ) where import HBS2.Prelude.Plated import HBS2.Base58 import HBS2.System.Logger.Simple import HBS2.OrDie import Data.Config.Suckless import HBS2Git.Types import Control.Applicative import Control.Exception import Control.Monad.Catch (MonadThrow, throwM) import System.FilePath import System.Directory import Data.Maybe import Data.Either import Data.List (isSuffixOf) import Control.Monad.Trans.Maybe import System.Environment import System.IO (stderr) data NoWorkDirException = NoWorkDirException deriving (Show, Typeable) instance Exception NoWorkDirException appName :: FilePath appName = "hbs2-git" -- Finds .git dir inside given directory moving upwards findGitDir :: MonadIO m => FilePath -> m (Maybe FilePath) findGitDir dir = liftIO do trace "locating .git directory" let gitDir = dir ".git" exists <- doesDirectoryExist gitDir if exists then return $ Just gitDir else let parentDir = takeDirectory dir in if parentDir == dir -- we've reached the root directory then return Nothing else findGitDir parentDir configPathOld :: MonadIO m => FilePath -> m FilePath configPathOld pwd = liftIO do xdg <- liftIO $ getXdgDirectory XdgConfig appName home <- liftIO getHomeDirectory pure $ xdg makeRelative home pwd configPath :: (MonadIO m, MonadThrow m) => FilePath -> m FilePath configPath _ = do pwd <- liftIO getCurrentDirectory git <- findGitDir pwd byEnv <- liftIO $ lookupEnv "GIT_DIR" bare <- if isJust (git <|> byEnv) then do pure Nothing else runMaybeT do -- check may be it's a bare git repo gitConf <- toMPlus =<< liftIO ( try @IOException $ readFile "config" <&> parseTop <&> fromRight mempty ) let core = or [True | SymbolVal @C "core" <- universeBi gitConf] let bare = or [True | ListVal [SymbolVal @C "bare", _, SymbolVal "true"] <- universeBi gitConf ] let repo = or [True | SymbolVal @C "repositoryformatversion" <- universeBi gitConf ] if core && bare && repo then do pure pwd else MaybeT $ pure Nothing let maybePath = dropSuffix <$> (git <|> byEnv <|> bare) path <- maybe (throwM NoWorkDirException) pure maybePath pure (path ".hbs2") where dropSuffix s | isSuffixOf ".git/" s = takeDirectory s | isSuffixOf ".git" s = takeDirectory s | otherwise = s data ConfigPathInfo = ConfigPathInfo { configRepoParentDir :: FilePath, configDir :: FilePath, configFilePath :: FilePath } deriving (Eq, Show) -- returns git repository parent dir, config directory and config file path getConfigPathInfo :: (MonadIO m, MonadThrow m) => m ConfigPathInfo getConfigPathInfo = do trace "getConfigPathInfo" confP <- configPath "" let pwd = takeDirectory confP let confFile = confP "config" trace $ "confPath:" <+> pretty confP pure ConfigPathInfo { configRepoParentDir = pwd, configDir = confP, configFilePath = confFile } -- returns current directory, where found .git directory configInit :: (MonadIO m, MonadThrow m) => m (FilePath, [Syntax C]) configInit = liftIO do trace "configInit" ConfigPathInfo{..} <- getConfigPathInfo here <- doesDirectoryExist configDir unless here do debug $ "create directory" <+> pretty configDir createDirectoryIfMissing True configDir confHere <- doesFileExist configFilePath unless confHere do appendFile configFilePath "" cfg <- readFile configFilePath <&> parseTop <&> either mempty id pure (configRepoParentDir, cfg) cookieFile :: (MonadIO m, MonadThrow m) => m FilePath cookieFile = configPath "" <&> ( "cookie") getAppStateDir :: forall m . MonadIO m => m FilePath getAppStateDir = liftIO $ getXdgDirectory XdgData appName makeDbPath :: MonadIO m => RepoRef -> m FilePath makeDbPath h = do state <- getAppStateDir liftIO $ createDirectoryIfMissing True state pure $ state show (pretty (AsBase58 h))