{-# LANGUAGE NoImplicitPrelude     #-}
{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NoFieldSelectors      #-}
{-# LANGUAGE OverloadedRecordDot   #-}
{-# LANGUAGE OverloadedStrings     #-}

module Stack.Types.Package
  ( BioInput (..)
  , BuildInfoOpts (..)
  , ExeName (..)
  , FileCacheInfo (..)
  , InstallLocation (..)
  , Installed (..)
  , InstalledLibraryInfo (..)
  , InstalledPackageLocation (..)
  , LocalPackage (..)
  , MemoizedWith (..)
  , Package (..)
  , PackageConfig (..)
  , PackageDatabase (..)
  , PackageDbVariety (..)
  , PackageException (..)
  , PackageSource (..)
  , dotCabalCFilePath
  , dotCabalGetPath
  , dotCabalMain
  , dotCabalMainPath
  , dotCabalModule
  , dotCabalModulePath
  , installedMapGhcPkgId
  , lpFiles
  , lpFilesForComponents
  , memoizeRefWith
  , packageDefinedFlags
  , packageIdentifier
  , psVersion
  , runMemoizedWith
  , simpleInstalledLib
  , toCabalMungedPackageName
  , toPackageDbVariety
  ) where

import           Data.Aeson
                   ( ToJSON (..), FromJSON (..), (.=), (.:), object, withObject
                   )
import qualified Data.Map as M
import qualified Data.Set as Set
import           Distribution.CabalSpecVersion
import           Distribution.Parsec ( PError (..), PWarning (..), showPos )
import qualified Distribution.SPDX.License as SPDX
import           Distribution.License ( License )
import           Distribution.ModuleName ( ModuleName )
import           Distribution.PackageDescription ( BuildType )
import           Distribution.System ( Platform (..) )
import           Distribution.Types.MungedPackageName
                   ( encodeCompatPackageName )
import qualified RIO.Text as T
import           Stack.Prelude
import           Stack.Types.CompCollection ( CompCollection )
import           Stack.Types.Compiler ( ActualCompiler )
import           Stack.Types.Component
                   ( StackBenchmark, StackBuildInfo, StackExecutable
                   , StackForeignLibrary, StackLibrary, StackTestSuite
                   , StackUnqualCompName
                   )
import           Stack.Types.ComponentUtils (toCabalName)
import           Stack.Types.Dependency ( DepValue )
import           Stack.Types.EnvConfig ( EnvConfig, HasEnvConfig (..) )
import           Stack.Types.GhcPkgId ( GhcPkgId )
import           Stack.Types.Installed
                   ( InstallLocation (..), InstallMap, Installed (..)
                   , InstalledLibraryInfo (..), InstalledMap
                   , InstalledPackageLocation (..), PackageDatabase (..)
                   , PackageDbVariety(..), simpleInstalledLib
                   , toPackageDbVariety
                   )
import           Stack.Types.NamedComponent ( NamedComponent )
import           Stack.Types.PackageFile
                   ( DotCabalDescriptor (..), DotCabalPath (..)
                   , StackPackageFile
                   )
import           Stack.Types.SourceMap ( CommonPackage, FromSnapshot )

-- | Type representing exceptions thrown by functions exported by the

-- "Stack.Package" module.

data PackageException
  = PackageInvalidCabalFile
      !(Either PackageIdentifierRevision (Path Abs File))
      !(Maybe Version)
      ![PError]
      ![PWarning]
  | MismatchedCabalIdentifier !PackageIdentifierRevision !PackageIdentifier
  | CabalFileNameParseFail FilePath
  | CabalFileNameInvalidPackageName FilePath
  | ComponentNotParsedBug String
  deriving (Int -> PackageException -> ShowS
[PackageException] -> ShowS
PackageException -> String
(Int -> PackageException -> ShowS)
-> (PackageException -> String)
-> ([PackageException] -> ShowS)
-> Show PackageException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PackageException -> ShowS
showsPrec :: Int -> PackageException -> ShowS
$cshow :: PackageException -> String
show :: PackageException -> String
$cshowList :: [PackageException] -> ShowS
showList :: [PackageException] -> ShowS
Show, Typeable)

instance Exception PackageException where
  displayException :: PackageException -> String
displayException (PackageInvalidCabalFile Either PackageIdentifierRevision (Path Abs File)
loc Maybe Version
_mversion [PError]
errs [PWarning]
warnings) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ String
"Error: [S-8072]\n"
    , String
"Unable to parse Cabal file "
    , case Either PackageIdentifierRevision (Path Abs File)
loc of
        Left PackageIdentifierRevision
pir -> String
"for " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack (Utf8Builder -> Text
utf8BuilderToText (PackageIdentifierRevision -> Utf8Builder
forall a. Display a => a -> Utf8Builder
display PackageIdentifierRevision
pir))
        Right Path Abs File
fp -> Path Abs File -> String
forall b t. Path b t -> String
toFilePath Path Abs File
fp
    {-
     Not actually needed, the errors will indicate if a newer version exists.
     Also, it seems that this is set to Just the version even if we support it.
    , case mversion of
        Nothing -> ""
        Just version -> "\nRequires newer Cabal file parser version: " ++
                        versionString version
    -}
    , String
"\n\n"
    , [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (PError -> String) -> [PError] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map
        (\(PError Position
pos String
msg) -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
            [ String
"- "
            , Position -> String
showPos Position
pos
            , String
": "
            , String
msg
            ])
        [PError]
errs
    , [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (PWarning -> String) -> [PWarning] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map
        (\(PWarning PWarnType
_ Position
pos String
msg) -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
            [ String
"- "
            , Position -> String
showPos Position
pos
            , String
": "
            , String
msg
            ])
        [PWarning]
warnings
    ]
  displayException (MismatchedCabalIdentifier PackageIdentifierRevision
pir PackageIdentifier
ident) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ String
"Error: [S-5394]\n"
    , String
"Mismatched package identifier."
    , String
"\nFound:    "
    , PackageIdentifier -> String
packageIdentifierString PackageIdentifier
ident
    , String
"\nExpected: "
    , Text -> String
T.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ Utf8Builder -> Text
utf8BuilderToText (Utf8Builder -> Text) -> Utf8Builder -> Text
forall a b. (a -> b) -> a -> b
$ PackageIdentifierRevision -> Utf8Builder
forall a. Display a => a -> Utf8Builder
display PackageIdentifierRevision
pir
    ]
  displayException (CabalFileNameParseFail String
fp) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ String
"Error: [S-2203]\n"
    , String
"Invalid file path for Cabal file, must have a .cabal extension: "
    , String
fp
    ]
  displayException (CabalFileNameInvalidPackageName String
fp) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ String
"Error: [S-8854]\n"
    , String
"Cabal file names must use valid package names followed by a .cabal \
      \extension, the following is invalid: "
    , String
fp
    ]
  displayException (ComponentNotParsedBug String
name) = String -> ShowS
bugReport String
"[S-4623]"
    (  String
"Component names should always parse as directory names. The component \
       \name without a directory is '"
    String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
name
    String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"'."
    )

-- | Name of an executable.

newtype ExeName
  = ExeName { ExeName -> Text
exeName :: Text }
  deriving (Typeable ExeName
Typeable ExeName =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> ExeName -> c ExeName)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c ExeName)
-> (ExeName -> Constr)
-> (ExeName -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c ExeName))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ExeName))
-> ((forall b. Data b => b -> b) -> ExeName -> ExeName)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> ExeName -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> ExeName -> r)
-> (forall u. (forall d. Data d => d -> u) -> ExeName -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> ExeName -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> ExeName -> m ExeName)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ExeName -> m ExeName)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ExeName -> m ExeName)
-> Data ExeName
ExeName -> Constr
ExeName -> DataType
(forall b. Data b => b -> b) -> ExeName -> ExeName
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> ExeName -> u
forall u. (forall d. Data d => d -> u) -> ExeName -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ExeName -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ExeName -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ExeName -> m ExeName
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ExeName -> m ExeName
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ExeName
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ExeName -> c ExeName
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ExeName)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ExeName)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ExeName -> c ExeName
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ExeName -> c ExeName
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ExeName
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ExeName
$ctoConstr :: ExeName -> Constr
toConstr :: ExeName -> Constr
$cdataTypeOf :: ExeName -> DataType
dataTypeOf :: ExeName -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ExeName)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ExeName)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ExeName)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ExeName)
$cgmapT :: (forall b. Data b => b -> b) -> ExeName -> ExeName
gmapT :: (forall b. Data b => b -> b) -> ExeName -> ExeName
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ExeName -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ExeName -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ExeName -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ExeName -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> ExeName -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> ExeName -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ExeName -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ExeName -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ExeName -> m ExeName
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ExeName -> m ExeName
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ExeName -> m ExeName
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ExeName -> m ExeName
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ExeName -> m ExeName
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ExeName -> m ExeName
Data, ExeName -> ExeName -> Bool
(ExeName -> ExeName -> Bool)
-> (ExeName -> ExeName -> Bool) -> Eq ExeName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExeName -> ExeName -> Bool
== :: ExeName -> ExeName -> Bool
$c/= :: ExeName -> ExeName -> Bool
/= :: ExeName -> ExeName -> Bool
Eq, (forall x. ExeName -> Rep ExeName x)
-> (forall x. Rep ExeName x -> ExeName) -> Generic ExeName
forall x. Rep ExeName x -> ExeName
forall x. ExeName -> Rep ExeName x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ExeName -> Rep ExeName x
from :: forall x. ExeName -> Rep ExeName x
$cto :: forall x. Rep ExeName x -> ExeName
to :: forall x. Rep ExeName x -> ExeName
Generic, Eq ExeName
Eq ExeName =>
(Int -> ExeName -> Int) -> (ExeName -> Int) -> Hashable ExeName
Int -> ExeName -> Int
ExeName -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> ExeName -> Int
hashWithSalt :: Int -> ExeName -> Int
$chash :: ExeName -> Int
hash :: ExeName -> Int
Hashable, String -> ExeName
(String -> ExeName) -> IsString ExeName
forall a. (String -> a) -> IsString a
$cfromString :: String -> ExeName
fromString :: String -> ExeName
IsString, ExeName -> ()
(ExeName -> ()) -> NFData ExeName
forall a. (a -> ()) -> NFData a
$crnf :: ExeName -> ()
rnf :: ExeName -> ()
NFData, Eq ExeName
Eq ExeName =>
(ExeName -> ExeName -> Ordering)
-> (ExeName -> ExeName -> Bool)
-> (ExeName -> ExeName -> Bool)
-> (ExeName -> ExeName -> Bool)
-> (ExeName -> ExeName -> Bool)
-> (ExeName -> ExeName -> ExeName)
-> (ExeName -> ExeName -> ExeName)
-> Ord ExeName
ExeName -> ExeName -> Bool
ExeName -> ExeName -> Ordering
ExeName -> ExeName -> ExeName
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ExeName -> ExeName -> Ordering
compare :: ExeName -> ExeName -> Ordering
$c< :: ExeName -> ExeName -> Bool
< :: ExeName -> ExeName -> Bool
$c<= :: ExeName -> ExeName -> Bool
<= :: ExeName -> ExeName -> Bool
$c> :: ExeName -> ExeName -> Bool
> :: ExeName -> ExeName -> Bool
$c>= :: ExeName -> ExeName -> Bool
>= :: ExeName -> ExeName -> Bool
$cmax :: ExeName -> ExeName -> ExeName
max :: ExeName -> ExeName -> ExeName
$cmin :: ExeName -> ExeName -> ExeName
min :: ExeName -> ExeName -> ExeName
Ord, Int -> ExeName -> ShowS
[ExeName] -> ShowS
ExeName -> String
(Int -> ExeName -> ShowS)
-> (ExeName -> String) -> ([ExeName] -> ShowS) -> Show ExeName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExeName -> ShowS
showsPrec :: Int -> ExeName -> ShowS
$cshow :: ExeName -> String
show :: ExeName -> String
$cshowList :: [ExeName] -> ShowS
showList :: [ExeName] -> ShowS
Show, Typeable)

