From 93bb89515c981ca46c1362a675bb1934c4120ee4 Mon Sep 17 00:00:00 2001 From: Oleg Grenrus <oleg.grenrus@iki.fi> Date: Fri, 24 Apr 2020 17:22:56 +0300 Subject: [PATCH] VersionIntervals don't destroy MajorBoundVersion --- Cabal/Distribution/Types/VersionInterval.hs | 70 +++++++++++++-------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/Cabal/Distribution/Types/VersionInterval.hs b/Cabal/Distribution/Types/VersionInterval.hs index ebb2178fc5..e2f9bfdfad 100644 --- a/Cabal/Distribution/Types/VersionInterval.hs +++ b/Cabal/Distribution/Types/VersionInterval.hs @@ -57,7 +57,7 @@ import qualified Prelude (foldr1) -- > , v == v' = Just v -- > | otherwise = Nothing -- -asVersionIntervals :: VersionRange -> [VersionInterval] +asVersionIntervals :: VersionRange -> ([Version], [VersionInterval]) asVersionIntervals = versionIntervals . toVersionIntervals @@ -77,13 +77,13 @@ asVersionIntervals = versionIntervals . toVersionIntervals -- predicates for translation into foreign packaging systems that do not -- support complex version range expressions. -- -newtype VersionIntervals = VersionIntervals [VersionInterval] +data VersionIntervals = VersionIntervals [Version] [VersionInterval] deriving (Eq, Show, Typeable) -- | Inspect the list of version intervals. -- -versionIntervals :: VersionIntervals -> [VersionInterval] -versionIntervals (VersionIntervals is) = is +versionIntervals :: VersionIntervals -> ([Version], [VersionInterval]) +versionIntervals (VersionIntervals ms is) = (ms, is) type VersionInterval = (LowerBound, UpperBound) data LowerBound = LowerBound Version !Bound deriving (Eq, Show) @@ -111,8 +111,11 @@ instance Ord UpperBound where GT -> False invariant :: VersionIntervals -> Bool -invariant (VersionIntervals intervals) = all validInterval intervals - && all doesNotTouch' adjacentIntervals +invariant (VersionIntervals _ms intervals) = and + [ all validInterval intervals + , all doesNotTouch' adjacentIntervals + -- TODO: ms + ] where doesNotTouch' :: (VersionInterval, VersionInterval) -> Bool doesNotTouch' ((_,u), (l',_)) = doesNotTouch u l' @@ -131,15 +134,16 @@ checkInvariant is = assert (invariant is) is -- mkVersionIntervals :: [VersionInterval] -> VersionIntervals mkVersionIntervals intervals - | invariant (VersionIntervals intervals) = VersionIntervals intervals + | invariant (VersionIntervals [] intervals) + = VersionIntervals [] intervals | otherwise - = checkInvariant - . foldl' (flip insertInterval) (VersionIntervals []) - . filter validInterval - $ intervals + = checkInvariant + . foldl' (flip insertInterval) (VersionIntervals [] []) + . filter validInterval + $ intervals insertInterval :: VersionInterval -> VersionIntervals -> VersionIntervals -insertInterval i is = unionVersionIntervals (VersionIntervals [i]) is +insertInterval i is = unionVersionIntervals (VersionIntervals [] [i]) is validInterval :: (LowerBound, UpperBound) -> Bool validInterval i@(l, u) = validLower l && validUpper u && nonEmpty i @@ -186,10 +190,15 @@ doesNotIntersect (UpperBound u ub) (LowerBound l lb) = -- > withinIntervals v ivs = withinRange v (fromVersionIntervals ivs) -- withinIntervals :: Version -> VersionIntervals -> Bool -withinIntervals v (VersionIntervals intervals) = any withinInterval intervals +withinIntervals v (VersionIntervals ms intervals) = + any withinInterval intervals || + any withinMajorInterval ms where + withinMajorInterval m = m >= v && v < majorUpperBound m + withinInterval (lowerBound, upperBound) = withinLower lowerBound && withinUpper upperBound + withinLower (LowerBound v' ExclusiveBound) = v' < v withinLower (LowerBound v' InclusiveBound) = v' <= v @@ -204,19 +213,19 @@ toVersionIntervals = foldVersionRange ( chkIvl (minLowerBound, NoUpperBound)) (\v -> chkIvl (LowerBound v InclusiveBound, UpperBound v InclusiveBound)) (\v -> chkIvl (LowerBound v ExclusiveBound, NoUpperBound)) - (\v -> if isVersion0 v then VersionIntervals [] else + (\v -> if isVersion0 v then VersionIntervals [] [] else chkIvl (minLowerBound, UpperBound v ExclusiveBound)) unionVersionIntervals intersectVersionIntervals where - chkIvl interval = checkInvariant (VersionIntervals [interval]) + chkIvl interval = checkInvariant (VersionIntervals [] [interval]) -- | Convert a 'VersionIntervals' value back into a 'VersionRange' expression -- representing the version intervals. -- fromVersionIntervals :: VersionIntervals -> VersionRange -fromVersionIntervals (VersionIntervals []) = noVersion -fromVersionIntervals (VersionIntervals intervals) = +fromVersionIntervals (VersionIntervals [] []) = noVersion +fromVersionIntervals (VersionIntervals _ms intervals) = -- TODO Prelude.foldr1 unionVersionRanges [ interval l u | (l, u) <- intervals ] where @@ -244,8 +253,8 @@ fromVersionIntervals (VersionIntervals intervals) = unionVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals -unionVersionIntervals (VersionIntervals is0) (VersionIntervals is'0) = - checkInvariant (VersionIntervals (union is0 is'0)) +unionVersionIntervals (VersionIntervals ms is0) (VersionIntervals ns is'0) = + checkInvariant (VersionIntervals (ms ++ ns) {- TODO -} (union is0 is'0)) where union is [] = is union [] is' = is' @@ -277,8 +286,8 @@ unionInterval (lower , upper ) (lower', upper') intersectVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals -intersectVersionIntervals (VersionIntervals is0) (VersionIntervals is'0) = - checkInvariant (VersionIntervals (intersect is0 is'0)) +intersectVersionIntervals (VersionIntervals ms is0) (VersionIntervals ns is'0) = + checkInvariant (VersionIntervals [] {- TODO -} (intersect is0 is'0)) where intersect _ [] = [] intersect [] _ = [] @@ -310,18 +319,20 @@ intersectInterval (lower , upper ) (lower', upper') invertVersionIntervals :: VersionIntervals -> VersionIntervals -invertVersionIntervals (VersionIntervals xs) = +invertVersionIntervals (VersionIntervals ms is) = case xs of -- Empty interval set - [] -> VersionIntervals [(noLowerBound, NoUpperBound)] + [] -> VersionIntervals [] [(noLowerBound, NoUpperBound)] -- Interval with no lower bound ((lb, ub) : more) | lb == noLowerBound -> - VersionIntervals $ invertVersionIntervals' ub more + VersionIntervals [] $ invertVersionIntervals' ub more -- Interval with a lower bound ((lb, ub) : more) -> - VersionIntervals $ (noLowerBound, invertLowerBound lb) + VersionIntervals [] $ (noLowerBound, invertLowerBound lb) : invertVersionIntervals' ub more where + xs = is -- TODO: ms + -- Invert subsequent version intervals given the upper bound of -- the intervals already inverted. invertVersionIntervals' :: UpperBound @@ -349,16 +360,21 @@ invertVersionIntervals (VersionIntervals xs) = noLowerBound :: LowerBound noLowerBound = LowerBound (mkVersion [0]) InclusiveBound +------------------------------------------------------------------------------- +-- Relaxation +------------------------------------------------------------------------------- + +-- TODO relaxLastInterval :: VersionIntervals -> VersionIntervals -relaxLastInterval (VersionIntervals xs) = VersionIntervals (relaxLastInterval' xs) +relaxLastInterval (VersionIntervals ms xs) = VersionIntervals ms (relaxLastInterval' xs) where relaxLastInterval' [] = [] relaxLastInterval' [(l,_)] = [(l, NoUpperBound)] relaxLastInterval' (i:is) = i : relaxLastInterval' is relaxHeadInterval :: VersionIntervals -> VersionIntervals -relaxHeadInterval (VersionIntervals xs) = VersionIntervals (relaxHeadInterval' xs) +relaxHeadInterval (VersionIntervals ms xs) = VersionIntervals ms (relaxHeadInterval' xs) where relaxHeadInterval' [] = [] relaxHeadInterval' ((_,u):is) = (minLowerBound,u) : is -- GitLab