proteome-0.3.0.0: lib/Proteome/Project/Resolve.hs
{-# LANGUAGE NamedFieldPuns #-}
module Proteome.Project.Resolve(
resolveProject,
) where
import Data.List (find)
import Data.List.Utils (uniq)
import Data.Maybe (fromMaybe)
import Data.Map.Strict ((!?), Map)
import System.FilePath (takeDirectory)
import Ribosome.Data.Maybe (orElse)
import Proteome.Config (ProjectConfig(ProjectConfig))
import Proteome.Data.Project (
Project(Project),
ProjectName(..),
ProjectRoot(..),
ProjectType(..),
ProjectLang(..),
ProjectMetadata(DirProject, VirtualProject),
)
import Proteome.Data.ProjectSpec (ProjectSpec(ProjectSpec))
import qualified Proteome.Data.ProjectSpec as PS (ProjectSpec(..))
projectFromSegments :: ProjectType -> ProjectName -> ProjectRoot -> Project
projectFromSegments tpe name root =
Project (DirProject name root (Just tpe)) [] (Just (ProjectLang (projectType tpe))) []
projectFromSpec :: ProjectSpec -> Project
projectFromSpec (ProjectSpec name root tpe types lang langs) =
Project (DirProject name root tpe) types lang langs
hasProjectRoot :: ProjectRoot -> ProjectSpec -> Bool
hasProjectRoot root spec = root == PS.root spec
hasProjectTypeName :: ProjectType -> ProjectName -> ProjectSpec -> Bool
hasProjectTypeName tpe' name' (ProjectSpec name _ (Just tpe) _ _ _) =
name' == name && tpe' == tpe
hasProjectTypeName _ _ _ = False
byProjectTypeName :: [ProjectSpec] -> ProjectName -> ProjectType -> Maybe ProjectSpec
byProjectTypeName specs name tpe = find (hasProjectTypeName tpe name) specs
byProjectBases :: [FilePath] -> ProjectRoot -> Bool
byProjectBases baseDirs (ProjectRoot root) = (takeDirectory . takeDirectory) root `elem` baseDirs
virtualProject :: ProjectName -> Project
virtualProject name = Project (VirtualProject name) [] Nothing []
resolveByType :: [FilePath] -> [ProjectSpec] -> ProjectRoot -> ProjectName -> ProjectType -> Maybe Project
resolveByType baseDirs explicit root name tpe =
orElse (if byPath then Just (projectFromSegments tpe name root) else Nothing) (fmap projectFromSpec byTypeName)
where
byTypeName = byProjectTypeName explicit name tpe
byPath = byProjectBases baseDirs root
resolveByRoot :: [ProjectSpec] -> ProjectRoot -> Maybe Project
resolveByRoot explicit root =
fmap projectFromSpec byRoot
where
byRoot = find (hasProjectRoot root) explicit
augment :: Eq a => Map ProjectType [a] -> ProjectType -> [a] -> [a]
augment m tpe as =
case m !? tpe of
Just extra -> uniq $ as ++ extra
Nothing -> as
augmentTypes :: ProjectConfig -> ProjectType -> [ProjectType] -> [ProjectType]
augmentTypes (ProjectConfig _ typeMap _) =
augment typeMap
augmentLangs :: ProjectConfig -> ProjectType -> [ProjectLang] -> [ProjectLang]
augmentLangs (ProjectConfig _ _ langMap) =
augment langMap
augmentFromConfig :: ProjectConfig -> Project -> Project
augmentFromConfig config (Project meta@(DirProject _ _ (Just tpe)) types lang langs) =
Project meta (augmentTypes config tpe types) lang (augmentLangs config tpe langs)
augmentFromConfig _ project = project
resolveProject ::
[FilePath] ->
[ProjectSpec] ->
ProjectConfig ->
ProjectRoot ->
ProjectName ->
Maybe ProjectType ->
Project
resolveProject baseDirs explicit config root name tpe =
augmentFromConfig config project
where
project = fromMaybe byTypeOrVirtual byRoot
byTypeOrVirtual = fromMaybe (virtualProject name) byType
byType = tpe >>= resolveByType baseDirs explicit root name
byRoot = resolveByRoot explicit root