-- | Utility functions to work with 'GenericPackageDescription' and -- other miscellaneous stuff in .cabal files. module Importify.Cabal.Package ( extractFromTargets , packageDependencies , readCabal ) where import Universum hiding (fromString) import Distribution.Package (Dependency (..), unPackageName) import Distribution.PackageDescription (Benchmark (benchmarkBuildInfo), BuildInfo (..), CondTree, Executable (..), GenericPackageDescription (..), Library (..), TestSuite (testBuildInfo), condTreeData) import Distribution.PackageDescription.Parse (readPackageDescription) import Distribution.Verbosity (normal) -- | Parse 'GenericPackageDescription' from given path to .cabal file. readCabal :: MonadIO m => FilePath -> m GenericPackageDescription readCabal = liftIO . readPackageDescription normal dependencyName :: Dependency -> String dependencyName (Dependency name _) = unPackageName name -- | Retrieve list of unique names for all package dependencies inside -- library, all executables, all test suites and all benchmarks for a -- given package. packageDependencies :: GenericPackageDescription -> [String] packageDependencies = ordNub . concatMap (map dependencyName . targetBuildDepends) . allBuildInfos allBuildInfos :: GenericPackageDescription -> [BuildInfo] allBuildInfos = extractFromTargets libBuildInfo buildInfo testBuildInfo benchmarkBuildInfo -- | Extract some uniform data from every target if it's present. extractFromTargets :: (Library -> r) -- ^ 'Library' extractor -> (Executable -> r) -- ^ 'Executable' extractor -> (TestSuite -> r) -- ^ 'TestSuite' extractor -> (Benchmark -> r) -- ^ 'Benchmakr' extractor -> GenericPackageDescription -- ^ Package -> [r] -- ^ List of results collected from each target extractFromTargets fromLib fromExe fromTst fromBnc GenericPackageDescription{..} = concat [ maybe [] (one . fromLib . condTreeData) condLibrary , mapTargets fromExe condExecutables , mapTargets fromTst condTestSuites , mapTargets fromBnc condBenchmarks ] mapTargets :: (t -> r) -> [(s, CondTree v c t)] -> [r] mapTargets extractor = map (extractor . condTreeData . snd)