{-# LANGUAGE CPP                        #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE RecordWildCards            #-}

-- | SPDX-License-Identifier: GPL-2.0-or-later
--
-- Utilities for reading @cabal@'s @plan.json@ file
--
-- @plan.json@ are generated when using @cabal@
-- <http://cabal.readthedocs.io/en/latest/nix-local-build-overview.html Nix-style Local Builds>.
module Cabal.Plan
    (
      PlanJson(..)
    , Unit(..)
    , CompName(..)
    , dispCompName
    , dispCompNameTarget
    , CompInfo(..)
    , UnitType(..)

    -- * Basic types
    , Ver(..)
    , dispVer
    , PkgName(..)
    , PkgId(..)
    , dispPkgId
    , UnitId(..)
    , FlagName(..)

    -- ** SHA-256
    , Sha256
    , dispSha256
    , parseSha256
    , sha256ToByteString
    , sha256FromByteString

    -- ** PkgLoc
    , PkgLoc(..)
    , Repo(..)
    , SourceRepo(..)
    , URI(..)
    , RepoType(..)

    -- * Utilities
    , planJsonIdGraph
    , planJsonIdRoots

    -- * Convenience functions
    , SearchPlanJson(..)
    , findAndDecodePlanJson
    , findPlanJson
    , findProjectRoot
    , decodePlanJson
    ) where

import           Control.Applicative          as App
import           Control.Monad
import           Data.Aeson
#if MIN_VERSION_aeson(2,0,0)
import qualified Data.Aeson.Key                as AK
#endif
import           Data.Aeson.Types
import qualified Data.ByteString              as B
import qualified Data.ByteString.Base16       as B16
import           Data.List
import           Data.Map                     (Map)
import qualified Data.Map                     as M
import           Data.Monoid
import           Data.Set                     (Set)
import qualified Data.Set                     as S
import           Data.Text                    (Text)
import qualified Data.Text                    as T
import qualified Data.Text.Encoding           as T
import qualified Data.Version                 as DV
import qualified System.Directory             as Dir
import           System.FilePath
                 ((</>), takeExtension, isDrive, takeDirectory)
import           Text.ParserCombinators.ReadP

----------------------------------------------------------------------------

-- | Equivalent to @Cabal@'s @Distribution.Package.Version@
newtype Ver = Ver [Int]
            deriving (Int -> Ver -> ShowS
[Ver] -> ShowS
Ver -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [Ver] -> ShowS
$cshowList :: [Ver] -> ShowS
show :: Ver -> [Char]
$cshow :: Ver -> [Char]
showsPrec :: Int -> Ver -> ShowS
$cshowsPrec :: Int -> Ver -> ShowS
Show,Ver -> Ver -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Ver -> Ver -> Bool
$c/= :: Ver -> Ver -> Bool
== :: Ver -> Ver -> Bool
$c== :: Ver -> Ver -> Bool
Eq,Eq Ver
Ver -> Ver -> Bool
Ver -> Ver -> Ordering
Ver -> Ver -> Ver
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
min :: Ver -> Ver -> Ver
$cmin :: Ver -> Ver -> Ver
max :: Ver -> Ver -> Ver
$cmax :: Ver -> Ver -> Ver
>= :: Ver -> Ver -> Bool
$c>= :: Ver -> Ver -> Bool
> :: Ver -> Ver -> Bool
$c> :: Ver -> Ver -> Bool
<= :: Ver -> Ver -> Bool
$c<= :: Ver -> Ver -> Bool
< :: Ver -> Ver -> Bool
$c< :: Ver -> Ver -> Bool
compare :: Ver -> Ver -> Ordering
$ccompare :: Ver -> Ver -> Ordering
Ord)

-- | Equivalent to @Cabal@'s @Distribution.Package.UnitId@
newtype UnitId = UnitId Text
               deriving (Int -> UnitId -> ShowS
[UnitId] -> ShowS
UnitId -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [UnitId] -> ShowS
$cshowList :: [UnitId] -> ShowS
show :: UnitId -> [Char]
$cshow :: UnitId -> [Char]
showsPrec :: Int -> UnitId -> ShowS
$cshowsPrec :: Int -> UnitId -> ShowS
Show,UnitId -> UnitId -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UnitId -> UnitId -> Bool
$c/= :: UnitId -> UnitId -> Bool
== :: UnitId -> UnitId -> Bool
$c== :: UnitId -> UnitId -> Bool
Eq,Eq UnitId
UnitId -> UnitId -> Bool
UnitId -> UnitId -> Ordering
UnitId -> UnitId -> UnitId
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
min :: UnitId -> UnitId -> UnitId
$cmin :: UnitId -> UnitId -> UnitId
max :: UnitId -> UnitId -> UnitId
$cmax :: UnitId -> UnitId -> UnitId
>= :: UnitId -> UnitId -> Bool
$c>= :: UnitId -> UnitId -> Bool
> :: UnitId -> UnitId -> Bool
$c> :: UnitId -> UnitId -> Bool
<= :: UnitId -> UnitId -> Bool
$c<= :: UnitId -> UnitId -> Bool
< :: UnitId -> UnitId -> Bool
$c< :: UnitId -> UnitId -> Bool
compare :: UnitId -> UnitId -> Ordering
$ccompare :: UnitId -> UnitId -> Ordering
Ord,Value -> Parser [UnitId]
Value -> Parser UnitId
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [UnitId]
$cparseJSONList :: Value -> Parser [UnitId]
parseJSON :: Value -> Parser UnitId
$cparseJSON :: Value -> Parser UnitId
FromJSON,[UnitId] -> Encoding
[UnitId] -> Value
UnitId -> Encoding
UnitId -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [UnitId] -> Encoding
$ctoEncodingList :: [UnitId] -> Encoding
toJSONList :: [UnitId] -> Value
$ctoJSONList :: [UnitId] -> Value
toEncoding :: UnitId -> Encoding
$ctoEncoding :: UnitId -> Encoding
toJSON :: UnitId -> Value
$ctoJSON :: UnitId -> Value
ToJSON,FromJSONKeyFunction [UnitId]
FromJSONKeyFunction UnitId
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
fromJSONKeyList :: FromJSONKeyFunction [UnitId]
$cfromJSONKeyList :: FromJSONKeyFunction [UnitId]
fromJSONKey :: FromJSONKeyFunction UnitId
$cfromJSONKey :: FromJSONKeyFunction UnitId
FromJSONKey,ToJSONKeyFunction [UnitId]
ToJSONKeyFunction UnitId
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
toJSONKeyList :: ToJSONKeyFunction [UnitId]
$ctoJSONKeyList :: ToJSONKeyFunction [UnitId]
toJSONKey :: ToJSONKeyFunction UnitId
$ctoJSONKey :: ToJSONKeyFunction UnitId
ToJSONKey)

-- | Equivalent to @Cabal@'s @Distribution.Package.PackageName@
newtype PkgName = PkgName Text
                deriving (Int -> PkgName -> ShowS
[PkgName] -> ShowS
PkgName -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [PkgName] -> ShowS
$cshowList :: [PkgName] -> ShowS
show :: PkgName -> [Char]
$cshow :: PkgName -> [Char]
showsPrec :: Int -> PkgName -> ShowS
$cshowsPrec :: Int -> PkgName -> ShowS
Show,PkgName -> PkgName -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PkgName -> PkgName -> Bool
$c/= :: PkgName -> PkgName -> Bool
== :: PkgName -> PkgName -> Bool
$c== :: PkgName -> PkgName -> Bool
Eq,Eq PkgName
PkgName -> PkgName -> Bool
PkgName -> PkgName -> Ordering
PkgName -> PkgName -> PkgName
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
min :: PkgName -> PkgName -> PkgName
$cmin :: PkgName -> PkgName -> PkgName
max :: PkgName -> PkgName -> PkgName
$cmax :: PkgName -> PkgName -> PkgName
>= :: PkgName -> PkgName -> Bool
$c>= :: PkgName -> PkgName -> Bool
> :: PkgName -> PkgName -> Bool
$c> :: PkgName -> PkgName -> Bool
<= :: PkgName -> PkgName -> Bool
$c<= :: PkgName -> PkgName -> Bool
< :: PkgName -> PkgName -> Bool
$c< :: PkgName -> PkgName -> Bool
compare :: PkgName -> PkgName -> Ordering
$ccompare :: PkgName -> PkgName -> Ordering
Ord,Value -> Parser [PkgName]
Value -> Parser PkgName
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [PkgName]
$cparseJSONList :: Value -> Parser [PkgName]
parseJSON :: Value -> Parser PkgName
$cparseJSON :: Value -> Parser PkgName
FromJSON,[PkgName] -> Encoding
[PkgName] -> Value
PkgName -> Encoding
PkgName -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [PkgName] -> Encoding
$ctoEncodingList :: [PkgName] -> Encoding
toJSONList :: [PkgName] -> Value
$ctoJSONList :: [PkgName] -> Value
toEncoding :: PkgName -> Encoding
$ctoEncoding :: PkgName -> Encoding
toJSON :: PkgName -> Value
$ctoJSON :: PkgName -> Value
ToJSON,FromJSONKeyFunction [PkgName]
FromJSONKeyFunction PkgName
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
fromJSONKeyList :: FromJSONKeyFunction [PkgName]
$cfromJSONKeyList :: FromJSONKeyFunction [PkgName]
fromJSONKey :: FromJSONKeyFunction PkgName
$cfromJSONKey :: FromJSONKeyFunction PkgName
FromJSONKey,ToJSONKeyFunction [PkgName]
ToJSONKeyFunction PkgName
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
toJSONKeyList :: ToJSONKeyFunction [PkgName]
$ctoJSONKeyList :: ToJSONKeyFunction [PkgName]
toJSONKey :: ToJSONKeyFunction PkgName
$ctoJSONKey :: ToJSONKeyFunction PkgName
ToJSONKey)

-- | Equivalent to @Cabal@'s @Distribution.Package.PackageIdentifier@
data PkgId = PkgId !PkgName !Ver
           deriving (Int -> PkgId -> ShowS
[PkgId] -> ShowS
PkgId -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [PkgId] -> ShowS
$cshowList :: [PkgId] -> ShowS
show :: PkgId -> [Char]
$cshow :: PkgId -> [Char]
showsPrec :: Int -> PkgId -> ShowS
$cshowsPrec :: Int -> PkgId -> ShowS
Show,PkgId -> PkgId -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PkgId -> PkgId -> Bool
$c/= :: PkgId -> PkgId -> Bool
== :: PkgId -> PkgId -> Bool
$c== :: PkgId -> PkgId -> Bool
Eq,Eq PkgId
PkgId -> PkgId -> Bool
PkgId -> PkgId -> Ordering
PkgId -> PkgId -> PkgId
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
min :: PkgId -> PkgId -> PkgId
$cmin :: PkgId -> PkgId -> PkgId
max :: PkgId -> PkgId -> PkgId
$cmax :: PkgId -> PkgId -> PkgId
>= :: PkgId -> PkgId -> Bool
$c>= :: PkgId -> PkgId -> Bool
> :: PkgId -> PkgId -> Bool
$c> :: PkgId -> PkgId -> Bool
<= :: PkgId -> PkgId -> Bool
$c<= :: PkgId -> PkgId -> Bool
< :: PkgId -> PkgId -> Bool
$c< :: PkgId -> PkgId -> Bool
compare :: PkgId -> PkgId -> Ordering
$ccompare :: PkgId -> PkgId -> Ordering
Ord)

-- | Equivalent to @Cabal@'s @Distribution.PackageDescription.FlagName@
--
-- @since 0.3.0.0
newtype FlagName = FlagName Text
                 deriving (Int -> FlagName -> ShowS
[FlagName] -> ShowS
FlagName -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [FlagName] -> ShowS
$cshowList :: [FlagName] -> ShowS
show :: FlagName -> [Char]
$cshow :: FlagName -> [Char]
showsPrec :: Int -> FlagName -> ShowS
$cshowsPrec :: Int -> FlagName -> ShowS
Show,FlagName -> FlagName -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FlagName -> FlagName -> Bool
$c/= :: FlagName -> FlagName -> Bool
== :: FlagName -> FlagName -> Bool
$c== :: FlagName -> FlagName -> Bool
Eq,Eq FlagName
FlagName -> FlagName -> Bool
FlagName -> FlagName -> Ordering
FlagName -> FlagName -> FlagName
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
min :: FlagName -> FlagName -> FlagName
$cmin :: FlagName -> FlagName -> FlagName
max :: FlagName -> FlagName -> FlagName
$cmax :: FlagName -> FlagName -> FlagName
>= :: FlagName -> FlagName -> Bool
$c>= :: FlagName -> FlagName -> Bool
> :: FlagName -> FlagName -> Bool
$c> :: FlagName -> FlagName -> Bool
<= :: FlagName -> FlagName -> Bool
$c<= :: FlagName -> FlagName -> Bool
< :: FlagName -> FlagName -> Bool
$c< :: FlagName -> FlagName -> Bool
compare :: FlagName -> FlagName -> Ordering
$ccompare :: FlagName -> FlagName -> Ordering
Ord,Value -> Parser [FlagName]
Value -> Parser FlagName
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [FlagName]
$cparseJSONList :: Value -> Parser [FlagName]
parseJSON :: Value -> Parser FlagName
$cparseJSON :: Value -> Parser FlagName
FromJSON,[FlagName] -> Encoding
[FlagName] -> Value
FlagName -> Encoding
FlagName -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [FlagName] -> Encoding
$ctoEncodingList :: [FlagName] -> Encoding
toJSONList :: [FlagName] -> Value
$ctoJSONList :: [FlagName] -> Value
toEncoding :: FlagName -> Encoding
$ctoEncoding :: FlagName -> Encoding
toJSON :: FlagName -> Value
$ctoJSON :: FlagName -> Value
ToJSON,FromJSONKeyFunction [FlagName]
FromJSONKeyFunction FlagName
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
fromJSONKeyList :: FromJSONKeyFunction [FlagName]
$cfromJSONKeyList :: FromJSONKeyFunction [FlagName]
fromJSONKey :: FromJSONKeyFunction FlagName
$cfromJSONKey :: FromJSONKeyFunction FlagName
FromJSONKey,ToJSONKeyFunction [FlagName]
ToJSONKeyFunction FlagName
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
toJSONKeyList :: ToJSONKeyFunction [FlagName]
$ctoJSONKeyList :: ToJSONKeyFunction [FlagName]
toJSONKey :: ToJSONKeyFunction FlagName
$ctoJSONKey :: ToJSONKeyFunction FlagName
ToJSONKey)

-- | <https://en.wikipedia.org/wiki/SHA-2 SHA-256> hash
newtype Sha256 = Sha256 B.ByteString -- internal invariant: exactly 32 bytes long
               deriving (Sha256 -> Sha256 -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Sha256 -> Sha256 -> Bool
$c/= :: Sha256 -> Sha256 -> Bool
== :: Sha256 -> Sha256 -> Bool
$c== :: Sha256 -> Sha256 -> Bool
Eq,Eq Sha256
Sha256 -> Sha256 -> Bool
Sha256 -> Sha256 -> Ordering
Sha256 -> Sha256 -> Sha256
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
min :: Sha256 -> Sha256 -> Sha256
$cmin :: Sha256 -> Sha256 -> Sha256
max :: Sha256 -> Sha256 -> Sha256
$cmax :: Sha256 -> Sha256 -> Sha256
>= :: Sha256 -> Sha256 -> Bool
$c>= :: Sha256 -> Sha256 -> Bool
> :: Sha256 -> Sha256 -> Bool
$c> :: Sha256 -> Sha256 -> Bool
<= :: Sha256 -> Sha256 -> Bool
$c<= :: Sha256 -> Sha256 -> Bool
< :: Sha256 -> Sha256 -> Bool
$c< :: Sha256 -> Sha256 -> Bool
compare :: Sha256 -> Sha256 -> Ordering
$ccompare :: Sha256 -> Sha256 -> Ordering
Ord)
-- | Equivalent to @Cabal@\'s @Distribution.Client.Types.PackageLocation@
--
-- @since 0.5.0.0
data PkgLoc
   = LocalUnpackedPackage    !FilePath
   | LocalTarballPackage     !FilePath
   | RemoteTarballPackage    !URI
   | RepoTarballPackage      !Repo
   | RemoteSourceRepoPackage !SourceRepo
     deriving (Int -> PkgLoc -> ShowS
[PkgLoc] -> ShowS
PkgLoc -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [PkgLoc] -> ShowS
$cshowList :: [PkgLoc] -> ShowS
show :: PkgLoc -> [Char]
$cshow :: PkgLoc -> [Char]
showsPrec :: Int -> PkgLoc -> ShowS
$cshowsPrec :: Int -> PkgLoc -> ShowS
Show,PkgLoc -> PkgLoc -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PkgLoc -> PkgLoc -> Bool
$c/= :: PkgLoc -> PkgLoc -> Bool
== :: PkgLoc -> PkgLoc -> Bool
$c== :: PkgLoc -> PkgLoc -> Bool
Eq,Eq PkgLoc
PkgLoc -> PkgLoc -> Bool
PkgLoc -> PkgLoc -> Ordering
PkgLoc -> PkgLoc -> PkgLoc
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
min :: PkgLoc -> PkgLoc -> PkgLoc
$cmin :: PkgLoc -> PkgLoc -> PkgLoc
max :: PkgLoc -> PkgLoc -> PkgLoc
$cmax :: PkgLoc -> PkgLoc -> PkgLoc
>= :: PkgLoc -> PkgLoc -> Bool
$c>= :: PkgLoc -> PkgLoc -> Bool
> :: PkgLoc -> PkgLoc -> Bool
$c> :: PkgLoc -> PkgLoc -> Bool
<= :: PkgLoc -> PkgLoc -> Bool
$c<= :: PkgLoc -> PkgLoc -> Bool
< :: PkgLoc -> PkgLoc -> Bool
$c< :: PkgLoc -> PkgLoc -> Bool
compare :: PkgLoc -> PkgLoc -> Ordering
$ccompare :: PkgLoc -> PkgLoc -> Ordering
Ord)

-- | Equivalent to @Cabal@\'s @Distribution.Types.SourceRepo@
--
-- @since 0.5.0.0
data Repo
   = RepoLocal  !FilePath
   | RepoRemote !URI
   | RepoSecure !URI
   | RepoLocalNoIndex !FilePath
     deriving (Int -> Repo -> ShowS
[Repo] -> ShowS
Repo -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [Repo] -> ShowS
$cshowList :: [Repo] -> ShowS
show :: Repo -> [Char]
$cshow :: Repo -> [Char]
showsPrec :: Int -> Repo -> ShowS
$cshowsPrec :: Int -> Repo -> ShowS
Show,Repo -> Repo -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Repo -> Repo -> Bool
$c/= :: Repo -> Repo -> Bool
== :: Repo -> Repo -> Bool
$c== :: Repo -> Repo -> Bool
Eq,Eq Repo
Repo -> Repo -> Bool
Repo -> Repo -> Ordering
Repo -> Repo -> Repo
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
min :: Repo -> Repo -> Repo
$cmin :: Repo -> Repo -> Repo
max :: Repo -> Repo -> Repo
$cmax :: Repo -> Repo -> Repo
>= :: Repo -> Repo -> Bool
$c>= :: Repo -> Repo -> Bool
> :: Repo -> Repo -> Bool
$c> :: Repo -> Repo -> Bool
<= :: Repo -> Repo -> Bool
$c<= :: Repo -> Repo -> Bool
< :: Repo -> Repo -> Bool
$c< :: Repo -> Repo -> Bool
compare :: Repo -> Repo -> Ordering
$ccompare :: Repo -> Repo -> Ordering
Ord)

-- | Equivalent to @Cabal@\'s @Distribution.Client.Types.Repo@
--
-- @since 0.5.0.0
data SourceRepo = SourceRepo
     { SourceRepo -> Maybe RepoType
srType     :: !(Maybe RepoType)
     , SourceRepo -> Maybe Text
srLocation :: !(Maybe Text)
     , SourceRepo -> Maybe Text
srModule   :: !(Maybe Text)
     , SourceRepo -> Maybe Text
srBranch   :: !(Maybe Text)
     , SourceRepo -> Maybe Text
srTag      :: !(Maybe Text)
     , SourceRepo -> Maybe [Char]
srSubdir   :: !(Maybe FilePath)
     } deriving (Int -> SourceRepo -> ShowS
[SourceRepo] -> ShowS
SourceRepo -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [SourceRepo] -> ShowS
$cshowList :: [SourceRepo] -> ShowS
show :: SourceRepo -> [Char]
$cshow :: SourceRepo -> [Char]
showsPrec :: Int -> SourceRepo -> ShowS
$cshowsPrec :: Int -> SourceRepo -> ShowS
Show,SourceRepo -> SourceRepo -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SourceRepo -> SourceRepo -> Bool
$c/= :: SourceRepo -> SourceRepo -> Bool
== :: SourceRepo -> SourceRepo -> Bool
$c== :: SourceRepo -> SourceRepo -> Bool
Eq,Eq SourceRepo
SourceRepo -> SourceRepo -> Bool
SourceRepo -> SourceRepo -> Ordering
SourceRepo -> SourceRepo -> SourceRepo
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
min :: SourceRepo -> SourceRepo -> SourceRepo
$cmin :: SourceRepo -> SourceRepo -> SourceRepo
max :: SourceRepo -> SourceRepo -> SourceRepo
$cmax :: SourceRepo -> SourceRepo -> SourceRepo
>= :: SourceRepo -> SourceRepo -> Bool
$c>= :: SourceRepo -> SourceRepo -> Bool
> :: SourceRepo -> SourceRepo -> Bool
$c> :: SourceRepo -> SourceRepo -> Bool
<= :: SourceRepo -> SourceRepo -> Bool
$c<= :: SourceRepo -> SourceRepo -> Bool
< :: SourceRepo -> SourceRepo -> Bool
$c< :: SourceRepo -> SourceRepo -> Bool
compare :: SourceRepo -> SourceRepo -> Ordering
$ccompare :: SourceRepo -> SourceRepo -> Ordering
Ord)

-- | Represents an URI (used e.g. by 'Repo')
--
-- @since 0.5.0.0
newtype URI = URI Text
    deriving (Int -> URI -> ShowS
[URI] -> ShowS
URI -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [URI] -> ShowS
$cshowList :: [URI] -> ShowS
show :: URI -> [Char]
$cshow :: URI -> [Char]
showsPrec :: Int -> URI -> ShowS
$cshowsPrec :: Int -> URI -> ShowS
Show,URI -> URI -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: URI -> URI -> Bool
$c/= :: URI -> URI -> Bool
== :: URI -> URI -> Bool
$c== :: URI -> URI -> Bool
Eq,Eq URI
URI -> URI -> Bool
URI -> URI -> Ordering
URI -> URI -> URI
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
min :: URI -> URI -> URI
$cmin :: URI -> URI -> URI
max :: URI -> URI -> URI
$cmax :: URI -> URI -> URI
>= :: URI -> URI -> Bool
$c>= :: URI -> URI -> Bool
> :: URI -> URI -> Bool
$c> :: URI -> URI -> Bool
<= :: URI -> URI -> Bool
$c<= :: URI -> URI -> Bool
< :: URI -> URI -> Bool
$c< :: URI -> URI -> Bool
compare :: URI -> URI -> Ordering
$ccompare :: URI -> URI -> Ordering
Ord,Value -> Parser [URI]
Value -> Parser URI
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [URI]
$cparseJSONList :: Value -> Parser [URI]
parseJSON :: Value -> Parser URI
$cparseJSON :: Value -> Parser URI
FromJSON,[URI] -> Encoding
[URI] -> Value
URI -> Encoding
URI -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [URI] -> Encoding
$ctoEncodingList :: [URI] -> Encoding
toJSONList :: [URI] -> Value
$ctoJSONList :: [URI] -> Value
toEncoding :: URI -> Encoding
$ctoEncoding :: URI -> Encoding
toJSON :: URI -> Value
$ctoJSON :: URI -> Value
ToJSON,FromJSONKeyFunction [URI]
FromJSONKeyFunction URI
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
fromJSONKeyList :: FromJSONKeyFunction [URI]
$cfromJSONKeyList :: FromJSONKeyFunction [URI]
fromJSONKey :: FromJSONKeyFunction URI
$cfromJSONKey :: FromJSONKeyFunction URI
FromJSONKey,ToJSONKeyFunction [URI]
ToJSONKeyFunction URI
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
toJSONKeyList :: ToJSONKeyFunction [URI]
$ctoJSONKeyList :: ToJSONKeyFunction [URI]
toJSONKey :: ToJSONKeyFunction URI
$ctoJSONKey :: ToJSONKeyFunction URI
ToJSONKey)

-- | Equivalent to @Cabal@\'s @Distribution.Client.SourceRepo.RepoType@
--
-- @since 0.5.0.0
data RepoType
   = Darcs
   | Git
   | SVN
   | CVS
   | Mercurial
   | GnuArch
   | Bazaar
   | Monotone
   | OtherRepoType Text
     deriving (Int -> RepoType -> ShowS
[RepoType] -> ShowS
RepoType -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [RepoType] -> ShowS
$cshowList :: [RepoType] -> ShowS
show :: RepoType -> [Char]
$cshow :: RepoType -> [Char]
showsPrec :: Int -> RepoType -> ShowS
$cshowsPrec :: Int -> RepoType -> ShowS
Show,RepoType -> RepoType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RepoType -> RepoType -> Bool
$c/= :: RepoType -> RepoType -> Bool
== :: RepoType -> RepoType -> Bool
$c== :: RepoType -> RepoType -> Bool
Eq,Eq RepoType
RepoType -> RepoType -> Bool
RepoType -> RepoType -> Ordering
RepoType -> RepoType -> RepoType
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
min :: RepoType -> RepoType -> RepoType
$cmin :: RepoType -> RepoType -> RepoType
max :: RepoType -> RepoType -> RepoType
$cmax :: RepoType -> RepoType -> RepoType
>= :: RepoType -> RepoType -> Bool
$c>= :: RepoType -> RepoType -> Bool
> :: RepoType -> RepoType -> Bool
$c> :: RepoType -> RepoType -> Bool
<= :: RepoType -> RepoType -> Bool
$c<= :: RepoType -> RepoType -> Bool
< :: RepoType -> RepoType -> Bool
$c< :: RepoType -> RepoType -> Bool
compare :: RepoType -> RepoType -> Ordering
$ccompare :: RepoType -> RepoType -> Ordering
Ord)

-- | Represents the information contained in cabal's @plan.json@ file.
--
-- This comprises basic information describing the environment as well
-- as the install/build plan computed by @cabal@.
data PlanJson = PlanJson
     { PlanJson -> Ver
pjCabalVersion    :: !Ver                     -- ^ Version of @cabal@ frontend
     , PlanJson -> Ver
pjCabalLibVersion :: !Ver                     -- ^ Version of Cabal library
     , PlanJson -> PkgId
pjCompilerId      :: !PkgId                   -- ^ Name and version of Haskell compiler
     , PlanJson -> Text
pjArch            :: !Text                    -- ^ Architecture name
     , PlanJson -> Text
pjOs              :: !Text                    -- ^ Operating system name
     , PlanJson -> Map UnitId Unit
pjUnits           :: !(M.Map UnitId Unit) -- ^ install/build plan
     } deriving Int -> PlanJson -> ShowS
[PlanJson] -> ShowS
PlanJson -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [PlanJson] -> ShowS
$cshowList :: [PlanJson] -> ShowS
show :: PlanJson -> [Char]
$cshow :: PlanJson -> [Char]
showsPrec :: Int -> PlanJson -> ShowS
$cshowsPrec :: Int -> PlanJson -> ShowS
Show

-- | Describes kind of build unit and its provenance
data UnitType = UnitTypeBuiltin -- ^ Lives in global (non-nix-style) package db
              | UnitTypeGlobal  -- ^ Lives in Nix-store cache
              | UnitTypeLocal   -- ^ Local package
              | UnitTypeInplace -- ^ Local in-place package
              deriving (Int -> UnitType -> ShowS
[UnitType] -> ShowS
UnitType -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [UnitType] -> ShowS
$cshowList :: [UnitType] -> ShowS
show :: UnitType -> [Char]
$cshow :: UnitType -> [Char]
showsPrec :: Int -> UnitType -> ShowS
$cshowsPrec :: Int -> UnitType -> ShowS
Show,UnitType -> UnitType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UnitType -> UnitType -> Bool
$c/= :: UnitType -> UnitType -> Bool
== :: UnitType -> UnitType -> Bool
$c== :: UnitType -> UnitType -> Bool
Eq)

-- | Represents a build-plan unit uniquely identified by its 'UnitId'
data Unit = Unit
     { Unit -> UnitId
uId          :: !UnitId      -- ^ Unit ID uniquely identifying a 'Unit' in install plan
     , Unit -> PkgId
uPId         :: !PkgId       -- ^ Package name and version (not necessarily unique within plan)
     , Unit -> UnitType
uType        :: !UnitType      -- ^ Describes type of build item, see 'UnitType'
     , Unit -> Maybe Sha256
uSha256      :: !(Maybe Sha256) -- ^ SHA256 source tarball checksum (as used by e.g. @hackage-security@)
     , Unit -> Maybe Sha256
uCabalSha256 :: !(Maybe Sha256) -- ^ SHA256 package description metadata checksum
        --
        -- In other words, the checksum of the @.cabal@ file that was used as input to the build planning
        --
        -- __NOTE__: This meta-information is available only for 'pjCabalVersion' >= 2.4.1.0
        --
        -- @since 0.5.0.0
     , Unit -> Map CompName CompInfo
uComps       :: !(Map CompName CompInfo) -- ^ Components identified by 'UnitId'
       --
       -- When @cabal@ needs to fall back to legacy-mode (currently for
       -- @custom@ build-types or obsolete @cabal-version@ values), 'uComps'
       -- may contain more than one element.
     , Unit -> Map FlagName Bool
uFlags       :: !(Map FlagName Bool) -- ^ cabal flag settings (not available for 'UnitTypeBuiltin')
     , Unit -> Maybe [Char]
uDistDir     :: !(Maybe FilePath) -- ^ In-place dist-dir (if available)
                                     --
                                     -- @since 0.3.0.0
     , Unit -> Maybe PkgLoc
uPkgSrc      :: !(Maybe PkgLoc)
       -- ^ Source of the package
       --
       -- __NOTE__: This meta-information is available only for 'pjCabalVersion' >= 2.4.0.0
       --
       -- @since 0.5.0.0
     } deriving Int -> Unit -> ShowS
[Unit] -> ShowS
Unit -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [Unit] -> ShowS
$cshowList :: [Unit] -> ShowS
show :: Unit -> [Char]
$cshow :: Unit -> [Char]
showsPrec :: Int -> Unit -> ShowS
$cshowsPrec :: Int -> Unit -> ShowS
Show

-- | Component name inside a build-plan unit
--
-- A similiar type exists in @Cabal@ codebase, see
-- @Distribution.Simple.LocalBuildInfo.ComponentName@
data CompName =
    CompNameLib
  | CompNameSubLib !Text
  | CompNameFLib   !Text -- ^ @since 0.3.0.0
  | CompNameExe    !Text
  | CompNameTest   !Text
  | CompNameBench  !Text
  | CompNameSetup
  deriving (Int -> CompName -> ShowS
[CompName] -> ShowS
CompName -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [CompName] -> ShowS
$cshowList :: [CompName] -> ShowS
show :: CompName -> [Char]
$cshow :: CompName -> [Char]
showsPrec :: Int -> CompName -> ShowS
$cshowsPrec :: Int -> CompName -> ShowS
Show, CompName -> CompName -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CompName -> CompName -> Bool
$c/= :: CompName -> CompName -> Bool
== :: CompName -> CompName -> Bool
$c== :: CompName -> CompName -> Bool
Eq, Eq CompName
CompName -> CompName -> Bool
CompName -> CompName -> Ordering
CompName -> CompName -> CompName
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
min :: CompName -> CompName -> CompName
$cmin :: CompName -> CompName -> CompName
max :: CompName -> CompName -> CompName
$cmax :: CompName -> CompName -> CompName
>= :: CompName -> CompName -> Bool
$c>= :: CompName -> CompName -> Bool
> :: CompName -> CompName -> Bool
$c> :: CompName -> CompName -> Bool
<= :: CompName -> CompName -> Bool
$c<= :: CompName -> CompName -> Bool
< :: CompName -> CompName -> Bool
$c< :: CompName -> CompName -> Bool
compare :: CompName -> CompName -> Ordering
$ccompare :: CompName -> CompName -> Ordering
Ord)

-- | Describes component-specific information inside a 'Unit'
data CompInfo = CompInfo
    { CompInfo -> Set UnitId
ciLibDeps :: Set UnitId     -- ^ library dependencies
    , CompInfo -> Set UnitId
ciExeDeps :: Set UnitId     -- ^ executable dependencies
    , CompInfo -> Maybe [Char]
ciBinFile :: Maybe FilePath -- ^ path-name of artifact if available
    } deriving Int -> CompInfo -> ShowS
[CompInfo] -> ShowS
CompInfo -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [CompInfo] -> ShowS
$cshowList :: [CompInfo] -> ShowS
show :: CompInfo -> [Char]
$cshow :: CompInfo -> [Char]
showsPrec :: Int -> CompInfo -> ShowS
$cshowsPrec :: Int -> CompInfo -> ShowS
Show

----------------------------------------------------------------------------
----------------------------------------------------------------------------
----------------------------------------------------------------------------

-- JSON instances

instance FromJSON CompName where
    parseJSON :: Value -> Parser CompName
parseJSON = forall a. [Char] -> (Text -> Parser a) -> Value -> Parser a
withText [Char]
"CompName" (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"invalid CompName") forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe CompName
parseCompName)

