{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeFamilies  #-}
module Distribution.Client.Types.ConfiguredPackage (
    ConfiguredPackage (..),
) where

import Distribution.Client.Compat.Prelude
import Prelude ()

import Distribution.Compat.Graph (IsNode (..))
import Distribution.Package      (newSimpleUnitId, HasMungedPackageId (..), HasUnitId (..), Package (..), PackageInstalled (..), UnitId)
import Distribution.Types.Flag   (FlagAssignment)
import Distribution.Types.ComponentName
import Distribution.Types.LibraryName (LibraryName (..))
import Distribution.Types.MungedPackageId (computeCompatPackageId)
import Distribution.Simple.Utils (ordNub)

import Distribution.Client.Types.ConfiguredId
import Distribution.Solver.Types.OptionalStanza   (OptionalStanzaSet)
import Distribution.Solver.Types.PackageFixedDeps
import Distribution.Solver.Types.SourcePackage    (SourcePackage)

import qualified Distribution.Solver.Types.ComponentDeps as CD

-- | A 'ConfiguredPackage' is a not-yet-installed package along with the
-- total configuration information. The configuration information is total in
-- the sense that it provides all the configuration information and so the
-- final configure process will be independent of the environment.
--
-- 'ConfiguredPackage' is assumed to not support Backpack.  Only the
-- @v2-build@ codepath supports Backpack.
--
data ConfiguredPackage loc = ConfiguredPackage
    { forall loc. ConfiguredPackage loc -> InstalledPackageId
confPkgId      :: InstalledPackageId
    , forall loc. ConfiguredPackage loc -> SourcePackage loc
confPkgSource  :: SourcePackage loc  -- ^ package info, including repo
    , forall loc. ConfiguredPackage loc -> FlagAssignment
confPkgFlags   :: FlagAssignment     -- ^ complete flag assignment for the package
    , forall loc. ConfiguredPackage loc -> OptionalStanzaSet
confPkgStanzas :: OptionalStanzaSet  -- ^ list of enabled optional stanzas for the package
    , forall loc. ConfiguredPackage loc -> ComponentDeps [ConfiguredId]
confPkgDeps    :: CD.ComponentDeps [ConfiguredId]
      -- ^ set of exact dependencies (installed or source).
      --
      -- These must be consistent with the 'buildDepends'
      -- in the 'PackageDescription' that you'd get by
      -- applying the flag assignment and optional stanzas.
    }
  deriving (ConfiguredPackage loc -> ConfiguredPackage loc -> Bool
forall loc.
Eq loc =>
ConfiguredPackage loc -> ConfiguredPackage loc -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ConfiguredPackage loc -> ConfiguredPackage loc -> Bool
$c/= :: forall loc.
Eq loc =>
ConfiguredPackage loc -> ConfiguredPackage loc -> Bool
== :: ConfiguredPackage loc -> ConfiguredPackage loc -> Bool
$c== :: forall loc.
Eq loc =>
ConfiguredPackage loc -> ConfiguredPackage loc -> Bool
Eq, Int -> ConfiguredPackage loc -> ShowS
forall loc. Show loc => Int -> ConfiguredPackage loc -> ShowS
forall loc. Show loc => [ConfiguredPackage loc] -> ShowS
forall loc. Show loc => ConfiguredPackage loc -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ConfiguredPackage loc] -> ShowS
$cshowList :: forall loc. Show loc => [ConfiguredPackage loc] -> ShowS
show :: ConfiguredPackage loc -> String
$cshow :: forall loc. Show loc => ConfiguredPackage loc -> String
showsPrec :: Int -> ConfiguredPackage loc -> ShowS
$cshowsPrec :: forall loc. Show loc => Int -> ConfiguredPackage loc -> ShowS
Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall loc x.
Rep (ConfiguredPackage loc) x -> ConfiguredPackage loc
forall loc x.
ConfiguredPackage loc -> Rep (ConfiguredPackage loc) x
$cto :: forall loc x.
Rep (ConfiguredPackage loc) x -> ConfiguredPackage loc
$cfrom :: forall loc x.
ConfiguredPackage loc -> Rep (ConfiguredPackage loc) x
Generic)