-- | Some package info.

data Package = Package
  { Package -> PackageName
name :: !PackageName
    -- ^ Name of the package.

  , Package -> Version
version :: !Version
    -- ^ Version of the package

  , Package -> Either License License
license :: !(Either SPDX.License License)
    -- ^ The license the package was released under.

  , Package -> [Text]
ghcOptions :: ![Text]
    -- ^ Ghc options used on package.

  , Package -> [Text]
cabalConfigOpts :: ![Text]
    -- ^ Additional options passed to ./Setup.hs configure

  , Package -> Map FlagName Bool
flags :: !(Map FlagName Bool)
    -- ^ Flags used on package.

  , Package -> Map FlagName Bool
defaultFlags :: !(Map FlagName Bool)
    -- ^ Defaults for unspecified flags.

  , Package -> Maybe StackLibrary
library :: !(Maybe StackLibrary)
    -- ^ Does the package have a buildable main library stanza?

  , Package -> CompCollection StackLibrary
subLibraries :: !(CompCollection StackLibrary)
    -- ^ The sub-libraries of the package.

  , Package -> CompCollection StackForeignLibrary
foreignLibraries :: !(CompCollection StackForeignLibrary)
    -- ^ The foreign libraries of the package.

  , Package -> CompCollection StackTestSuite
testSuites :: !(CompCollection StackTestSuite)
    -- ^ The test suites of the package.

  , Package -> CompCollection StackBenchmark
benchmarks :: !(CompCollection StackBenchmark)
    -- ^ The benchmarks of the package.

  , Package -> CompCollection StackExecutable
executables :: !(CompCollection StackExecutable)
    -- ^ The executables of the package.

  , Package -> BuildType
buildType :: !BuildType
    -- ^ Package build-type.

  , Package -> Maybe (Map PackageName DepValue)
setupDeps :: !(Maybe (Map PackageName DepValue))
    -- ^ If present: custom-setup dependencies

  , Package -> CabalSpecVersion
cabalSpec :: !CabalSpecVersion
    -- ^ Cabal spec range

  , Package -> StackPackageFile
file :: StackPackageFile
    -- ^ The Cabal sourced files related to the package at the package level

    -- The components may have file information in their own types

  , Package -> Bool
testEnabled :: Bool
    -- ^ This is a requirement because when tests are not enabled, Stack's

    -- package dependencies should ignore test dependencies. Directly set from

    -- 'packageConfigEnableTests'.

  , Package -> Bool
benchmarkEnabled :: Bool
    -- ^ This is a requirement because when benchmark are not enabled, Stack's

    -- package dependencies should ignore benchmark dependencies. Directly set

    -- from 'packageConfigEnableBenchmarks'.

  }
  deriving (Int -> Package -> ShowS
[Package] -> ShowS
Package -> String
(Int -> Package -> ShowS)
-> (Package -> String) -> ([Package] -> ShowS) -> Show Package
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Package -> ShowS
showsPrec :: Int -> Package -> ShowS
$cshow :: Package -> String
show :: Package -> String
$cshowList :: [Package] -> ShowS
showList :: [Package] -> ShowS
Show, Typeable)