instance ToJSON CompName where
    toJSON :: CompName -> Value
toJSON     = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. CompName -> Text
dispCompName

instance FromJSONKey CompName where
    fromJSONKey :: FromJSONKeyFunction CompName
fromJSONKey = forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"CompName") forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe CompName
parseCompName)

instance ToJSONKey   CompName where
    toJSONKey :: ToJSONKeyFunction CompName
toJSONKey = forall a. (a -> Text) -> ToJSONKeyFunction a
toJSONKeyText CompName -> Text
dispCompName

----

instance FromJSON CompInfo where
    parseJSON :: Value -> Parser CompInfo
parseJSON = forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"CompInfo" forall a b. (a -> b) -> a -> b
$ \Object
o ->
        Set UnitId -> Set UnitId -> Maybe [Char] -> CompInfo
CompInfo forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. (FromJSON a, Monoid a) => Object -> Text -> Parser a
.:?! Text
"depends"
                 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. (FromJSON a, Monoid a) => Object -> Text -> Parser a
.:?! Text
"exe-depends"
                 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"bin-file"

----

instance FromJSON PkgId where
    parseJSON :: Value -> Parser PkgId
parseJSON = forall a. [Char] -> (Text -> Parser a) -> Value -> Parser a
withText [Char]
"PkgId" (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"invalid PkgId") forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe PkgId
parsePkgId)

