packages feed

hsinstall-2.8: src/app/HSInstall/DeploymentInfo.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}

module HSInstall.DeploymentInfo
  ( BinDir (..)
  , DeploymentInfo (..)
  , DocDir (..)
  , PrefixDir (..)
  , constructDeploymentInfo

  -- re-exporting
  , normal
  , prettyShow
  )
  where

import Control.Applicative ( (<|>) )
import Control.Monad.Trans.Maybe ( MaybeT (..), runMaybeT )
import Control.Newtype.Generics
import Data.List ( find, isSuffixOf )
import Distribution.Package
  ( PackageId
  , PackageIdentifier (pkgName, pkgVersion)
  )
import Distribution.PackageDescription
  ( GenericPackageDescription (packageDescription)
  , PackageDescription (package)
  )
import Distribution.Pretty ( prettyShow )
import Distribution.Simple.PackageDescription
  ( readGenericPackageDescription )
import Distribution.Types.PackageName ( unPackageName )
import Distribution.Types.Version ( Version )
import Distribution.Verbosity ( normal )
import GHC.Generics hiding ( Prefix )
import System.Directory ( getDirectoryContents )
import System.FilePath ( (</>), (<.>) )

import HSInstall.Build ( BuildTool, makeCabal )
import HSInstall.Common ( ExeFile (..) )
import HSInstall.Except
  ( HSInstallException (NoCabalFiles)
  , throwM
  )
import HSInstall.Opts
  ( BuildMode (AppImageExe, Project)
  , PrefixOpt (..)
  , Options (..)
  )


newtype PrefixDir = PrefixDir FilePath
  deriving Generic

instance Newtype PrefixDir

newtype BinDir = BinDir FilePath
  deriving Generic

instance Newtype BinDir

newtype DocDir = DocDir FilePath
  deriving Generic

instance Newtype DocDir

data DeploymentInfo = DeploymentInfo
  { prefixDir :: PrefixDir
  , binDir :: BinDir
  , docDir :: DocDir
  , version :: Version
  }


locateCabalFile :: IO (Maybe FilePath)
locateCabalFile = find (isSuffixOf ".cabal")
    <$> getDirectoryContents "."


constructDeploymentInfo :: BuildTool -> Options -> IO DeploymentInfo
constructDeploymentInfo buildTool opts = do
  mbCabalFile <- runMaybeT
    $   MaybeT locateCabalFile
    <|> MaybeT (makeCabal buildTool >> locateCabalFile)
  maybe (throwM NoCabalFiles)
    (fmap (constructDeploymentInfo' opts . package . packageDescription)
      . readGenericPackageDescription normal) mbCabalFile


constructDeploymentInfo' :: Options -> PackageId -> DeploymentInfo
constructDeploymentInfo' opts pkgId =
  DeploymentInfo prefixDir' (BinDir binFp)
    (DocDir $ shareFp </> "doc") (pkgVersion pkgId)

  where
    prefixDir'@(PrefixDir prefixFp) = computePrefixDir (optPrefix opts) (optBuildMode opts)
    binFp = prefixFp </> "bin"
    project = unPackageName . pkgName $ pkgId
    shareFp = prefixFp </> "share" </> project


defaultPrefix :: PrefixDir
defaultPrefix = PrefixDir $ "AppDir" </> "usr"

computePrefixDir :: PrefixOpt -> BuildMode -> PrefixDir
computePrefixDir (Prefix prefixFp) _ = PrefixDir prefixFp
computePrefixDir NoPrefixSpecified (AppImageExe (ExeFile exeFp)) =
  over PrefixDir (exeFp <.>) defaultPrefix
computePrefixDir NoPrefixSpecified Project = defaultPrefix