module Hix.Component where

import Data.List.Extra (firstJust)
import qualified Data.Map.Strict as Map
import Data.Map.Strict ((!?))
import qualified Data.Text as Text
import Exon (exon)
import Path (Abs, Dir, File, Path, Rel, SomeBase (Abs, Rel), isProperPrefixOf, reldir, stripProperPrefix)

import qualified Hix.Data.ComponentConfig
import Hix.Data.ComponentConfig (
  ComponentConfig,
  PackageConfig (PackageConfig),
  PackageName (PackageName),
  PackagesConfig,
  SourceDir (SourceDir),
  Target (Target),
  TargetOrDefault (DefaultTarget, ExplicitTarget, NoDefaultTarget),
  )
import Hix.Data.Error (Error (EnvError), pathText)
import Hix.Monad (M, noteEnv, throwM)
import qualified Hix.Options as Options
import Hix.Options (
  ComponentCoords,
  ComponentSpec (ComponentSpec),
  PackageSpec (PackageSpec),
  TargetSpec (TargetForComponent, TargetForFile),
  )
import Hix.Path (rootDir)

data ResolvedPackage =
  ResolvedPackage Bool PackageConfig
  |
  NoPackage Text
  deriving stock (ResolvedPackage -> ResolvedPackage -> Bool
(ResolvedPackage -> ResolvedPackage -> Bool)
-> (ResolvedPackage -> ResolvedPackage -> Bool)
-> Eq ResolvedPackage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ResolvedPackage -> ResolvedPackage -> Bool
== :: ResolvedPackage -> ResolvedPackage -> Bool
$c/= :: ResolvedPackage -> ResolvedPackage -> Bool
/= :: ResolvedPackage -> ResolvedPackage -> Bool
Eq, Int -> ResolvedPackage -> ShowS
[ResolvedPackage] -> ShowS
ResolvedPackage -> String
(Int -> ResolvedPackage -> ShowS)
-> (ResolvedPackage -> String)
-> ([ResolvedPackage] -> ShowS)
-> Show ResolvedPackage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ResolvedPackage -> ShowS
showsPrec :: Int -> ResolvedPackage -> ShowS
$cshow :: ResolvedPackage -> String
show :: ResolvedPackage -> String
$cshowList :: [ResolvedPackage] -> ShowS
showList :: [ResolvedPackage] -> ShowS
Show, (forall x. ResolvedPackage -> Rep ResolvedPackage x)
-> (forall x. Rep ResolvedPackage x -> ResolvedPackage)
-> Generic ResolvedPackage
forall x. Rep ResolvedPackage x -> ResolvedPackage
forall x. ResolvedPackage -> Rep ResolvedPackage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ResolvedPackage -> Rep ResolvedPackage x
from :: forall x. ResolvedPackage -> Rep ResolvedPackage x
$cto :: forall x. Rep ResolvedPackage x -> ResolvedPackage
to :: forall x. Rep ResolvedPackage x -> ResolvedPackage
Generic)

tryPackageByDir ::
  PackagesConfig ->
  Path Rel Dir ->
  Maybe PackageConfig
tryPackageByDir :: PackagesConfig -> Path Rel Dir -> Maybe PackageConfig
tryPackageByDir PackagesConfig
config Path Rel Dir
dir =
  (PackageConfig -> Bool) -> [PackageConfig] -> Maybe PackageConfig
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find PackageConfig -> Bool
match (PackagesConfig -> [PackageConfig]
forall k a. Map k a -> [a]
Map.elems PackagesConfig
config)
  where
    match :: PackageConfig -> Bool
match PackageConfig
pkg = PackageConfig
pkg.src Path Rel Dir -> Path Rel Dir -> Bool
forall a. Eq a => a -> a -> Bool
== Path Rel Dir
dir

packageByDir ::
  PackagesConfig ->
  Path Rel Dir ->
  M PackageConfig
packageByDir :: PackagesConfig -> Path Rel Dir -> M PackageConfig
packageByDir PackagesConfig
config Path Rel Dir
dir =
  Text -> Maybe PackageConfig -> M PackageConfig
forall a. Text -> Maybe a -> M a
noteEnv [exon|No package at this directory: #{pathText dir}|] (PackagesConfig -> Path Rel Dir -> Maybe PackageConfig
tryPackageByDir PackagesConfig
config Path Rel Dir
dir)

