module Hix.Path where

import Control.Monad.Trans.Reader (ask)
import Path (Abs, Dir, Path, parent, toFilePath)
import System.FilePattern.Directory (getDirectoryFiles)
import System.IO.Error (tryIOError)

import qualified Hix.Monad
import Hix.Monad (Env (Env), M)

findFlake :: Path Abs Dir -> IO (Maybe (Path Abs Dir))
findFlake :: Path Abs Dir -> IO (Maybe (Path Abs Dir))
findFlake Path Abs Dir
cur =
  forall a. IO a -> IO (Either IOError a)
tryIOError (FilePattern -> [FilePattern] -> IO [FilePattern]
getDirectoryFiles (forall b t. Path b t -> FilePattern
toFilePath Path Abs Dir
cur) [FilePattern
"flake.nix"]) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> b -> a
const (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing)) \case
    [Item [FilePattern]
_] -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. a -> Maybe a
Just Path Abs Dir
cur)
    [FilePattern]
_ | forall b t. Path b t -> Path b Dir
parent Path Abs Dir
cur forall a. Eq a => a -> a -> Bool
== Path Abs Dir
cur -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing
    [FilePattern]
_ | Bool
otherwise -> Path Abs Dir -> IO (Maybe (Path Abs Dir))
findFlake (forall b t. Path b t -> Path b Dir
parent Path Abs Dir
cur)

inferRoot :: M (Path Abs Dir)
inferRoot :: M (Path Abs Dir)
inferRoot = do
  Env {Path Abs Dir
$sel:cwd:Env :: Env -> Path Abs Dir
cwd :: Path Abs Dir
cwd} <- forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
  forall a. a -> Maybe a -> a
fromMaybe Path Abs Dir
cwd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Path Abs Dir -> IO (Maybe (Path Abs Dir))
findFlake Path Abs Dir
cwd)

rootDir :: Maybe (Path Abs Dir) -> M (Path Abs Dir)
rootDir :: Maybe (Path Abs Dir) -> M (Path Abs Dir)
rootDir =
  forall b a. b -> (a -> b) -> Maybe a -> b
maybe M (Path Abs Dir)
inferRoot forall (f :: * -> *) a. Applicative f => a -> f a
pure