packageIdentifier :: Package -> PackageIdentifier
packageIdentifier :: Package -> PackageIdentifier
packageIdentifier Package
p = PackageName -> Version -> PackageIdentifier
PackageIdentifier Package
p.name Package
p.version

packageDefinedFlags :: Package -> Set FlagName
packageDefinedFlags :: Package -> Set FlagName
packageDefinedFlags = Map FlagName Bool -> Set FlagName
forall k a. Map k a -> Set k
M.keysSet (Map FlagName Bool -> Set FlagName)
-> (Package -> Map FlagName Bool) -> Package -> Set FlagName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.defaultFlags)

-- | GHC options based on cabal information and ghc-options.

data BuildInfoOpts = BuildInfoOpts
  { BuildInfoOpts -> [String]
opts :: [String]
  , BuildInfoOpts -> [String]
oneWordOpts :: [String]
  , BuildInfoOpts -> [String]
packageFlags :: [String]
    -- ^ These options can safely have 'nubOrd' applied to them, as there are no

    -- multi-word options (see

    -- https://github.com/commercialhaskell/stack/issues/1255)

  , BuildInfoOpts -> Path Abs File
cabalMacros :: Path Abs File
  }
  deriving Int -> BuildInfoOpts -> ShowS
[BuildInfoOpts] -> ShowS
BuildInfoOpts -> String
(Int -> BuildInfoOpts -> ShowS)
-> (BuildInfoOpts -> String)
-> ([BuildInfoOpts] -> ShowS)
-> Show BuildInfoOpts
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BuildInfoOpts -> ShowS
showsPrec :: Int -> BuildInfoOpts -> ShowS
$cshow :: BuildInfoOpts -> String
show :: BuildInfoOpts -> String
$cshowList :: [BuildInfoOpts] -> ShowS
showList :: [BuildInfoOpts] -> ShowS
Show

-- | Package build configuration

data PackageConfig = PackageConfig
  { PackageConfig -> Bool
enableTests :: !Bool
    -- ^ Are tests enabled?

  , PackageConfig -> Bool
enableBenchmarks :: !Bool
    -- ^ Are benchmarks enabled?

  , PackageConfig -> Map FlagName Bool
flags :: !(Map FlagName Bool)
    -- ^ Configured flags.

  , PackageConfig -> [Text]
ghcOptions :: ![Text]
    -- ^ Configured ghc options.

  , PackageConfig -> [Text]
cabalConfigOpts :: ![Text]
    -- ^ ./Setup.hs configure options

  , PackageConfig -> ActualCompiler
compilerVersion :: ActualCompiler
    -- ^ GHC version

  , PackageConfig -> Platform
platform :: !Platform
    -- ^ host platform

  }
 deriving (Int -> PackageConfig -> ShowS
[PackageConfig] -> ShowS
PackageConfig -> String
(Int -> PackageConfig -> ShowS)
-> (PackageConfig -> String)
-> ([PackageConfig] -> ShowS)
-> Show PackageConfig
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PackageConfig -> ShowS
showsPrec :: Int -> PackageConfig -> ShowS
$cshow :: PackageConfig -> String
show :: PackageConfig -> String
$cshowList :: [PackageConfig] -> ShowS
showList :: [PackageConfig] -> ShowS
Show, Typeable)

-- | Compares the package name.

instance Ord Package where
  compare :: Package -> Package -> Ordering
compare = (PackageName -> PackageName -> Ordering)
-> (Package -> PackageName) -> Package -> Package -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on PackageName -> PackageName -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (.name)

-- | Compares the package name.

instance Eq Package where
  == :: Package -> Package -> Bool
(==) = (PackageName -> PackageName -> Bool)
-> (Package -> PackageName) -> Package -> Package -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on PackageName -> PackageName -> Bool
forall a. Eq a => a -> a -> Bool
(==) (.name)

-- | Where the package's source is located: local directory or package index

data PackageSource
  = PSFilePath LocalPackage
    -- ^ Package which exist on the filesystem

  | PSRemote PackageLocationImmutable Version FromSnapshot CommonPackage
    -- ^ Package which is downloaded remotely.


instance Show PackageSource where
  show :: PackageSource -> String
show (PSFilePath LocalPackage
lp) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"PSFilePath (", LocalPackage -> String
forall a. Show a => a -> String
show LocalPackage
lp, String
")"]
  show (PSRemote PackageLocationImmutable
pli Version
v FromSnapshot
fromSnapshot CommonPackage
_) =
    [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
      [ String
"PSRemote"
      , String
"(", PackageLocationImmutable -> String
forall a. Show a => a -> String
show PackageLocationImmutable
pli, String
")"
      , String
"(", Version -> String
forall a. Show a => a -> String
show Version
v, String
")"
      , FromSnapshot -> String
forall a. Show a => a -> String
show FromSnapshot
fromSnapshot
      , String
"<CommonPackage>"
      ]

psVersion :: PackageSource -> Version
psVersion :: PackageSource -> Version
psVersion (PSFilePath LocalPackage
lp) = LocalPackage
lp.package.version
psVersion (PSRemote PackageLocationImmutable
_ Version
v FromSnapshot
_ CommonPackage
_) = Version
v

-- | Information on a locally available package of source code.

data LocalPackage = LocalPackage
  { LocalPackage -> Package
package       :: !Package
     -- ^ The @Package@ info itself, after resolution with package flags, with

     -- tests and benchmarks disabled

  , LocalPackage -> Set NamedComponent
components    :: !(Set NamedComponent)
    -- ^ Components to build, not including the library component.

  , LocalPackage -> Set NamedComponent
unbuildable   :: !(Set NamedComponent)
    -- ^ Components explicitly requested for build, that are marked

    -- "buildable: false".

  , LocalPackage -> Bool
wanted        :: !Bool -- FIXME Should completely drop this "wanted"

                             -- terminology, it's unclear

    -- ^ Whether this package is wanted as a target.

  , LocalPackage -> Maybe Package
testBench     :: !(Maybe Package)
    -- ^ This stores the 'Package' with tests and benchmarks enabled, if either

    -- is asked for by the user.

  , LocalPackage -> Path Abs File
cabalFP     :: !(Path Abs File)
    -- ^ Absolute path to the Cabal file.

  , LocalPackage -> Bool
buildHaddocks :: !Bool
    -- ^ Is Haddock documentation being built for this package?

  , LocalPackage -> Bool
forceDirty    :: !Bool
  , LocalPackage -> MemoizedWith EnvConfig (Maybe (Set String))
dirtyFiles    :: !(MemoizedWith EnvConfig (Maybe (Set FilePath)))
    -- ^ Nothing == not dirty, Just == dirty. Note that the Set may be empty if

    -- we forced the build to treat packages as dirty. Also, the Set may not

    -- include all modified files.

  , LocalPackage
-> MemoizedWith
     EnvConfig (Map NamedComponent (Map String FileCacheInfo))
newBuildCaches :: !( MemoizedWith
                             EnvConfig
                             (Map NamedComponent (Map FilePath FileCacheInfo))
                         )
    -- ^ current state of the files

  , LocalPackage
-> MemoizedWith
     EnvConfig (Map NamedComponent (Set (Path Abs File)))
componentFiles :: !( MemoizedWith
                             EnvConfig
                             (Map NamedComponent (Set (Path Abs File)))
                         )
    -- ^ all files used by this package

  }
  deriving Int -> LocalPackage -> ShowS
[LocalPackage] -> ShowS
LocalPackage -> String
(Int -> LocalPackage -> ShowS)
-> (LocalPackage -> String)
-> ([LocalPackage] -> ShowS)
-> Show LocalPackage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LocalPackage -> ShowS
showsPrec :: Int -> LocalPackage -> ShowS
$cshow :: LocalPackage -> String
show :: LocalPackage -> String
$cshowList :: [LocalPackage] -> ShowS
showList :: [LocalPackage] -> ShowS
Show

newtype MemoizedWith env a
  = MemoizedWith { forall env a. MemoizedWith env a -> RIO env a
memoizedWith :: RIO env a }
  deriving (Functor (MemoizedWith env)
Functor (MemoizedWith env) =>
(forall a. a -> MemoizedWith env a)
-> (forall a b.
    MemoizedWith env (a -> b)
    -> MemoizedWith env a -> MemoizedWith env b)
-> (forall a b c.
    (a -> b -> c)
    -> MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env c)
-> (forall a b.
    MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b)
-> (forall a b.
    MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env a)
-> Applicative (MemoizedWith env)
forall env. Functor (MemoizedWith env)
forall a. a -> MemoizedWith env a
forall env a. a -> MemoizedWith env a
forall a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env a
forall a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b
forall a b.
MemoizedWith env (a -> b)
-> MemoizedWith env a -> MemoizedWith env b
forall env a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env a
forall env a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b
forall env a b.
MemoizedWith env (a -> b)
-> MemoizedWith env a -> MemoizedWith env b
forall a b c.
(a -> b -> c)
-> MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env c
forall env a b c.
(a -> b -> c)
-> MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall env a. a -> MemoizedWith env a
pure :: forall a. a -> MemoizedWith env a
$c<*> :: forall env a b.
MemoizedWith env (a -> b)
-> MemoizedWith env a -> MemoizedWith env b
<*> :: forall a b.
MemoizedWith env (a -> b)
-> MemoizedWith env a -> MemoizedWith env b
$cliftA2 :: forall env a b c.
(a -> b -> c)
-> MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env c
liftA2 :: forall a b c.
(a -> b -> c)
-> MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env c
$c*> :: forall env a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b
*> :: forall a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b
$c<* :: forall env a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env a
<* :: forall a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env a
Applicative, (forall a b. (a -> b) -> MemoizedWith env a -> MemoizedWith env b)
-> (forall a b. a -> MemoizedWith env b -> MemoizedWith env a)
-> Functor (MemoizedWith env)
forall a b. a -> MemoizedWith env b -> MemoizedWith env a
forall a b. (a -> b) -> MemoizedWith env a -> MemoizedWith env b
forall env a b. a -> MemoizedWith env b -> MemoizedWith env a
forall env a b.
(a -> b) -> MemoizedWith env a -> MemoizedWith env b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall env a b.
(a -> b) -> MemoizedWith env a -> MemoizedWith env b
fmap :: forall a b. (a -> b) -> MemoizedWith env a -> MemoizedWith env b
$c<$ :: forall env a b. a -> MemoizedWith env b -> MemoizedWith env a
<$ :: forall a b. a -> MemoizedWith env b -> MemoizedWith env a
Functor, Applicative (MemoizedWith env)
Applicative (MemoizedWith env) =>
(forall a b.
 MemoizedWith env a
 -> (a -> MemoizedWith env b) -> MemoizedWith env b)
-> (forall a b.
    MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b)
-> (forall a. a -> MemoizedWith env a)
-> Monad (MemoizedWith env)
forall env. Applicative (MemoizedWith env)
forall a. a -> MemoizedWith env a
forall env a. a -> MemoizedWith env a
forall a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b
forall a b.
MemoizedWith env a
-> (a -> MemoizedWith env b) -> MemoizedWith env b
forall env a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b
forall env a b.
MemoizedWith env a
-> (a -> MemoizedWith env b) -> MemoizedWith env b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall env a b.
MemoizedWith env a
-> (a -> MemoizedWith env b) -> MemoizedWith env b
>>= :: forall a b.
MemoizedWith env a
-> (a -> MemoizedWith env b) -> MemoizedWith env b
$c>> :: forall env a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b
>> :: forall a b.
MemoizedWith env a -> MemoizedWith env b -> MemoizedWith env b
$creturn :: forall env a. a -> MemoizedWith env a
return :: forall a. a -> MemoizedWith env a
Monad)

memoizeRefWith :: MonadIO m => RIO env a -> m (MemoizedWith env a)
memoizeRefWith :: forall (m :: * -> *) env a.
MonadIO m =>
RIO env a -> m (MemoizedWith env a)
memoizeRefWith RIO env a
action = do
  IORef (Maybe (Either SomeException a))
ref <- Maybe (Either SomeException a)
-> m (IORef (Maybe (Either SomeException a)))
forall (m :: * -> *) a. MonadIO m => a -> m (IORef a)
newIORef Maybe (Either SomeException a)
forall a. Maybe a
Nothing
  MemoizedWith env a -> m (MemoizedWith env a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (MemoizedWith env a -> m (MemoizedWith env a))
-> MemoizedWith env a -> m (MemoizedWith env a)
forall a b. (a -> b) -> a -> b
$ RIO env a -> MemoizedWith env a
forall env a. RIO env a -> MemoizedWith env a
MemoizedWith (RIO env a -> MemoizedWith env a)
-> RIO env a -> MemoizedWith env a
forall a b. (a -> b) -> a -> b
$ do
    Maybe (Either SomeException a)
mres <- IORef (Maybe (Either SomeException a))
-> RIO env (Maybe (Either SomeException a))
forall (m :: * -> *) a. MonadIO m => IORef a -> m a
readIORef IORef (Maybe (Either SomeException a))
ref
    Either SomeException a
res <-
      case Maybe (Either SomeException a)
mres of
        Just Either SomeException a
res -> Either SomeException a -> RIO env (Either SomeException a)
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Either SomeException a
res
        Maybe (Either SomeException a)
Nothing -> do
          Either SomeException a
res <- RIO env a -> RIO env (Either SomeException a)
forall (m :: * -> *) a.
MonadUnliftIO m =>
m a -> m (Either SomeException a)
tryAny RIO env a
action
          IORef (Maybe (Either SomeException a))
-> Maybe (Either SomeException a) -> RIO env ()
forall (m :: * -> *) a. MonadIO m => IORef a -> a -> m ()
writeIORef IORef (Maybe (Either SomeException a))
ref (Maybe (Either SomeException a) -> RIO env ())
-> Maybe (Either SomeException a) -> RIO env ()
forall a b. (a -> b) -> a -> b
$ Either SomeException a -> Maybe (Either SomeException a)
forall a. a -> Maybe a
Just Either SomeException a
res
          Either SomeException a -> RIO env (Either SomeException a)
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Either SomeException a
res
    (SomeException -> RIO env a)
-> (a -> RIO env a) -> Either SomeException a -> RIO env a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either SomeException -> RIO env a
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO a -> RIO env a
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Either SomeException a
res

runMemoizedWith ::
     (HasEnvConfig env, MonadReader env m, MonadIO m)
  => MemoizedWith EnvConfig a
  -> m a
runMemoizedWith :: forall env (m :: * -> *) a.
(HasEnvConfig env, MonadReader env m, MonadIO m) =>
MemoizedWith EnvConfig a -> m a
runMemoizedWith (MemoizedWith RIO EnvConfig a
action) = do
  EnvConfig
envConfig <- Getting EnvConfig env EnvConfig -> m EnvConfig
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting EnvConfig env EnvConfig
forall env. HasEnvConfig env => Lens' env EnvConfig
Lens' env EnvConfig
envConfigL
  EnvConfig -> RIO EnvConfig a -> m a
forall (m :: * -> *) env a. MonadIO m => env -> RIO env a -> m a
runRIO EnvConfig
envConfig RIO EnvConfig a
action

instance Show (MemoizedWith env a) where
  show :: MemoizedWith env a -> String
show MemoizedWith env a
_ = String
"<<MemoizedWith>>"

lpFiles :: HasEnvConfig env => LocalPackage -> RIO env (Set.Set (Path Abs File))
lpFiles :: forall env.
HasEnvConfig env =>
LocalPackage -> RIO env (Set (Path Abs File))
lpFiles = MemoizedWith EnvConfig (Set (Path Abs File))
-> RIO env (Set (Path Abs File))
forall env (m :: * -> *) a.
(HasEnvConfig env, MonadReader env m, MonadIO m) =>
MemoizedWith EnvConfig a -> m a
runMemoizedWith (MemoizedWith EnvConfig (Set (Path Abs File))
 -> RIO env (Set (Path Abs File)))
-> (LocalPackage -> MemoizedWith EnvConfig (Set (Path Abs File)))
-> LocalPackage
-> RIO env (Set (Path Abs File))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map NamedComponent (Set (Path Abs File)) -> Set (Path Abs File))
-> MemoizedWith
     EnvConfig (Map NamedComponent (Set (Path Abs File)))
-> MemoizedWith EnvConfig (Set (Path Abs File))
forall a b.
(a -> b) -> MemoizedWith EnvConfig a -> MemoizedWith EnvConfig b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Set (Path Abs File)] -> Set (Path Abs File)
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
Set.unions ([Set (Path Abs File)] -> Set (Path Abs File))
-> (Map NamedComponent (Set (Path Abs File))
    -> [Set (Path Abs File)])
