guardian-0.5.0.0: src/Development/Guardian/Graph/Adapter/Stack/Enabled.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
module Development.Guardian.Graph.Adapter.Stack.Enabled (
buildPackageGraphM,
buildPackageGraph,
Stack,
CustomPackageOptions (..),
) where
import qualified Algebra.Graph as G
import Control.Applicative ((<**>))
import Data.Maybe (fromMaybe)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.String (fromString)
import qualified Data.Text as T
import Development.Guardian.Graph.Adapter.Stack.Types
import Development.Guardian.Graph.Adapter.Types
import Development.Guardian.Types (Overlayed (Overlayed, getOverlayed), PackageGraph)
import qualified Development.Guardian.Types as Guard
import Distribution.Simple (unPackageName)
import Options.Applicative (helper)
import qualified Options.Applicative as Opt
import Path (fromAbsDir)
import Path.IO (withCurrentDir)
import Stack.Build.Source (loadLocalPackage)
import Stack.Options.GlobalParser (globalOptsFromMonoid, globalOptsParser)
import Stack.Options.Utils (GlobalOptsContext (OuterGlobalOpts))
import Stack.Prelude (RIO, toList, view)
import qualified Stack.Prelude as Stack
import Stack.Runners (ShouldReexec (NoReexec), withConfig, withDefaultEnvConfig, withRunnerGlobal)
import Stack.Types.Build (LocalPackage)
import Stack.Types.BuildConfig (HasBuildConfig)
import Stack.Types.EnvConfig (HasSourceMap (sourceMapL))
import Stack.Types.Package (LocalPackage (..), Package (..))
import qualified Stack.Types.Package as Stack
import Stack.Types.SourceMap (SourceMap (..))
localPackageToPackage :: LocalPackage -> Package
localPackageToPackage lp =
fromMaybe (lpPackage lp) (lpTestBench lp)
{- | Resolve the direct (depth 0) external dependencies of the given local packages (assumed to come from project packages)
Stolen from @stack@ and further simplified.
-}
projectPackageDependencies ::
[LocalPackage] -> [(Stack.PackageName, Set Stack.PackageName)]
projectPackageDependencies locals =
map
( \lp ->
let pkg = localPackageToPackage lp
in (Stack.packageName pkg, deps pkg)
)
locals
where
deps pkg =
Set.intersection localNames (packageAllDeps pkg)
localNames = Set.fromList $ map (Stack.packageName . lpPackage) locals
buildPackageGraph :: PackageGraphOptions Stack -> IO PackageGraph
buildPackageGraph PackageGraphOptions {customOptions = StackOptions {..}, ..} = do
withCurrentDir targetPath $ do
let pInfo =
Opt.info
(globalOptsParser (fromAbsDir targetPath) OuterGlobalOpts <**> helper)
mempty
cliOpts =
"--skip-ghc-check"
: concat
[ ["--test", "--no-run-tests"]
| tests components
]
<> concat
[ ["--bench", "--no-run-benchmarks"]
| benchmarks components
]
++ map T.unpack stackOptions
Just gopt <-
mapM (globalOptsFromMonoid False) $
Opt.getParseResult $
Opt.execParserPure (Opt.prefs mempty) pInfo cliOpts
withRunnerGlobal gopt $
withConfig NoReexec $
withDefaultEnvConfig buildPackageGraphM
buildPackageGraphM ::
(HasSourceMap env, HasBuildConfig env) =>
RIO env PackageGraph
buildPackageGraphM = do
sourceMap <- view sourceMapL
locals <- mapM loadLocalPackage $ toList $ smProject sourceMap
let gr = projectPackageDependencies locals
pure $
getOverlayed $
foldMap
( \(fromStackPackageName -> pkg, deps) ->
foldMap (Overlayed . G.edge pkg . fromStackPackageName) deps
)
gr
fromStackPackageName :: Stack.PackageName -> Guard.PackageName
fromStackPackageName = fromString . unPackageName