packageDefault :: Maybe PackageName -> PackagesConfig -> ResolvedPackage
packageDefault :: Maybe PackageName -> PackagesConfig -> ResolvedPackage
packageDefault Maybe PackageName
mainPkg = \case
  [] -> Text -> ResolvedPackage
NoPackage Text
"Project has no packages."
  [(PackageName
_, PackageConfig
pkg)] -> Bool -> PackageConfig -> ResolvedPackage
ResolvedPackage Bool
False PackageConfig
pkg
  PackagesConfig
pkgs | Just PackageName
name <- Maybe PackageName
mainPkg ->
    case PackageName -> PackagesConfig -> Maybe PackageConfig
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup PackageName
name PackagesConfig
pkgs of
      Just PackageConfig
pkg ->
        Bool -> PackageConfig -> ResolvedPackage
ResolvedPackage Bool
False PackageConfig
pkg
      Maybe PackageConfig
Nothing ->
        Text -> ResolvedPackage
NoPackage (
          [exon|Project has multiple packages and the main package '##{name}' is not among them. |] Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
          Text
"Specify -p or -f to choose one explicitly."
        )
  PackagesConfig
_ -> Text -> ResolvedPackage
NoPackage Text
"Project has more than one package, specify -p or -f."

packageForSpec ::
  Path Abs Dir ->
  PackagesConfig ->
  PackageSpec ->
  M PackageConfig
packageForSpec :: Path Abs Dir -> PackagesConfig -> PackageSpec -> M PackageConfig
packageForSpec Path Abs Dir
root PackagesConfig
config = \case
  PackageSpec PackageName
_ (Just (Abs Path Abs Dir
dir)) -> do
    Path Rel Dir
rel <- Text -> Maybe (Path Rel Dir) -> M (Path Rel Dir)
forall a. Text -> Maybe a -> M a
noteEnv [exon|Path is not a subdirectory of the project root: #{pathText dir}|] (Path Abs Dir -> Path Abs Dir -> Maybe (Path Rel Dir)
forall (m :: * -> *) b t.
MonadThrow m =>
Path b Dir -> Path b t -> m (Path Rel t)
stripProperPrefix Path Abs Dir
root Path Abs Dir
dir)
    PackagesConfig -> Path Rel Dir -> M PackageConfig
packageByDir PackagesConfig
config Path Rel Dir
rel
  PackageSpec (PackageName Text
name) (Just (Rel Path Rel Dir
dir)) | Char -> Text -> Bool
Text.elem Char
'/' Text
name ->
    PackagesConfig -> Path Rel Dir -> M PackageConfig
packageByDir PackagesConfig
config Path Rel Dir
dir
  PackageSpec PackageName
name Maybe (SomeBase Dir)
dir ->
    Text -> Maybe PackageConfig -> M PackageConfig
forall a. Text -> Maybe a -> M a
noteEnv [exon|No package matching '##{name}'|] (PackagesConfig
config PackagesConfig -> PackageName -> Maybe PackageConfig
forall k a. Ord k => Map k a -> k -> Maybe a
!? PackageName
name Maybe PackageConfig -> Maybe PackageConfig -> Maybe PackageConfig
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (SomeBase Dir -> Maybe PackageConfig
tryDir (SomeBase Dir -> Maybe PackageConfig)
-> Maybe (SomeBase Dir) -> Maybe PackageConfig
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe (SomeBase Dir)
dir))
    where
      tryDir :: SomeBase Dir -> Maybe PackageConfig
tryDir = \case
        Abs Path Abs Dir
_ -> Maybe PackageConfig
forall a. Maybe a
Nothing
        Rel Path Rel Dir
rd -> PackagesConfig -> Path Rel Dir -> Maybe PackageConfig
tryPackageByDir PackagesConfig
config Path Rel Dir
rd

packageForSpecOrDefault ::
  Path Abs Dir ->
  Maybe PackageName ->
  PackagesConfig ->
  Maybe PackageSpec ->
  M ResolvedPackage
packageForSpecOrDefault :: Path Abs Dir
-> Maybe PackageName
-> PackagesConfig
-> Maybe PackageSpec
-> M ResolvedPackage
packageForSpecOrDefault Path Abs Dir
root Maybe PackageName
mainPkg PackagesConfig
config = \case
  Just PackageSpec