-> Map NamedComponent (Set (Path Abs File))
-> Set (Path Abs File)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map NamedComponent (Set (Path Abs File)) -> [Set (Path Abs File)]
forall k a. Map k a -> [a]
M.elems) (MemoizedWith EnvConfig (Map NamedComponent (Set (Path Abs File)))
 -> MemoizedWith EnvConfig (Set (Path Abs File)))
-> (LocalPackage
    -> MemoizedWith
         EnvConfig (Map NamedComponent (Set (Path Abs File))))
-> LocalPackage
-> MemoizedWith EnvConfig (Set (Path Abs File))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.componentFiles)

lpFilesForComponents :: HasEnvConfig env
                     => Set NamedComponent
                     -> LocalPackage
                     -> RIO env (Set.Set (Path Abs File))
lpFilesForComponents :: forall env.
HasEnvConfig env =>
Set NamedComponent -> LocalPackage -> RIO env (Set (Path Abs File))
lpFilesForComponents Set NamedComponent
components LocalPackage
lp = MemoizedWith EnvConfig (Set (Path Abs File))
-> RIO env (Set (Path Abs File))
forall env (m :: * -> *) a.
(HasEnvConfig env, MonadReader env m, MonadIO m) =>
MemoizedWith EnvConfig a -> m a
runMemoizedWith (MemoizedWith EnvConfig (Set (Path Abs File))
 -> RIO env (Set (Path Abs File)))