instance ToJSON PkgId where
    toJSON :: PkgId -> Value
toJSON = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. PkgId -> Text
dispPkgId

instance FromJSONKey PkgId where
    fromJSONKey :: FromJSONKeyFunction PkgId
fromJSONKey = forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"PkgId") forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe PkgId
parsePkgId)

instance ToJSONKey PkgId where
    toJSONKey :: ToJSONKeyFunction PkgId
toJSONKey = forall a. (a -> Text) -> ToJSONKeyFunction a
toJSONKeyText PkgId -> Text
dispPkgId

----

instance FromJSON PkgLoc where
    parseJSON :: Value -> Parser PkgLoc
parseJSON = forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"PkgSrc" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Text
ty <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
        case Text
ty :: Text of
          Text
"local"       -> [Char] -> PkgLoc
LocalUnpackedPackage    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"path"
          Text
"local-tar"   -> [Char] -> PkgLoc
LocalTarballPackage     forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"path"
          Text
"remote-tar"  -> URI -> PkgLoc
RemoteTarballPackage    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"uri"
          Text
"repo-tar"    -> Repo -> PkgLoc
RepoTarballPackage      forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"repo"
          Text
"source-repo" -> SourceRepo -> PkgLoc
RemoteSourceRepoPackage forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"source-repo"
          Text
