packages feed

sandman-0.1.0.0: Sandman/InstalledPackage.hs

{-# LANGUAGE NamedFieldPuns #-}
module Sandman.InstalledPackage (
      InstalledPackage
    , installedPackageInfo
    , installedPackageInfoPath
    , installedPackageId
    , installedPackageName
    , installedPackageVersion

    , getInstalledPackage
    ) where

import Data.Text            (Text)
import Distribution.Version (Version)
import System.Directory     (doesFileExist)

import qualified Data.Text                         as Text
import qualified Distribution.InstalledPackageInfo as Cabal
import qualified Distribution.Package              as Cabal
import qualified Distribution.Text                 as Cabal

-- | Represents a Cabal package installed somewhere in the system.
data InstalledPackage = InstalledPackage {
    installedPackageInfo     :: Cabal.InstalledPackageInfo
  -- ^ 'Cabal.InstalledPackageInfo' for the package.
  , installedPackageInfoPath :: FilePath
  -- ^ Path where the 'Cabal.InstalledPackageInfo' file is stored.
  , cabalPackageId           :: Cabal.PackageId
  -- ^ Cabal package ID
  }

-- | Get the package ID for the given InstalledPackage
installedPackageId :: InstalledPackage -> Text
installedPackageId = Text.pack . Cabal.display . cabalPackageId

-- | Get the package name
installedPackageName :: InstalledPackage -> Text
installedPackageName =
    Text.pack . Cabal.display . Cabal.pkgName . cabalPackageId

-- | Get the package version
installedPackageVersion :: InstalledPackage -> Version
installedPackageVersion = Cabal.pkgVersion . cabalPackageId

-- | Build a 'InstalledPackage' object from the given path.
--
-- Returns either an error or the 'InstalledPackage' object.
getInstalledPackage :: FilePath -> IO (Either String InstalledPackage)
getInstalledPackage path =
  doesFileExist path >>= \exists ->
    if not exists
      then return (Left $ "File does not exist: " ++ path)
      else getInstalledPackage_ path

getInstalledPackage_ :: FilePath -> IO (Either String InstalledPackage)
getInstalledPackage_ installedPackageInfoPath =
  readFile installedPackageInfoPath >>= \contents ->
    case Cabal.parseInstalledPackageInfo contents of
      Cabal.ParseFailed e -> return . Left $
          "Failed to parse " ++ installedPackageInfoPath ++ ": " ++ show e
      Cabal.ParseOk _ installedPackageInfo -> return . Right $
          InstalledPackage{
              installedPackageInfo
            , installedPackageInfoPath
            , cabalPackageId = Cabal.sourcePackageId installedPackageInfo
            }