pkg -> Bool -> PackageConfig -> ResolvedPackage
ResolvedPackage Bool
True (PackageConfig -> ResolvedPackage)
-> M PackageConfig -> M ResolvedPackage
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Path Abs Dir -> PackagesConfig -> PackageSpec -> M PackageConfig
packageForSpec Path Abs Dir
root PackagesConfig
config PackageSpec
pkg
  Maybe PackageSpec
Nothing -> ResolvedPackage -> M ResolvedPackage
forall a. a -> ReaderT Env (ExceptT Error IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe PackageName -> PackagesConfig -> ResolvedPackage
packageDefault Maybe PackageName
mainPkg PackagesConfig
config)

matchComponent :: ComponentConfig -> ComponentSpec -> Bool
matchComponent :: ComponentConfig -> ComponentSpec -> Bool
matchComponent ComponentConfig
candidate (ComponentSpec ComponentName
name Maybe SourceDir
dir) =
  ComponentConfig
candidate.name ComponentName -> ComponentName -> Bool
forall a. Eq a => a -> a -> Bool
== ComponentName
name Bool -> Bool -> Bool
|| (SourceDir -> Bool) -> Maybe SourceDir -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\ SourceDir
d -> forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem @[] SourceDir
d (SourceDirs -> [SourceDir]
forall a b. Coercible a b => a -> b
coerce ComponentConfig
candidate.sourceDirs)) Maybe SourceDir
dir

componentError :: PackageName -> ComponentSpec -> Text
componentError :: PackageName -> ComponentSpec -> Text
componentError PackageName
pname ComponentSpec
spec =
  [exon|No component with name or source dir '##{name}' in the package '##{pname}'|]
  where
    name :: ComponentName
name = ComponentSpec
spec.name

undecidableComponentError :: PackageName -> Text
undecidableComponentError :: PackageName -> Text
undecidableComponentError PackageName
pname =
  [exon|Please specify a component name or source dir with -c for the package '##{pname}'|]

testComponent :: ComponentSpec
testComponent :: ComponentSpec
testComponent =
  ComponentName -> Maybe SourceDir -> ComponentSpec
ComponentSpec ComponentName
"test" (SourceDir -> Maybe SourceDir
forall a. a -> Maybe a
Just (Path Rel Dir -> SourceDir
SourceDir [reldir|test|]))

defaultComponent :: PackageConfig -> Either Text Target
defaultComponent :: PackageConfig -> Either Text Target
defaultComponent PackageConfig
package = do
  ComponentConfig
component <- Text -> Maybe ComponentConfig -> Either Text ComponentConfig
forall l r. l -> Maybe r -> Either l r
maybeToRight (PackageName -> Text
undecidableComponentError PackageConfig
package.name) (Map ComponentName ComponentConfig -> Maybe ComponentConfig
forall {k}. Ord k => Map k ComponentConfig -> Maybe ComponentConfig
selectComponent PackageConfig
package.components)
  pure Target {$sel:sourceDir:Target :: Maybe SourceDir
sourceDir = Maybe SourceDir
forall a. Maybe a
Nothing, PackageConfig
ComponentConfig
package :: PackageConfig
component :: ComponentConfig
$sel:package:Target :: PackageConfig
$sel:component:Target :: ComponentConfig
..}
  where
    selectComponent :: Map k ComponentConfig -> Maybe ComponentConfig
selectComponent [(k
_, ComponentConfig
comp)] = ComponentConfig -> Maybe ComponentConfig
forall a. a -> Maybe a
Just ComponentConfig
comp
    selectComponent (Map k ComponentConfig -> [ComponentConfig]
forall k a. Map k a -> [a]
Map.elems -> [ComponentConfig]
comps) = (ComponentConfig -> Bool)
-> [ComponentConfig] -> Maybe ComponentConfig
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (ComponentSpec -> ComponentConfig -> Bool
match ComponentSpec
testComponent) [ComponentConfig]
comps
    match :: ComponentSpec -> ComponentConfig -> Bool
match = (ComponentConfig -> ComponentSpec -> Bool)
-> ComponentSpec -> ComponentConfig -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip ComponentConfig -> ComponentSpec -> Bool
matchComponent