_             -> forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"invalid PkgSrc \"type\""

instance FromJSON Repo where
    parseJSON :: Value -> Parser Repo
parseJSON = forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"Repo" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Text
ty <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
        case Text
ty :: Text of
          Text
"local-repo"          -> [Char] -> Repo
RepoLocal        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"path"
          Text
"remote-repo"         -> URI -> Repo
RepoRemote       forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"uri"
          Text
"secure-repo"         -> URI -> Repo
RepoSecure       forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"uri"
          Text
"local-repo-no-index" -> [Char] -> Repo
RepoLocalNoIndex forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"path"
          Text
_                     -> forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"invalid Repo \"type\""

instance FromJSON SourceRepo where
    parseJSON :: Value -> Parser SourceRepo
parseJSON = forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"SourceRepo" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Maybe RepoType
-> Maybe Text
-> Maybe Text
-> Maybe Text
-> Maybe Text
-> Maybe [Char]
-> SourceRepo
SourceRepo forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"type"
                   forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"location"
                   forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"module"
                   forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"branch"
                   forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"tag"
                   forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"subdir"

instance FromJSON RepoType where
    parseJSON :: Value -> Parser RepoType
parseJSON = forall a. [Char] -> (Text -> Parser a) -> Value -> Parser a
withText [Char]
"RepoType" forall a b. (a -> b) -> a -> b
$ \Text
ty -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
        case Text