-> MemoizedWith EnvConfig (Set (Path Abs File))
-> RIO env (Set (Path Abs File))
forall a b. (a -> b) -> a -> b
$ do
  Map NamedComponent (Set (Path Abs File))
componentFiles <- LocalPackage
lp.componentFiles
  Set (Path Abs File) -> MemoizedWith EnvConfig (Set (Path Abs File))
forall a. a -> MemoizedWith EnvConfig a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Set (Path Abs File)
 -> MemoizedWith EnvConfig (Set (Path Abs File)))
-> Set (Path Abs File)
-> MemoizedWith EnvConfig (Set (Path Abs File))
forall a b. (a -> b) -> a -> b
$ [Set (Path Abs File)] -> Set (Path Abs File)
forall a. Monoid a => [a] -> a
mconcat (Map NamedComponent (Set (Path Abs File)) -> [Set (Path Abs File)]
forall k a. Map k a -> [a]
M.elems (Map NamedComponent (Set (Path Abs File))
-> Set NamedComponent -> Map NamedComponent (Set (Path Abs File))
forall k a. Ord k => Map k a -> Set k -> Map k a
M.restrictKeys Map NamedComponent (Set (Path Abs File))
componentFiles Set NamedComponent
components))

newtype FileCacheInfo = FileCacheInfo
  { FileCacheInfo -> SHA256
hash :: SHA256
  }
  deriving (FileCacheInfo -> FileCacheInfo -> Bool
(FileCacheInfo -> FileCacheInfo -> Bool)
-> (FileCacheInfo -> FileCacheInfo -> Bool) -> Eq FileCacheInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileCacheInfo -> FileCacheInfo -> Bool
== :: FileCacheInfo -> FileCacheInfo -> Bool
$c/= :: FileCacheInfo -> FileCacheInfo -> Bool
/= :: FileCacheInfo -> FileCacheInfo -> Bool
Eq, (forall x. FileCacheInfo -> Rep FileCacheInfo x)
-> (forall x. Rep FileCacheInfo x -> FileCacheInfo)
-> Generic FileCacheInfo
forall x. Rep FileCacheInfo x -> FileCacheInfo
forall x. FileCacheInfo -> Rep FileCacheInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FileCacheInfo -> Rep FileCacheInfo x
from :: forall x. FileCacheInfo -> Rep FileCacheInfo x
$cto :: forall x. Rep FileCacheInfo x -> FileCacheInfo
to :: forall x. Rep FileCacheInfo x -> FileCacheInfo
Generic, Int -> FileCacheInfo -> ShowS
[FileCacheInfo] -> ShowS
FileCacheInfo -> String
(Int -> FileCacheInfo -> ShowS)
-> (FileCacheInfo -> String)
-> ([FileCacheInfo] -> ShowS)
-> Show FileCacheInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileCacheInfo -> ShowS
showsPrec :: Int -> FileCacheInfo -> ShowS
$cshow :: FileCacheInfo -> String
show :: FileCacheInfo -> String
$cshowList :: [FileCacheInfo] -> ShowS
showList :: [FileCacheInfo] -> ShowS
Show, Typeable)

