{-# Language StandaloneDeriving #-} module CabalBounds.Main ( cabalBounds ) where import Distribution.PackageDescription (GenericPackageDescription) import Distribution.PackageDescription.Parse (parsePackageDescription, ParseResult(..)) import Distribution.PackageDescription.PrettyPrint (showGenericPackageDescription) import Distribution.Simple.Configure (ConfigStateFileErrorType(..), tryGetConfigStateFile) import Distribution.Simple.LocalBuildInfo (LocalBuildInfo) import qualified CabalBounds.Args as A import qualified CabalBounds.Bound as B import qualified CabalBounds.Sections as S import qualified CabalBounds.Dependencies as DP import qualified CabalBounds.Drop as D import qualified CabalBounds.Update as U import qualified System.IO.Strict as SIO import Control.Applicative ((<$>)) import Control.Monad.Trans.Either (EitherT, runEitherT, bimapEitherT, hoistEither, left, right) import Control.Monad.IO.Class type Error = String cabalBounds :: A.Args -> IO (Maybe Error) cabalBounds args@A.Drop {} = leftToJust <$> runEitherT (do pkgDescrp <- packageDescription $ A.cabalFile args let pkgDescrp' = D.drop (B.boundOfDrop args) (S.sections args pkgDescrp) (DP.dependencies args) pkgDescrp liftIO $ writeFile (A.outputFile args) (showGenericPackageDescription pkgDescrp')) cabalBounds args@A.Update {} = leftToJust <$> runEitherT (do pkgDescrp <- packageDescription $ A.cabalFile args buildInfo <- localBuildInfo $ A.setupConfigFile args let pkgDescrp' = U.update (B.boundOfUpdate args) (S.sections args pkgDescrp) (DP.dependencies args) pkgDescrp buildInfo liftIO $ writeFile (A.outputFile args) (showGenericPackageDescription pkgDescrp')) packageDescription :: FilePath -> EitherT Error IO GenericPackageDescription packageDescription file = do contents <- liftIO $ SIO.readFile file case parsePackageDescription contents of ParseFailed error -> left $ show error ParseOk _ pkgDescrp -> right pkgDescrp localBuildInfo :: FilePath -> EitherT Error IO LocalBuildInfo localBuildInfo file = do binfo <- liftIO $ tryGetConfigStateFile file bimapEitherT show id (hoistEither binfo) leftToJust :: Either a b -> Maybe a leftToJust = either Just (const Nothing) deriving instance Show ConfigStateFileErrorType