ty of
          Text
"darcs"     -> RepoType
Darcs
          Text
"git"       -> RepoType
Git
          Text
"svn"       -> RepoType
SVN
          Text
"cvs"       -> RepoType
CVS
          Text
"mercurial" -> RepoType
Mercurial
          Text
"gnuarch"   -> RepoType
GnuArch
          Text
"bazaar"    -> RepoType
Bazaar
          Text
"monotone"  -> RepoType
Monotone
          Text
_           -> Text -> RepoType
OtherRepoType Text
ty

----------------------------------------------------------------------------
-- parser helpers

parseCompName :: Text -> Maybe CompName
parseCompName :: Text -> Maybe CompName
parseCompName Text
t0 = case Text -> Text -> [Text]
T.splitOn Text
":" Text
t0 of
                     [Text
"lib"]     -> forall a. a -> Maybe a
Just CompName
CompNameLib
                     [Text
"lib",Text
n]   -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$! Text -> CompName
CompNameSubLib Text
n
                     [Text
"flib",Text
n]  -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$! Text -> CompName
CompNameFLib Text
n
                     [Text
"exe",Text
n]   -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$! Text -> CompName
CompNameExe Text
n
                     [Text
"bench",Text
n] -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$! Text -> CompName
CompNameBench Text
n
                     [Text
"test",Text
n]  -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$! Text -> CompName
CompNameTest Text
n
                     [Text
"setup"]   -> forall a. a -> Maybe a
Just CompName
CompNameSetup
                     [Text]
_           -> forall a. Maybe a
Nothing

-- | Pretty print 'CompName' in cabal's target-selector syntax.
--
-- @since 0.5.0.0
dispCompNameTarget :: PkgName -> CompName -> Text
dispCompNameTarget :: PkgName -> CompName -> Text
dispCompNameTarget (PkgName Text
pkg) CompName
cn = case CompName
cn of
    CompName
CompNameLib -> Text
"lib:" forall a. Semigroup a => a -> a -> a
<> Text
pkg
    CompName
_           -> CompName -> Text
dispCompName CompName
cn

-- | Pretty print 'CompName' in the same syntax that is used in
-- @plan.json@. Note that this string can not be used as a target-selector on
-- the cabal command-line. See 'dispCompNameTarget' for a target-selector
-- compatible pretty printer.
dispCompName :: CompName -> Text
dispCompName :: CompName -> Text
dispCompName CompName
cn = case CompName
cn of
    CompName
CompNameLib      -> Text
"lib"
    CompNameSubLib Text
n -> Text
"lib:" forall a. Semigroup a => a -> a -> a
<> Text
n
    CompNameFLib Text
n   -> Text
"flib:" forall a. Semigroup a => a -> a -> a
<> Text
n
    CompNameExe Text
n    -> Text
"exe:" forall a. Semigroup a => a -> a -> a
<> Text
n
    CompNameBench Text
n  -> Text
"bench:" forall a. Semigroup a => a -> a -> a
<> Text
n
    CompNameTest Text
n   -> Text
"test:" forall a. Semigroup a => a -> a -> a
<> Text
n
    CompName
CompNameSetup    -> Text
"setup"

instance FromJSON PlanJson where
    parseJSON :: Value -> Parser PlanJson
parseJSON = forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"PlanJson" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Ver
pjCabalVersion    <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"cabal-version"

        forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Ver
pjCabalVersion forall a. Ord a => a -> a -> Bool
>= [Int] -> Ver
Ver [Int
2]) forall a b. (a -> b) -> a -> b
$
            forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char]
"plan.json version " forall a. [a] -> [a] -> [a]
++ Text -> [Char]
T.unpack (Ver -> Text
dispVer Ver
pjCabalVersion) forall a. [a] -> [a] -> [a]
++ [Char]
" not supported")

        Ver