-- | 'HasConfiguredId' indicates data types which have a 'ConfiguredId'.
-- This type class is mostly used to conveniently finesse between
-- 'ElaboratedPackage' and 'ElaboratedComponent'.
--
instance HasConfiguredId (ConfiguredPackage loc) where
    configuredId :: ConfiguredPackage loc -> ConfiguredId
configuredId ConfiguredPackage loc
pkg = PackageId
-> Maybe ComponentName -> InstalledPackageId -> ConfiguredId
ConfiguredId (forall pkg. Package pkg => pkg -> PackageId
packageId ConfiguredPackage loc
pkg) (forall a. a -> Maybe a
Just (LibraryName -> ComponentName
CLibName LibraryName
LMainLibName)) (forall loc. ConfiguredPackage loc -> InstalledPackageId
confPkgId ConfiguredPackage loc
pkg)

-- 'ConfiguredPackage' is the legacy codepath, we are guaranteed
-- to never have a nontrivial 'UnitId'
instance PackageFixedDeps (ConfiguredPackage loc) where
    depends :: ConfiguredPackage loc -> ComponentDeps [UnitId]
depends = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> [a] -> [b]
map (InstalledPackageId -> UnitId
newSimpleUnitId forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConfiguredId -> InstalledPackageId
confInstId)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall loc. ConfiguredPackage loc -> ComponentDeps [ConfiguredId]
confPkgDeps

instance IsNode (ConfiguredPackage loc) where
    type Key (ConfiguredPackage loc) = UnitId
    nodeKey :: ConfiguredPackage loc -> Key (ConfiguredPackage loc)
nodeKey       = InstalledPackageId -> UnitId
newSimpleUnitId forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall loc. ConfiguredPackage loc -> InstalledPackageId
confPkgId
    -- TODO: if we update ConfiguredPackage to support order-only
    -- dependencies, need to include those here.
    -- NB: have to deduplicate, otherwise the planner gets confused
    nodeNeighbors :: ConfiguredPackage loc -> [Key (ConfiguredPackage loc)]
nodeNeighbors = forall a. Ord a => [a] -> [a]
ordNub forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => ComponentDeps a -> a
CD.flatDeps forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall pkg. PackageFixedDeps pkg => pkg -> ComponentDeps [UnitId]
depends

instance (Binary loc) => Binary (ConfiguredPackage loc)




instance Package (ConfiguredPackage loc) where
  packageId :: ConfiguredPackage loc -> PackageId
packageId ConfiguredPackage loc
cpkg = forall pkg. Package pkg => pkg -> PackageId
packageId (forall loc. ConfiguredPackage loc -> SourcePackage loc
confPkgSource ConfiguredPackage loc
cpkg)

instance HasMungedPackageId (ConfiguredPackage loc) where
  mungedId :: ConfiguredPackage loc -> MungedPackageId
mungedId ConfiguredPackage loc
cpkg = PackageId -> LibraryName -> MungedPackageId
computeCompatPackageId (forall pkg. Package pkg => pkg -> PackageId
packageId ConfiguredPackage loc
cpkg) LibraryName
LMainLibName

-- Never has nontrivial UnitId
instance HasUnitId (ConfiguredPackage loc) where
  installedUnitId :: ConfiguredPackage loc -> UnitId
installedUnitId = InstalledPackageId -> UnitId
newSimpleUnitId forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall loc. ConfiguredPackage loc -> InstalledPackageId
confPkgId

instance PackageInstalled (ConfiguredPackage loc) where
  installedDepends :: ConfiguredPackage loc -> [UnitId]
installedDepends = forall a. Monoid a => ComponentDeps a -> a
CD.flatDeps forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall pkg. PackageFixedDeps pkg => pkg -> ComponentDeps [UnitId]
depends