targetInPackage ::
  ResolvedPackage ->
  Maybe ComponentSpec ->
  M TargetOrDefault
targetInPackage :: ResolvedPackage -> Maybe ComponentSpec -> M TargetOrDefault
targetInPackage (ResolvedPackage Bool
_ PackageConfig
package) (Just ComponentSpec
comp) = do
  ComponentConfig
component <- Text -> Maybe ComponentConfig -> M ComponentConfig
forall a. Text -> Maybe a -> M a
noteEnv (PackageName -> ComponentSpec -> Text
componentError PackageConfig
package.name ComponentSpec
comp) ((ComponentConfig -> Bool)
-> [ComponentConfig] -> Maybe ComponentConfig
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ComponentConfig -> Bool
match (Map ComponentName ComponentConfig -> [ComponentConfig]
forall k a. Map k a -> [a]
Map.elems PackageConfig
package.components))
  pure (Target -> TargetOrDefault
ExplicitTarget (Target {$sel:sourceDir:Target :: Maybe SourceDir
sourceDir = Maybe SourceDir
forall a. Maybe a
Nothing, PackageConfig
ComponentConfig
$sel:package:Target :: PackageConfig
$sel:component:Target :: ComponentConfig
package :: PackageConfig
component :: ComponentConfig
..}))
  where
    match :: ComponentConfig -> Bool
match ComponentConfig
cand = ComponentConfig -> ComponentSpec -> Bool
matchComponent ComponentConfig
cand ComponentSpec
comp
targetInPackage (ResolvedPackage Bool
True PackageConfig
package) Maybe ComponentSpec
Nothing =
  (Text -> M TargetOrDefault)
-> (TargetOrDefault -> M TargetOrDefault)
-> Either Text TargetOrDefault
-> M TargetOrDefault
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Error -> M TargetOrDefault
forall a. Error -> M a
throwM (Error -> M TargetOrDefault)
-> (Text -> Error) -> Text -> M TargetOrDefault
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Error
EnvError) TargetOrDefault -> M TargetOrDefault
forall a. a -> ReaderT Env (ExceptT Error IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Target -> TargetOrDefault
ExplicitTarget (Target -> TargetOrDefault)
-> Either Text Target -> Either Text TargetOrDefault
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PackageConfig -> Either Text Target
defaultComponent PackageConfig
package)
targetInPackage (ResolvedPackage Bool
False PackageConfig
package) Maybe ComponentSpec
Nothing = do
  (Text -> M TargetOrDefault)
-> (TargetOrDefault -> M TargetOrDefault)
-> Either Text TargetOrDefault
-> M TargetOrDefault
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (TargetOrDefault -> M TargetOrDefault
forall a. a -> ReaderT Env (ExceptT Error IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TargetOrDefault -> M TargetOrDefault)
-> (Text -> TargetOrDefault) -> Text -> M TargetOrDefault
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> TargetOrDefault
NoDefaultTarget) TargetOrDefault -> M TargetOrDefault
forall a. a -> ReaderT Env (ExceptT Error IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Target -> TargetOrDefault
DefaultTarget (Target -> TargetOrDefault)
-> Either Text Target -> Either Text TargetOrDefault
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PackageConfig -> Either Text Target
defaultComponent PackageConfig
package)
targetInPackage (NoPackage Text
err) Maybe ComponentSpec
_ = TargetOrDefault -> M TargetOrDefault
forall a. a -> ReaderT Env (ExceptT Error IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> TargetOrDefault
NoDefaultTarget Text
err)

targetForComponent ::
  Path Abs Dir ->
  Maybe PackageName ->
  PackagesConfig ->
  ComponentCoords ->
  M TargetOrDefault
targetForComponent :: Path Abs Dir
-> Maybe PackageName
-> PackagesConfig
-> ComponentCoords
-> M TargetOrDefault
targetForComponent Path Abs Dir
root Maybe PackageName
mainPkg PackagesConfig
config ComponentCoords
spec = do
  ResolvedPackage
package <- Path Abs Dir
-> Maybe PackageName
-> PackagesConfig
-> Maybe PackageSpec
-> M ResolvedPackage
packageForSpecOrDefault Path Abs Dir
root Maybe PackageName
mainPkg PackagesConfig
config ComponentCoords
spec.package
  ResolvedPackage -> Maybe ComponentSpec -> M TargetOrDefault
