{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Distribution.Nixpkgs.Haskell.FromCabal.Configuration
( Configuration(..), readConfiguration, assertConsistency
)
where
import Control.DeepSeq
import Control.Exception ( throwIO )
import Control.Lens
import Control.Monad
import Data.Aeson
import Data.Map as Map
import Data.Set as Set
import Data.Text as T
import Data.Yaml
import Distribution.Compiler
import Distribution.Nixpkgs.Haskell.Constraint
import Distribution.Package
import Distribution.System
import GHC.Generics ( Generic )
import Language.Nix.Identifier
data Configuration = Configuration
{
compilerInfo :: CompilerInfo
, corePackages :: Set PackageIdentifier
, defaultPackageOverrides :: [Constraint]
, extraPackages :: [Constraint]
, packageMaintainers :: Map Identifier (Set PackageName)
, unsupportedPlatforms :: Map PackageName (Set Platform)
, dontDistributePackages :: Set PackageName
, brokenPackages :: [Constraint]
}
deriving (Show, Generic)
instance NFData Configuration
instance FromJSON Configuration where
parseJSON (Object o) = Configuration
<$> o .:? "compiler" .!= unknownCompilerInfo buildCompilerId NoAbiTag
<*> o .:? "core-packages" .!= mempty
<*> o .:? "default-package-overrides" .!= mempty
<*> o .:? "extra-packages" .!= mempty
<*> o .:? "package-maintainers" .!= mempty
<*> o .:? "unsupported-platforms" .!= mempty
<*> o .:? "dont-distribute-packages" .!= mempty
<*> o .:? "broken-packages" .!= mempty
parseJSON _ = error "invalid Configuration"
instance FromJSON Identifier where
parseJSON (String s) = pure (review ident (T.unpack s))
parseJSON s = fail ("parseJSON: " ++ show s ++ " is not a valid Nix identifier")
instance FromJSONKey Identifier where
fromJSONKey = FromJSONKeyText parseKey
instance FromJSONKey PackageName where
fromJSONKey = FromJSONKeyText parseKey
parseKey :: FromJSON k => Text -> k
parseKey s = either error id (parseEither parseJSON (String s))
readConfiguration :: FilePath -> IO Configuration
readConfiguration path = decodeFileEither path >>= either throwIO assertConsistency
assertConsistency :: Monad m => Configuration -> m Configuration
assertConsistency cfg@Configuration {..} = do
let report msg = fail ("*** configuration error: " ++ msg)
maintainedPackages = Set.unions (Map.elems packageMaintainers)
disabledPackages = dontDistributePackages `Set.union` Set.fromList (depPkgName <$> brokenPackages)
disabledMaintainedPackages = maintainedPackages `Set.intersection` disabledPackages
unless (Set.null disabledMaintainedPackages) $
report ("disabled packages that have a maintainer: " ++ show disabledMaintainedPackages)
return cfg