pjCabalLibVersion <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"cabal-lib-version"
        PkgId
pjCompilerId      <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"compiler-id"
        Text
pjArch            <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"arch"
        Text
pjOs              <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"os"
        Map UnitId Unit
pjUnits           <- forall {m :: * -> *}. MonadFail m => [Unit] -> m (Map UnitId Unit)
toMap forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"install-plan"

        forall (f :: * -> *) a. Applicative f => a -> f a
App.pure PlanJson{Text
Map UnitId Unit
PkgId
Ver
pjUnits :: Map UnitId Unit
pjOs :: Text
pjArch :: Text
pjCompilerId :: PkgId
pjCabalLibVersion :: Ver
pjCabalVersion :: Ver
pjUnits :: Map UnitId Unit
pjOs :: Text
pjArch :: Text
pjCompilerId :: PkgId
pjCabalLibVersion :: Ver
pjCabalVersion :: Ver
..}
      where
        toMap :: [Unit] -> m (Map UnitId Unit)
toMap [Unit]
pil = do
            let pim :: Map UnitId Unit
pim = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ (Unit -> UnitId
uId Unit
pi',Unit
pi') | Unit
pi' <- [Unit]
pil ]
            forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall k a. Map k a -> Int
M.size Map UnitId Unit
pim forall a. Eq a => a -> a -> Bool
== forall (t :: * -> *) a. Foldable t => t a -> Int
length [Unit]
pil) forall a b. (a -> b) -> a -> b
$
                forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"install-plan[] has duplicate ids"
            forall (f :: * -> *) a. Applicative f => a -> f a
pure Map UnitId Unit
pim

(.:?!) :: (FromJSON a, Monoid a) => Object -> Text -> Parser a
Object
o .:?! :: forall a. (FromJSON a, Monoid a) => Object -> Text -> Parser a
.:?! Text
fld = Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Text -> Key
fT Text
fld forall a. Parser (Maybe a) -> a -> Parser a
.!= forall a. Monoid a => a
Data.Monoid.mempty
  where
#if MIN_VERSION_aeson(2,0,0)
    fT :: Text -> Key
fT = Text -> Key
AK.fromText
#else
    fT = id   
#endif

planItemAllDeps :: Unit -> Set UnitId
planItemAllDeps :: Unit -> Set UnitId
planItemAllDeps Unit{Maybe [Char]
Maybe PkgLoc
Maybe Sha256
Map CompName CompInfo
Map FlagName Bool
UnitType
PkgId
UnitId
uPkgSrc :: Maybe PkgLoc
uDistDir :: Maybe [Char]
uFlags :: Map FlagName Bool
uComps :: Map CompName CompInfo
uCabalSha256 :: Maybe Sha256
uSha256 :: Maybe Sha256
uType :: UnitType
uPId :: PkgId
uId :: UnitId
uPkgSrc :: Unit -> Maybe PkgLoc
uDistDir :: Unit -> Maybe [Char]
uFlags :: Unit -> Map FlagName Bool
uComps :: Unit -> Map CompName CompInfo
uCabalSha256 :: Unit -> Maybe Sha256
uSha256 :: Unit -> Maybe Sha256
uType :: Unit -> UnitType
uPId :: Unit -> PkgId
uId :: Unit -> UnitId
..} = forall a. Monoid a => [a] -> a
mconcat [ Set UnitId
ciLibDeps forall a. Semigroup a => a -> a -> a
<> Set UnitId
ciExeDeps | CompInfo{Maybe [Char]
Set UnitId
ciBinFile :: Maybe [Char]
ciExeDeps :: Set UnitId
ciLibDeps :: Set UnitId
ciBinFile :: CompInfo -> Maybe [Char]
ciExeDeps :: CompInfo -> Set UnitId
ciLibDeps :: CompInfo -> Set UnitId
..} <- forall k a. Map k a -> [a]
M.elems Map CompName CompInfo
uComps ]

instance FromJSON Unit where
    parseJSON :: Value -> Parser Unit
parseJSON = forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"Unit" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Maybe (Map CompName CompInfo)
mcomponents    <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"components"
        Maybe CompName
mcomponentname <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"component-name"
        Text
ty             <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.:  Key
"type"
        Maybe Text
mstyle         <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"style"

        UnitId
uId     <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id"
        PkgId
uPId    <- PkgName -> Ver -> PkgId
PkgId forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"pkg-name" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"pkg-version"
        UnitType
uType   <- case (Text
ty :: Text, Maybe Text
mstyle :: Maybe Text) of
                   (Text
"pre-existing",Maybe Text
Nothing)      -> forall (f :: * -> *) a. Applicative f => a -> f a
pure UnitType
UnitTypeBuiltin
                   (Text
"configured",Just Text
"global")  -> forall (f :: * -> *) a. Applicative f => a -> f a
pure UnitType
UnitTypeGlobal
                   (Text
"configured",Just Text
"local")   -> forall (f :: * -> *) a. Applicative f => a -> f a
pure UnitType
UnitTypeLocal
                   (Text
"configured",Just Text
"inplace") -> forall (f :: * -> *) a. Applicative f => a -> f a
pure UnitType
UnitTypeInplace
                   (Text, Maybe Text)
_                             -> forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail (forall a. Show a => a -> [Char]
show (Text
ty,Maybe Text
mstyle))
        Map FlagName Bool
uFlags  <- Object
o forall a. (FromJSON a, Monoid a) => Object -> Text -> Parser a
.:?! Text
"flags"
        Maybe Sha256
uSha256 <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"pkg-src-sha256"
        Maybe Sha256
uCabalSha256 <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"pkg-cabal-sha256"
        Map CompName CompInfo
uComps  <- case (Maybe (Map CompName CompInfo)
mcomponents, Maybe CompName
mcomponentname) of
          (Just Map CompName CompInfo
comps0, Maybe CompName
Nothing) ->
              forall (f :: * -> *) a. Applicative f => a -> f a
pure Map CompName CompInfo
comps0
          (Maybe (Map CompName CompInfo)
Nothing, Just CompName
cname) ->
              forall k a. k -> a -> Map k a
M.singleton CompName
cname forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
          (Maybe (Map CompName CompInfo)
Nothing, Maybe CompName
Nothing) | UnitType
uType forall a. Eq a => a -> a -> Bool
== UnitType
UnitTypeBuiltin ->
              forall k a. k -> a -> Map k a
M.singleton CompName
CompNameLib forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
          (Maybe (Map CompName CompInfo), Maybe CompName)
_ -> forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail (forall a. Show a => a -> [Char]
show Object
o)

        Maybe [Char]
uDistDir <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"dist-dir"

        Maybe PkgLoc
uPkgSrc <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"pkg-src"

        forall (f :: * -> *) a. Applicative f => a -> f a
pure Unit{Maybe [Char]
Maybe PkgLoc
Maybe Sha256
Map CompName CompInfo
Map FlagName Bool
UnitType
PkgId
UnitId
uPkgSrc :: Maybe PkgLoc
uDistDir :: Maybe [Char]
uComps :: Map CompName CompInfo
uCabalSha256 :: Maybe Sha256
uSha256 :: Maybe Sha256
uFlags :: Map FlagName Bool
uType :: UnitType
uPId :: PkgId
uId :: UnitId
uPkgSrc :: Maybe PkgLoc
uDistDir :: Maybe [Char]
uFlags :: Map FlagName Bool
uComps :: Map CompName CompInfo
uCabalSha256 :: Maybe Sha256
uSha256 :: Maybe Sha256
uType :: UnitType
uPId :: PkgId
uId :: UnitId
..}

----------------------------------------------------------------------------
-- Convenience helper

