module Distribution.Cab.VerDB (
PkgName
, VerDB
, HowToObtain(..)
, getVerDB
, toList
, toMap
) where
import Control.Applicative
import Control.Arrow (second)
import Control.Monad.Trans.Resource (runResourceT)
import Data.Attoparsec.ByteString.Char8
import Data.Conduit.Attoparsec
import Data.Conduit.Process
import Data.Map (Map)
import qualified Data.Map as M
import Data.Maybe
import Distribution.Cab.Version
type PkgName = String
type VerInfo = (PkgName, Maybe [Int])
newtype VerDB = VerDB [(PkgName,Ver)] deriving (Eq, Show)
data HowToObtain = InstalledOnly | AllRegistered
getVerDB :: HowToObtain -> IO VerDB
getVerDB how = VerDB . justOnly <$> verInfos
where
script = case how of
InstalledOnly -> "cabal list --installed"
AllRegistered -> "cabal list"
verInfos = runResourceT $ sourceCmdWithConsumer script cabalListParser
justOnly = map (second (toVer . fromJust)) . filter (isJust . snd) . snd
cabalListParser = sinkParser verinfos
toList :: VerDB -> [(PkgName, Ver)]
toList (VerDB alist) = alist
toMap :: VerDB -> Map PkgName Ver
toMap (VerDB alist) = M.fromList alist
verinfos :: Parser [VerInfo]
verinfos = many1 verinfo
verinfo :: Parser VerInfo
verinfo = do
name <- string "* " *> nonEols <* endOfLine
synpsis
lat <- latestLabel *> latest <* endOfLine
_ <- many skip
endOfLine
return (name, lat)
where
latestLabel = string " Default available version: "
<|> string " Latest version available: "
skip = many1 nonEols *> endOfLine
synpsis = string " Synopsis:" *> nonEols *> endOfLine *> more
<|> return ()
where
more = () <$ many (string " " *> nonEols *> endOfLine)
latest = Nothing <$ (char '[' *> nonEols)
<|> Just <$> dotted
dotted :: Parser [Int]
dotted = decimal `sepBy` char '.'
nonEols :: Parser String
nonEols = many1 $ satisfy (notInClass "\r\n")