instance NFData FileCacheInfo

-- Provided for storing the BuildCache values in a file. But maybe JSON/YAML

-- isn't the right choice here, worth considering.

instance ToJSON FileCacheInfo where
  toJSON :: FileCacheInfo -> Value
toJSON (FileCacheInfo SHA256
hash') = [Pair] -> Value
object
    [ Key
"hash" Key -> SHA256 -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SHA256
hash'
    ]
instance FromJSON FileCacheInfo where
  parseJSON :: Value -> Parser FileCacheInfo
parseJSON = String
-> (Object -> Parser FileCacheInfo)
-> Value
-> Parser FileCacheInfo
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"FileCacheInfo" ((Object -> Parser FileCacheInfo) -> Value -> Parser FileCacheInfo)
-> (Object -> Parser FileCacheInfo)
-> Value
-> Parser FileCacheInfo
forall a b. (a -> b) -> a -> b
$ \Object
o -> SHA256 -> FileCacheInfo
FileCacheInfo
    (SHA256 -> FileCacheInfo) -> Parser SHA256 -> Parser FileCacheInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser SHA256
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"hash"

-- | Maybe get the module name from the .cabal descriptor.

dotCabalModule :: DotCabalDescriptor -> Maybe ModuleName
dotCabalModule :: DotCabalDescriptor -> Maybe ModuleName
dotCabalModule (DotCabalModule ModuleName
m) = ModuleName -> Maybe ModuleName
forall a. a -> Maybe a
Just ModuleName
m
dotCabalModule DotCabalDescriptor
_ = Maybe ModuleName
forall a. Maybe a
Nothing

-- | Maybe get the main name from the .cabal descriptor.

dotCabalMain :: DotCabalDescriptor -> Maybe FilePath
dotCabalMain :: DotCabalDescriptor -> Maybe String
dotCabalMain (DotCabalMain String
m) = String -> Maybe String
forall a. a -> Maybe a
Just String
m
dotCabalMain DotCabalDescriptor
_ = Maybe String
forall a. Maybe a
Nothing

-- | Get the module path.

dotCabalModulePath :: DotCabalPath -> Maybe (Path Abs File)
dotCabalModulePath :: DotCabalPath -> Maybe (Path Abs File)
dotCabalModulePath (DotCabalModulePath Path Abs File
fp) = Path Abs File -> Maybe (Path Abs File)
forall a. a -> Maybe a
Just Path Abs File
fp
dotCabalModulePath DotCabalPath
_ = Maybe (Path Abs File)
forall a. Maybe a
Nothing

-- | Get the main path.

dotCabalMainPath :: DotCabalPath -> Maybe (Path Abs File)
dotCabalMainPath :: DotCabalPath -> Maybe (Path Abs File)
dotCabalMainPath (DotCabalMainPath Path Abs File
fp) = Path Abs File -> Maybe (Path Abs File)
forall a. a -> Maybe a
Just Path Abs File
fp
dotCabalMainPath DotCabalPath
_ = Maybe (Path Abs File)
forall a. Maybe a
Nothing

-- | Get the c file path.

dotCabalCFilePath :: DotCabalPath -> Maybe (Path Abs File)
dotCabalCFilePath :: DotCabalPath -> Maybe (Path Abs File)
dotCabalCFilePath (DotCabalCFilePath Path Abs File
fp) = Path Abs File -> Maybe (Path Abs File)
forall a. a -> Maybe a
Just Path Abs File
fp
dotCabalCFilePath DotCabalPath
_ = Maybe (Path Abs File)
forall a. Maybe a
Nothing

-- | Get the path.

dotCabalGetPath :: DotCabalPath -> Path Abs File
dotCabalGetPath :: DotCabalPath -> Path Abs File
dotCabalGetPath DotCabalPath
dcp =
  case DotCabalPath
dcp of
    DotCabalModulePath Path Abs File
fp -> Path Abs File
fp
    DotCabalMainPath Path Abs File
fp -> Path Abs File
fp
    DotCabalFilePath Path Abs File
fp -> Path Abs File
fp
    DotCabalCFilePath Path Abs File
fp -> Path Abs File
fp

-- | Gathers all the GhcPkgId provided by a library into a map

installedMapGhcPkgId ::
     PackageIdentifier
  -> InstalledLibraryInfo
  -> Map PackageIdentifier GhcPkgId
installedMapGhcPkgId :: PackageIdentifier
-> InstalledLibraryInfo -> Map PackageIdentifier GhcPkgId
installedMapGhcPkgId pkgId :: PackageIdentifier
pkgId@(PackageIdentifier PackageName
pkgName Version
version) InstalledLibraryInfo
installedLib =
  Map PackageIdentifier GhcPkgId
finalMap
 where
  finalMap :: Map PackageIdentifier GhcPkgId
finalMap = PackageIdentifier
-> GhcPkgId
-> Map PackageIdentifier GhcPkgId
-> Map PackageIdentifier GhcPkgId
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert PackageIdentifier
pkgId InstalledLibraryInfo
installedLib.ghcPkgId Map PackageIdentifier GhcPkgId
baseMap
  baseMap :: Map PackageIdentifier GhcPkgId
baseMap =
    (StackUnqualCompName -> PackageIdentifier)
-> Map StackUnqualCompName GhcPkgId
-> Map PackageIdentifier GhcPkgId
forall k1 k2 a. (k1 -> k2) -> Map k1 a -> Map k2 a
M.mapKeysMonotonic
      (PackageName -> Version -> StackUnqualCompName -> PackageIdentifier
toCabalMungedPackageIdentifier PackageName
pkgName Version
version)
      InstalledLibraryInfo
installedLib.subLib

-- | Creates a 'MungedPackageName' identifier.

toCabalMungedPackageIdentifier ::
     PackageName
  -> Version
  -> StackUnqualCompName
  -> PackageIdentifier
toCabalMungedPackageIdentifier :: PackageName -> Version -> StackUnqualCompName -> PackageIdentifier
toCabalMungedPackageIdentifier PackageName
pkgName Version
version = (PackageName -> Version -> PackageIdentifier)
-> Version -> PackageName -> PackageIdentifier
forall a b c. (a -> b -> c) -> b -> a -> c
flip PackageName -> Version -> PackageIdentifier
PackageIdentifier Version
version
  (PackageName -> PackageIdentifier)
-> (StackUnqualCompName -> PackageName)
-> StackUnqualCompName
-> PackageIdentifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MungedPackageName -> PackageName
encodeCompatPackageName (MungedPackageName -> PackageName)
-> (StackUnqualCompName -> MungedPackageName)
-> StackUnqualCompName
-> PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> StackUnqualCompName -> MungedPackageName
toCabalMungedPackageName PackageName
pkgName

toCabalMungedPackageName ::
     PackageName
  -> StackUnqualCompName
  -> MungedPackageName
toCabalMungedPackageName :: PackageName -> StackUnqualCompName -> MungedPackageName
toCabalMungedPackageName PackageName
pkgName =
  PackageName -> LibraryName -> MungedPackageName
MungedPackageName PackageName
pkgName (LibraryName -> MungedPackageName)
-> (StackUnqualCompName -> LibraryName)
-> StackUnqualCompName
-> MungedPackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnqualComponentName -> LibraryName
LSubLibName (UnqualComponentName -> LibraryName)
-> (StackUnqualCompName -> UnqualComponentName)
-> StackUnqualCompName
-> LibraryName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StackUnqualCompName -> UnqualComponentName
toCabalName

-- | Type representing inputs to 'Stack.Package.generateBuildInfoOpts'.

data BioInput = BioInput
  { BioInput -> InstallMap
installMap :: !InstallMap
  , BioInput -> InstalledMap
installedMap :: !InstalledMap
  , BioInput -> Path Abs Dir
cabalDir :: !(Path Abs Dir)
  , BioInput -> Path Abs Dir
distDir :: !(Path Abs Dir)
  , BioInput -> [PackageName]
omitPackages :: ![PackageName]
  , BioInput -> [PackageName]
addPackages :: ![PackageName]
  , BioInput -> StackBuildInfo
buildInfo :: !StackBuildInfo
  , BioInput -> [DotCabalPath]
dotCabalPaths :: ![DotCabalPath]
  , BioInput -> [String]
configLibDirs :: ![FilePath]
  , BioInput -> [String]
configIncludeDirs :: ![FilePath]
  , BioInput -> NamedComponent
componentName :: !NamedComponent
  , BioInput -> Version
cabalVersion :: !Version
  }