-- | Where/how to search for the plan.json file.
data SearchPlanJson
    = ProjectRelativeToDir FilePath -- ^ Find the project root relative to
                                    --   specified directory and look for
                                    --   plan.json there.
    | InBuildDir FilePath           -- ^ Look for plan.json in specified build
                                    --   directory.
    | ExactPath FilePath            -- ^ Exact location of plan.json
    deriving (SearchPlanJson -> SearchPlanJson -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SearchPlanJson -> SearchPlanJson -> Bool
$c/= :: SearchPlanJson -> SearchPlanJson -> Bool
== :: SearchPlanJson -> SearchPlanJson -> Bool
$c== :: SearchPlanJson -> SearchPlanJson -> Bool
Eq, Int -> SearchPlanJson -> ShowS
[SearchPlanJson] -> ShowS
SearchPlanJson -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [SearchPlanJson] -> ShowS
$cshowList :: [SearchPlanJson] -> ShowS
show :: SearchPlanJson -> [Char]
$cshow :: SearchPlanJson -> [Char]
showsPrec :: Int -> SearchPlanJson -> ShowS
$cshowsPrec :: Int -> SearchPlanJson -> ShowS
Show, ReadPrec [SearchPlanJson]
ReadPrec SearchPlanJson
Int -> ReadS SearchPlanJson
ReadS [SearchPlanJson]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SearchPlanJson]
$creadListPrec :: ReadPrec [SearchPlanJson]
readPrec :: ReadPrec SearchPlanJson
$creadPrec :: ReadPrec SearchPlanJson
readList :: ReadS [SearchPlanJson]
$creadList :: ReadS [SearchPlanJson]
readsPrec :: Int -> ReadS SearchPlanJson
$creadsPrec :: Int -> ReadS SearchPlanJson
Read)

-- | Find and decode @plan.json@.
--
-- See 'findPlanJson' and 'decodePlanJson'.
--
findAndDecodePlanJson
    :: SearchPlanJson
    -> IO PlanJson
findAndDecodePlanJson :: SearchPlanJson -> IO PlanJson
findAndDecodePlanJson SearchPlanJson
searchLoc = SearchPlanJson -> IO [Char]
findPlanJson SearchPlanJson
searchLoc forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [Char] -> IO PlanJson
decodePlanJson

-- | Find @plan.json@.
--
-- When 'ProjectRelativeToDir' is passed locates the project root for cabal
-- project relative to specified directory.
--
-- @plan.json@ is located from either the optional build dir argument, or in
-- the default directory (@dist-newstyle@) relative to the project root.
--
-- This function determines the project root in a slightly more liberal manner
-- than cabal-install. If no cabal.project is found, cabal-install assumes an
-- implicit cabal.project if the current directory contains any *.cabal files.
--
-- This function looks for any *.cabal files in directories above the current
-- one and behaves as if there is an implicit cabal.project in that directory
-- when looking for a plan.json.
--
-- Throws 'IO' exceptions on errors.
--
-- @since 0.6.2.0
--
findPlanJson
    :: SearchPlanJson
    -> IO FilePath
findPlanJson :: SearchPlanJson -> IO [Char]
findPlanJson SearchPlanJson
searchLoc = do
    [Char]
planJsonFn <- case SearchPlanJson
searchLoc of
        ExactPath [Char]
fp -> forall (f :: * -> *) a. Applicative f => a -> f a
pure [Char]
fp
        InBuildDir [Char]
builddir -> [Char] -> IO [Char]
fromBuilddir [Char]
builddir
        ProjectRelativeToDir [Char]
fp -> do
            Maybe [Char]
mRoot <- [Char] -> IO (Maybe [Char])
findProjectRoot [Char]
fp
            case Maybe [Char]
mRoot of
                Maybe [Char]
Nothing  -> forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char]
"missing project root relative to: " forall a. [a] -> [a] -> [a]
++ [Char]
fp)
                Just [Char]
dir -> [Char] -> IO [Char]
fromBuilddir forall a b. (a -> b) -> a -> b
$ [Char]
dir [Char] -> ShowS
</> [Char]
"dist-newstyle"

    Bool
havePlanJson <- [Char] -> IO Bool
Dir.doesFileExist [Char]
planJsonFn

    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
havePlanJson forall a b. (a -> b) -> a -> b
$
        forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"missing 'plan.json' file; do you need to run 'cabal new-build'?"

    forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
planJsonFn  
  where
    fromBuilddir :: [Char] -> IO [Char]
fromBuilddir [Char]
distFolder = do
        Bool
haveDistFolder <- [Char] -> IO Bool
Dir.doesDirectoryExist [Char]
distFolder

        forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
haveDistFolder forall a b. (a -> b) -> a -> b
$
            forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char]
"missing " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show [Char]
distFolder forall a. [a] -> [a] -> [a]
++ [Char]
" folder; do you need to run 'cabal new-build'?")

        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ [Char]
distFolder [Char] -> ShowS
</> [Char]
"cache" [Char] -> ShowS
</> [Char]
"plan.json"

-- | Decodes @plan.json@ file location provided as 'FilePath'
--
-- This is a trivial convenience function so that the caller doesn't
-- have to depend on @aeson@ directly
--
-- Throws 'IO' exceptions on errors.
--
decodePlanJson :: FilePath -> IO PlanJson
decodePlanJson :: [Char] -> IO PlanJson
decodePlanJson [Char]
planJsonFn = do
    ByteString
jsraw <- [Char] -> IO ByteString
B.readFile [Char]
planJsonFn
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. FromJSON a => ByteString -> Either [Char] a
eitherDecodeStrict' ByteString
jsraw

-- | Find project root relative to a directory, this emulates cabal's current
-- heuristic, but is slightly more liberal. If no cabal.project is found,
-- cabal-install looks for *.cabal files in the specified directory only. This
-- function also considers *.cabal files in directories higher up in the
-- hierarchy.
findProjectRoot :: FilePath -> IO (Maybe FilePath)
findProjectRoot :: [Char] -> IO (Maybe [Char])
findProjectRoot [Char]
dir = do
    [Char]
normalisedPath <- [Char] -> IO [Char]
Dir.canonicalizePath [Char]
dir
    let checkCabalProject :: [Char] -> IO (Maybe [Char])
checkCabalProject [Char]
d = do
            Bool
ex <- [Char] -> IO Bool
Dir.doesFileExist [Char]
fn
            forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if Bool
ex then forall a. a -> Maybe a
Just [Char]
d else forall a. Maybe a
Nothing
          where
            fn :: [Char]
fn = [Char]
d [Char] -> ShowS
</> [Char]
"cabal.project"

        checkCabal :: [Char] -> IO (Maybe [Char])
checkCabal [Char]
d = do
            [[Char]]
files <- [Char] -> IO [[Char]]
listDirectory [Char]
d
            forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ([Char] -> [Char] -> Bool
isExtensionOf [Char]
".cabal") [[Char]]
files
                        then forall a. a -> Maybe a
Just [Char]
d
                        else forall a. Maybe a
Nothing

    Maybe [Char]
result <- forall a. ([Char] -> IO (Maybe a)) -> [Char] -> IO (Maybe a)
walkUpFolders [Char] -> IO (Maybe [Char])
checkCabalProject [Char]
normalisedPath
    case Maybe [Char]
result of
        Just [Char]
rootDir -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just [Char]
rootDir
        Maybe [Char]
Nothing      -> forall a. ([Char] -> IO (Maybe a)) -> [Char] -> IO (Maybe a)
walkUpFolders [Char] -> IO (Maybe [Char])
checkCabal [Char]
normalisedPath
  where
    isExtensionOf :: String -> FilePath -> Bool
    isExtensionOf :: [Char] -> [Char] -> Bool
isExtensionOf [Char]
ext [Char]
fp = [Char]
ext forall a. Eq a => a -> a -> Bool
== ShowS
takeExtension [Char]
fp

    listDirectory :: FilePath -> IO [FilePath]
    listDirectory :: [Char] -> IO [[Char]]
listDirectory [Char]
fp = forall a. (a -> Bool) -> [a] -> [a]
filter forall {a}. (Eq a, IsString a) => a -> Bool
isSpecialDir forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO [[Char]]
Dir.getDirectoryContents [Char]
fp
      where
        isSpecialDir :: a -> Bool
isSpecialDir a
f = a
f forall a. Eq a => a -> a -> Bool
/= a
"." Bool -> Bool -> Bool
&& a
f forall a. Eq a => a -> a -> Bool
/= a
".."

walkUpFolders
    :: (FilePath -> IO (Maybe a)) -> FilePath -> IO (Maybe a)
walkUpFolders :: forall a. ([Char] -> IO (Maybe a)) -> [Char] -> IO (Maybe a)
walkUpFolders [Char] -> IO (Maybe a)
dtest [Char]
d0 = do
    [Char]
home <- IO [Char]
Dir.getHomeDirectory

    let go :: [Char] -> IO (Maybe a)
go [Char]
d | [Char]
d forall a. Eq a => a -> a -> Bool
== [Char]
home  = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing
             | [Char] -> Bool
isDrive [Char]
d  = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing
             | Bool
otherwise  = do
                   Maybe a
t <- [Char] -> IO (Maybe a)
dtest [Char]
d
                   case Maybe a
