Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: a46eb46a49
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 96 lines (77 sloc) 3.048 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
{-|
Author : Andres Loeh <kosmikus@gentoo.org>
Stability : provisional
Portability : haskell98

Version parser, according to Portage spec.

Shamelessly borrowed from exi, ported from Parsec to ReadP

-}

module Portage.Version (
    Version(..),
    Suffix(..),
    fromCabalVersion,
    toCabalVersion,
    is_live
  ) where

import qualified Distribution.Version as Cabal

import Distribution.Text (Text(..))

import qualified Distribution.Compat.ReadP as Parse
import qualified Text.PrettyPrint as Disp
import Text.PrettyPrint ((<>))
import qualified Data.Char as Char (isAlpha, isDigit)

data Version = Version { versionNumber :: [Int] -- [1,42,3] ~= 1.42.3
                       , versionChar :: (Maybe Char) -- optional letter
                       , versionSuffix :: [Suffix]
                       , versionRevision :: Int -- revision, 0 means none
                       }
  deriving (Eq, Ord, Show, Read)

-- foo-9999* is treated as live ebuild
is_live :: Version -> Bool
is_live v =
    case versionNumber v of
        [n] | n >= 9999 && (all (== '9') . show) n -> True
        _ -> False

data Suffix = Alpha Int | Beta Int | Pre Int | RC Int | P Int
  deriving (Eq, Ord, Show, Read)

fromCabalVersion :: Cabal.Version -> Version
fromCabalVersion (Cabal.Version nums _tags) = Version nums Nothing [] 0

toCabalVersion :: Version -> Maybe Cabal.Version
toCabalVersion (Version nums Nothing [] _) = Just (Cabal.Version nums [])
toCabalVersion _ = Nothing

instance Text Version where
  disp (Version ver c suf rev) =
    dispVer ver <> dispC c <> dispSuf suf <> dispRev rev
    where
      dispVer = Disp.hcat . Disp.punctuate (Disp.char '.') . map Disp.int
      dispC = maybe Disp.empty Disp.char
      dispSuf = Disp.hcat . map disp
      dispRev 0 = Disp.empty
      dispRev n = Disp.text "-r" <> Disp.int n

  parse = do
    ver <- Parse.sepBy1 digits (Parse.char '.')
    c <- Parse.option Nothing (fmap Just (Parse.satisfy Char.isAlpha))
    suf <- Parse.many parse
    rev <- Parse.option 0 (Parse.string "-r" >> digits)
    return (Version ver c suf rev)

instance Text Suffix where
  disp suf = case suf of
    Alpha n -> Disp.text "_alpha" <> dispPos n
    Beta n -> Disp.text "_beta" <> dispPos n
    Pre n -> Disp.text "_pre" <> dispPos n
    RC n -> Disp.text "_rc" <> dispPos n
    P n -> Disp.text "_p" <> dispPos n

    where
      dispPos :: Int -> Disp.Doc
      dispPos 0 = Disp.empty
      dispPos n = Disp.int n

  parse = Parse.char '_'
       >> Parse.choice
    [ Parse.string "alpha" >> fmap Alpha maybeDigits
    , Parse.string "beta" >> fmap Beta maybeDigits
    , Parse.string "pre" >> fmap Pre maybeDigits
    , Parse.string "rc" >> fmap RC maybeDigits
    , Parse.string "p" >> fmap P maybeDigits
    ]
    where
      maybeDigits = Parse.option 0 digits

digits :: Parse.ReadP r Int
digits = fmap read (Parse.munch1 Char.isDigit)
Something went wrong with that request. Please try again.