targetInPackage ResolvedPackage
package ComponentCoords
spec.component

targetForFile ::
  Path Abs Dir ->
  PackagesConfig ->
  Path Abs File ->
  M Target
targetForFile :: Path Abs Dir -> PackagesConfig -> Path Abs File -> M Target
targetForFile Path Abs Dir
root PackagesConfig
config Path Abs File
file = do
  Path Rel File
fileRel <- Path Abs Dir
-> Path Abs File -> ReaderT Env (ExceptT Error IO) (Path Rel File)
forall (m :: * -> *) b t.
MonadThrow m =>
Path b Dir -> Path b t -> m (Path Rel t)
stripProperPrefix Path Abs Dir
root Path Abs File
file
  (PackageConfig
package, Path Rel File
subpath) <- Maybe (PackageConfig, Path Rel File)
-> M (PackageConfig, Path Rel File)
forall {a}. Maybe a -> M a
pkgError ((PackageConfig -> Maybe (PackageConfig, Path Rel File))
-> [PackageConfig] -> Maybe (PackageConfig, Path Rel File)
forall a b. (a -> Maybe b) -> [a] -> Maybe b
firstJust (Path Rel File
-> PackageConfig -> Maybe (PackageConfig, Path Rel File)
forall {f :: * -> *} {t}.
MonadThrow f =>
Path Rel t -> PackageConfig -> f (PackageConfig, Path Rel t)
matchPackage Path Rel File
fileRel) (PackagesConfig -> [PackageConfig]
forall k a. Map k a -> [a]
Map.elems PackagesConfig
config))
  (ComponentConfig
component, Maybe SourceDir
sourceDir) <- Maybe (ComponentConfig, Maybe SourceDir)
-> M (ComponentConfig, Maybe SourceDir)
forall {a}. Maybe a -> M a
compError ((ComponentConfig -> Maybe (ComponentConfig, Maybe SourceDir))
-> [ComponentConfig] -> Maybe (ComponentConfig, Maybe SourceDir)
forall a b. (a -> Maybe b) -> [a] -> Maybe b
firstJust (Path Rel File
-> ComponentConfig -> Maybe (ComponentConfig, Maybe SourceDir)
forall {a} {a} {t}.
(Coercible a [SourceDir], HasField "sourceDirs" a a) =>
Path Rel t -> a -> Maybe (a, Maybe SourceDir)
matchSourceDir Path Rel File
subpath) (Map ComponentName ComponentConfig -> [ComponentConfig]
forall k a. Map k a -> [a]
Map.elems PackageConfig
package.components))
  Target -> M Target
