module Distribution.Version (
Version(..),
VersionRange(..), notThisVersion,
orLaterVersion, orEarlierVersion,
betweenVersionsInclusive,
withinRange,
isAnyVersion,
showVersion,
parseVersion,
) where
import Data.Version ( Version(..) )
import Distribution.Text ( Text(..), display )
import qualified Distribution.Compat.ReadP as Parse
import Distribution.Compat.ReadP ((+++))
import qualified Text.PrettyPrint as Disp
import Text.PrettyPrint ((<>), (<+>))
data VersionRange
= AnyVersion
| ThisVersion Version
| LaterVersion Version
| EarlierVersion Version
| UnionVersionRanges VersionRange VersionRange
| IntersectVersionRanges VersionRange VersionRange
deriving (Show,Read,Eq)
isAnyVersion :: VersionRange -> Bool
isAnyVersion AnyVersion = True
isAnyVersion _ = False
notThisVersion :: Version -> VersionRange
notThisVersion v = UnionVersionRanges (EarlierVersion v) (LaterVersion v)
orLaterVersion :: Version -> VersionRange
orLaterVersion v = UnionVersionRanges (ThisVersion v) (LaterVersion v)
orEarlierVersion :: Version -> VersionRange
orEarlierVersion v = UnionVersionRanges (ThisVersion v) (EarlierVersion v)
betweenVersionsInclusive :: Version -> Version -> VersionRange
betweenVersionsInclusive v1 v2 =
IntersectVersionRanges (orLaterVersion v1) (orEarlierVersion v2)
laterVersion :: Version -> Version -> Bool
v1 `laterVersion` v2 = versionBranch v1 > versionBranch v2
earlierVersion :: Version -> Version -> Bool
v1 `earlierVersion` v2 = versionBranch v1 < versionBranch v2
withinRange :: Version -> VersionRange -> Bool
withinRange _ AnyVersion = True
withinRange v1 (ThisVersion v2) = v1 == v2
withinRange v1 (LaterVersion v2) = v1 `laterVersion` v2
withinRange v1 (EarlierVersion v2) = v1 `earlierVersion` v2
withinRange v1 (UnionVersionRanges v2 v3)
= v1 `withinRange` v2 || v1 `withinRange` v3
withinRange v1 (IntersectVersionRanges v2 v3)
= v1 `withinRange` v2 && v1 `withinRange` v3
instance Text VersionRange where
disp AnyVersion = Disp.text "-any"
disp (ThisVersion v) = Disp.text "==" <> disp v
disp (LaterVersion v) = Disp.char '>' <> disp v
disp (EarlierVersion v) = Disp.char '<' <> disp v
disp (UnionVersionRanges (ThisVersion v1) (LaterVersion v2))
| v1 == v2 = Disp.text ">=" <> disp v1
disp (UnionVersionRanges (LaterVersion v2) (ThisVersion v1))
| v1 == v2 = Disp.text ">=" <> disp v1
disp (UnionVersionRanges (ThisVersion v1) (EarlierVersion v2))
| v1 == v2 = Disp.text "<=" <> disp v1
disp (UnionVersionRanges (EarlierVersion v2) (ThisVersion v1))
| v1 == v2 = Disp.text "<=" <> disp v1
disp (UnionVersionRanges r1 r2)
= disp r1 <+> Disp.text "||" <+> disp r2
disp (IntersectVersionRanges r1 r2)
= disp r1 <+> Disp.text "&&" <+> disp r2
parse = do
f1 <- factor
Parse.skipSpaces
(do
Parse.string "||"
Parse.skipSpaces
f2 <- factor
return (UnionVersionRanges f1 f2)
+++
do
Parse.string "&&"
Parse.skipSpaces
f2 <- factor
return (IntersectVersionRanges f1 f2)
+++
return f1)
where
factor = Parse.choice ((Parse.string "-any" >> return AnyVersion) :
map parseRangeOp rangeOps)
parseRangeOp (s,f) = Parse.string s >> Parse.skipSpaces >> fmap f parse
rangeOps = [ ("<", EarlierVersion),
("<=", orEarlierVersion),
(">", LaterVersion),
(">=", orLaterVersion),
("==", ThisVersion) ]
showVersion :: Version -> String
showVersion = display
parseVersion :: Parse.ReadP r Version
parseVersion = parse