t of
                     Maybe a
Nothing  -> [Char] -> IO (Maybe a)
go forall a b. (a -> b) -> a -> b
$ ShowS
takeDirectory [Char]
d
                     x :: Maybe a
x@Just{} -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
x

    [Char] -> IO (Maybe a)
go [Char]
d0

parseVer :: Text -> Maybe Ver
parseVer :: Text -> Maybe Ver
parseVer Text
str = case forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall a. ReadP a -> ReadS a
readP_to_S ReadP Version
DV.parseVersion (Text -> [Char]
T.unpack Text
str) of
  (Version
ver, [Char]
"") : [(Version, [Char])]
_ | Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null (Version -> [Int]
DV.versionBranch Version
ver)), forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall a. Ord a => a -> a -> Bool
>= Int
0) (Version -> [Int]
DV.versionBranch Version
ver)
      -> forall a. a -> Maybe a
Just ([Int] -> Ver
Ver forall a b. (a -> b) -> a -> b
$ Version -> [Int]
DV.versionBranch Version
ver)
  [(Version, [Char])]
_   -> forall a. Maybe a
Nothing

-- | Pretty print 'Ver'
dispVer :: Ver -> Text
dispVer :: Ver -> Text
dispVer (Ver [Int]
ns) = [Char] -> Text
T.pack forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"." (forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> [Char]
show [Int]
ns)

instance FromJSON Ver where
    parseJSON :: Value -> Parser Ver
parseJSON = forall a. [Char] -> (Text -> Parser a) -> Value -> Parser a
withText [Char]
"Ver" (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"Ver") forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe Ver
parseVer)

instance ToJSON Ver where
    toJSON :: Ver -> Value
toJSON = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ver -> Text
dispVer

parsePkgId :: Text -> Maybe PkgId
parsePkgId :: Text -> Maybe PkgId
parsePkgId Text
t = do
  let (Text
pns_, Text
pvs) = Text -> Text -> (Text, Text)
T.breakOnEnd Text
"-" Text
t
  Ver
pv <- Text -> Maybe Ver
parseVer Text
pvs

  Text
pn <- Text -> Text -> Maybe Text
T.stripSuffix Text
"-" Text
pns_

  -- TODO: validate pn
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (PkgName -> Ver -> PkgId
PkgId (Text -> PkgName
PkgName Text
pn) Ver
pv)

-- | Pretty print 'PkgId'
dispPkgId :: PkgId -> Text
dispPkgId :: PkgId -> Text
dispPkgId (PkgId (PkgName Text
pn) Ver
pv) = Text
pn forall a. Semigroup a => a -> a -> a
<> Text
"-" forall a. Semigroup a => a -> a -> a
<> Ver -> Text
dispVer Ver
pv


-- | Pretty print 'Sha256' as base-16.
dispSha256 :: Sha256 -> Text
dispSha256 :: Sha256 -> Text
dispSha256 (Sha256 ByteString
s) = ByteString -> Text
T.decodeLatin1 (ByteString -> ByteString
B16.encode ByteString
s)

-- | Parse base-16 encoded 'Sha256'.
--
-- Returns 'Nothing' in case of parsing failure.
--
-- @since 0.3.0.0
parseSha256 :: Text -> Maybe Sha256
parseSha256 :: Text -> Maybe Sha256
parseSha256 Text
t
#if MIN_VERSION_base16_bytestring(1,0,0)
  = case ByteString -> Either [Char] ByteString
B16.decode (Text -> ByteString
T.encodeUtf8 Text
t) of
      Right ByteString
s | ByteString -> Int
B.length ByteString
s forall a. Eq a => a -> a -> Bool
== Int
32 -> forall a. a -> Maybe a
Just (ByteString -> Sha256
Sha256 ByteString
s)
      Either [Char] ByteString
_                          -> forall a. Maybe a
Nothing
#else
  | B.length s == 32, B.null rest = Just (Sha256 s)
  | otherwise                     = Nothing
  where
    (s, rest) = B16.decode $ T.encodeUtf8 t
#endif

-- | Export the 'Sha256' digest to a 32-byte 'B.ByteString'.
--
-- @since 0.3.0.0
sha256ToByteString :: Sha256 -> B.ByteString
sha256ToByteString :: Sha256 -> ByteString
sha256ToByteString (Sha256 ByteString
bs) = ByteString
bs

-- | Import the 'Sha256' digest from a 32-byte 'B.ByteString'.
--
-- Returns 'Nothing' if input 'B.ByteString' has incorrect length.
--
-- @since 0.3.0.0
sha256FromByteString :: B.ByteString -> Maybe Sha256
sha256FromByteString :: ByteString -> Maybe Sha256
sha256FromByteString ByteString
bs
  | ByteString -> Int
B.length ByteString
bs forall a. Eq a => a -> a -> Bool
== Int
32  = forall a. a -> Maybe a
Just (ByteString -> Sha256
Sha256 ByteString
bs)
  | Bool
otherwise          = forall a. Maybe a
Nothing

instance FromJSON Sha256 where
    parseJSON :: Value -> Parser Sha256
parseJSON = forall a. [Char] -> (Text -> Parser a) -> Value -> Parser a
withText [Char]
"Sha256" (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail [Char]
"Sha256") forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe Sha256
parseSha256)

instance ToJSON Sha256 where
    toJSON :: Sha256 -> Value
toJSON = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sha256 -> Text
dispSha256

instance Show Sha256 where
    show :: Sha256 -> [Char]
show = forall a. Show a => a -> [Char]
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sha256 -> Text
dispSha256

----------------------------------------------------------------------------

-- | Extract directed 'UnitId' dependency graph edges from 'pjUnits'
--
-- This graph contains both, library and executable dependencies edges
planJsonIdGraph :: PlanJson -> Map UnitId (Set UnitId)
planJsonIdGraph :: PlanJson -> Map UnitId (Set UnitId)
planJsonIdGraph PlanJson{Text
Map UnitId Unit
PkgId
Ver
pjUnits :: Map UnitId Unit
pjOs :: Text
pjArch :: Text
pjCompilerId :: PkgId
pjCabalLibVersion :: Ver
pjCabalVersion :: Ver
pjUnits :: PlanJson -> Map UnitId Unit
pjOs :: PlanJson -> Text
pjArch :: PlanJson -> Text
pjCompilerId :: PlanJson -> PkgId
pjCabalLibVersion :: PlanJson -> Ver
pjCabalVersion :: PlanJson -> Ver
..} = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [ (Unit -> UnitId
uId Unit
unit, Unit -> Set UnitId
planItemAllDeps Unit
unit)
                                          | Unit
unit <- forall k a. Map k a -> [a]
M.elems Map UnitId Unit
pjUnits
                                          ]

-- | Extract 'UnitId' root nodes from dependency graph computed by 'planJsonIdGraph'
planJsonIdRoots :: PlanJson -> Set UnitId
planJsonIdRoots :: PlanJson -> Set UnitId
planJsonIdRoots PlanJson{Text
Map UnitId Unit
PkgId
Ver
pjUnits :: Map UnitId Unit
pjOs :: Text
pjArch :: Text
pjCompilerId :: PkgId
pjCabalLibVersion :: Ver
pjCabalVersion :: Ver
pjUnits :: PlanJson -> Map UnitId Unit
pjOs :: PlanJson -> Text
pjArch :: PlanJson -> Text
pjCompilerId :: PlanJson -> PkgId
pjCabalLibVersion :: PlanJson -> Ver
pjCabalVersion :: PlanJson -> Ver
..} = forall k a. Map k a -> Set k
M.keysSet Map UnitId Unit
pjUnits forall a. Ord a => Set a -> Set a -> Set a
`S.difference` Set UnitId
nonRoots
  where
    nonRoots :: Set UnitId
    nonRoots :: Set UnitId
nonRoots = forall a. Monoid a => [a] -> a
mconcat forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [a]
M.elems forall a b. (a -> b) -> a -> b
$ PlanJson -> Map UnitId (Set UnitId)
planJsonIdGraph PlanJson{Text
Map UnitId Unit
PkgId
Ver
pjUnits :: Map UnitId Unit
pjOs :: Text
pjArch :: Text
pjCompilerId :: PkgId
pjCabalLibVersion :: Ver
pjCabalVersion :: Ver
pjUnits :: Map UnitId Unit
pjOs :: Text
pjArch :: Text
pjCompilerId :: PkgId
pjCabalLibVersion :: Ver
pjCabalVersion :: Ver
..}