forall a. a -> ReaderT Env (ExceptT Error IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Target {Maybe SourceDir
PackageConfig
ComponentConfig
$sel:sourceDir:Target :: Maybe SourceDir
$sel:package:Target :: PackageConfig
$sel:component:Target :: ComponentConfig
package :: PackageConfig
component :: ComponentConfig
sourceDir :: Maybe SourceDir
..}
  where
    matchPackage :: Path Rel t -> PackageConfig -> f (PackageConfig, Path Rel t)
matchPackage Path Rel t
fileRel package :: PackageConfig
package@PackageConfig {Path Rel Dir
src :: Path Rel Dir
$sel:src:PackageConfig :: PackageConfig -> Path Rel Dir
src} = do
      Path Rel t
subpath <- Path Rel Dir -> Path Rel t -> f (Path Rel t)
forall (m :: * -> *) b t.
MonadThrow m =>
Path b Dir -> Path b t -> m (Path Rel t)
stripProperPrefix Path Rel Dir
src Path Rel t
fileRel
      pure (PackageConfig
package, Path Rel t
subpath)
    matchSourceDir :: Path Rel t -> a -> Maybe (a, Maybe SourceDir)
matchSourceDir Path Rel t
subpath a
component = do
      let match :: SourceDir -> Maybe SourceDir
match d :: SourceDir
d@(SourceDir Path Rel Dir
dir) = if Path Rel Dir -> Path Rel t -> Bool
forall b t. Path b Dir -> Path b t -> Bool
isProperPrefixOf Path Rel Dir
dir Path Rel t
subpath then SourceDir -> Maybe SourceDir
forall a. a -> Maybe a
Just SourceDir
d else Maybe SourceDir
forall a. Maybe a
Nothing
      SourceDir
dir <- (SourceDir -> Maybe SourceDir) -> [SourceDir] -> Maybe SourceDir
forall a b. (a -> Maybe b) -> [a] -> Maybe b
firstJust SourceDir -> Maybe SourceDir
match (a -> [SourceDir]
forall a b. Coercible a b => a -> b
coerce a
component.sourceDirs)
      pure (a
component, SourceDir -> Maybe SourceDir
forall a. a -> Maybe a
Just SourceDir
dir)
    pkgError :: Maybe a -> M a
pkgError = Text -> Maybe a -> M a
forall a. Text -> Maybe a -> M a
noteEnv Text
"No package contains this file"
    compError :: Maybe a -> M a
compError = Text -> Maybe a -> M a
forall a. Text -> Maybe a -> M a
noteEnv Text
"No component source dir contains this file"

targetComponentIn ::
  Path Abs Dir ->
  Maybe PackageName ->
  PackagesConfig ->
  TargetSpec ->
  M TargetOrDefault
targetComponentIn :: Path Abs Dir
-> Maybe PackageName
-> PackagesConfig
-> TargetSpec
-> M TargetOrDefault
targetComponentIn Path Abs Dir
root Maybe PackageName
mainPkg PackagesConfig
config = \case
  TargetForComponent ComponentCoords
spec ->
    Path Abs Dir
-> Maybe PackageName
-> PackagesConfig
-> ComponentCoords
-> M TargetOrDefault
targetForComponent Path Abs Dir
root Maybe PackageName
mainPkg PackagesConfig
config ComponentCoords
spec
  TargetForFile Path Abs File
spec ->
    Target -> TargetOrDefault
ExplicitTarget (Target -> TargetOrDefault) -> M Target -> M TargetOrDefault
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Path Abs Dir -> PackagesConfig -> Path Abs File -> M Target
targetForFile Path Abs Dir
root PackagesConfig
config Path Abs File
spec

targetComponent ::
  Maybe (Path Abs Dir) ->
  Maybe PackageName ->
  PackagesConfig ->
  TargetSpec ->
  M TargetOrDefault
targetComponent :: Maybe (Path Abs Dir)
-> Maybe PackageName
-> PackagesConfig
-> TargetSpec
-> M TargetOrDefault
targetComponent Maybe (Path Abs Dir)
cliRoot Maybe PackageName
mainPkg PackagesConfig
config TargetSpec
spec = do
  Path Abs Dir
root <- Maybe (Path Abs Dir) -> M (Path Abs Dir)
rootDir Maybe (Path Abs Dir)
cliRoot
  Path Abs Dir
-> Maybe PackageName
-> PackagesConfig
-> TargetSpec
-> M TargetOrDefault
targetComponentIn Path Abs Dir
root Maybe PackageName
mainPkg PackagesConfig
config TargetSpec
spec

targetComponentOrError ::
  Maybe (Path Abs Dir) ->
  Maybe PackageName ->
  PackagesConfig ->
  TargetSpec ->
  M Target
targetComponentOrError :: Maybe (Path Abs Dir)
-> Maybe PackageName -> PackagesConfig -> TargetSpec -> M Target
targetComponentOrError Maybe (Path Abs Dir)
cliRoot Maybe PackageName
mainPkg PackagesConfig
config TargetSpec
spec =
  Maybe (Path Abs Dir)
-> Maybe PackageName
-> PackagesConfig
-> TargetSpec
-> M TargetOrDefault
targetComponent Maybe (Path Abs Dir)
cliRoot Maybe PackageName
mainPkg PackagesConfig
config TargetSpec
spec M TargetOrDefault -> (TargetOrDefault -> M Target) -> M Target
forall a b.
ReaderT Env (ExceptT Error IO) a
-> (a -> ReaderT Env (ExceptT Error IO) b)
-> ReaderT Env (ExceptT Error IO) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    ExplicitTarget Target
t -> Target -> M Target
forall a. a -> ReaderT Env (ExceptT Error IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Target
t
    DefaultTarget Target
t -> Target -> M Target
forall a. a -> ReaderT Env (ExceptT Error IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Target
t
    NoDefaultTarget Text
err -> Error -> M Target
forall a. Error -> M a
throwM (Text -> Error
EnvError Text
err)