{-# language MonadComprehensions #-} module Hix.Version where import Data.List.Extra (groupOnKey) import Distribution.Version ( Bound (ExclusiveBound), LowerBound (LowerBound), UpperBound (UpperBound), Version, VersionInterval (VersionInterval), VersionRange, alterVersion, asVersionIntervals, version0, versionNumbers, ) import qualified Hix.Data.Version import Hix.Data.Version (Major (Major)) lowerVersion :: VersionRange -> Maybe Version lowerVersion :: VersionRange -> Maybe Version lowerVersion VersionRange range = [Version v | VersionInterval (LowerBound Version v Bound _) UpperBound _ <- [VersionInterval] -> Maybe VersionInterval forall a. [a] -> Maybe a head (VersionRange -> [VersionInterval] asVersionIntervals VersionRange range), Version v Version -> Version -> Bool forall a. Eq a => a -> a -> Bool /= Version version0] exclusiveUpperVersion :: VersionRange -> Maybe Version exclusiveUpperVersion :: VersionRange -> Maybe Version exclusiveUpperVersion VersionRange range = [Version v | VersionInterval LowerBound _ (UpperBound Version v Bound ExclusiveBound) <- [VersionInterval] -> Maybe VersionInterval forall a. [a] -> Maybe a last (VersionRange -> [VersionInterval] asVersionIntervals VersionRange range)] upperVersion :: VersionRange -> Maybe Version upperVersion :: VersionRange -> Maybe Version upperVersion VersionRange range = [Version v | VersionInterval LowerBound _ (UpperBound Version v Bound _) <- [VersionInterval] -> Maybe VersionInterval forall a. [a] -> Maybe a last (VersionRange -> [VersionInterval] asVersionIntervals VersionRange range)] majorParts :: Version -> Maybe (Int, Int) majorParts :: Version -> Maybe (Int, Int) majorParts = Version -> [Int] versionNumbers (Version -> [Int]) -> ([Int] -> Maybe (Int, Int)) -> Version -> Maybe (Int, Int) forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c >>> \case [] -> Maybe (Int, Int) forall a. Maybe a Nothing [Item [Int] 0] -> Maybe (Int, Int) forall a. Maybe a Nothing [Item [Int] s] -> (Int, Int) -> Maybe (Int, Int) forall a. a -> Maybe a Just (Int Item [Int] s, Int 0) Int s : Int m : [Int] _ -> (Int, Int) -> Maybe (Int, Int) forall a. a -> Maybe a Just (Int s, Int m) majorPrefix :: Version -> Maybe [Int] majorPrefix :: Version -> Maybe [Int] majorPrefix = Version -> Maybe (Int, Int) majorParts (Version -> Maybe (Int, Int)) -> (Maybe (Int, Int) -> Maybe [Int]) -> Version -> Maybe [Int] forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c >>> ((Int, Int) -> [Int]) -> Maybe (Int, Int) -> Maybe [Int] forall a b. (a -> b) -> Maybe a -> Maybe b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap \case (Int s, Int m) -> [Int Item [Int] s, Int Item [Int] m] hasMajor :: Int -> Int -> Version -> Bool hasMajor :: Int -> Int -> Version -> Bool hasMajor Int s Int m Version candidate = case Int -> [Int] -> [Int] forall a. Int -> [a] -> [a] take Int 2 (Version -> [Int] versionNumbers Version candidate) of [Item [Int] s'] -> Int Item [Int] s' Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int s Bool -> Bool -> Bool && Int m Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int 0 Int s' : Int m' : [Int] _ -> Int s' Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int s Bool -> Bool -> Bool && Int m' Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int m [Int] _ -> Bool False minMajor :: Int -> Int -> Version -> Bool minMajor :: Int -> Int -> Version -> Bool minMajor Int s Int m Version candidate = case Int -> [Int] -> [Int] forall a. Int -> [a] -> [a] take Int 2 (Version -> [Int] versionNumbers Version candidate) of [Item [Int] s'] -> Int Item [Int] s' Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int s Bool -> Bool -> Bool || (Int Item [Int] s' Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int s Bool -> Bool -> Bool && Int m Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int 0) Int s' : Int m' : [Int] _ -> Int s' Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int s Bool -> Bool -> Bool || (Int s' Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int s Bool -> Bool -> Bool && Int m' Int -> Int -> Bool forall a. Ord a => a -> a -> Bool >= Int m) [Int] _ -> Bool False beforeMajor :: Int -> Int -> Version -> Bool beforeMajor :: Int -> Int -> Version -> Bool beforeMajor Int s Int m Version candidate = case Int -> [Int] -> [Int] forall a. Int -> [a] -> [a] take Int 2 (Version -> [Int] versionNumbers Version candidate) of [Item [Int] s'] -> Int Item [Int] s' Int -> Int -> Bool forall a. Ord a => a -> a -> Bool < Int s Bool -> Bool -> Bool || (Int Item [Int] s' Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int s Bool -> Bool -> Bool && Int m Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int 0) Int s' : Int m' : [Int] _ -> Int s' Int -> Int -> Bool forall a. Ord a => a -> a -> Bool < Int s Bool -> Bool -> Bool || (Int s' Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int s Bool -> Bool -> Bool && Int m' Int -> Int -> Bool forall a. Ord a => a -> a -> Bool < Int m) [Int] _ -> Bool False lastMajor :: [Version] -> [Version] lastMajor :: [Version] -> [Version] lastMajor = [Version] -> [Version] forall a. [a] -> [a] reverse ([Version] -> [Version]) -> ([Version] -> [Version]) -> [Version] -> [Version] forall b c a. (b -> c) -> (a -> b) -> a -> c . ([Version], (Int, Int)) -> [Version] forall a b. (a, b) -> a fst (([Version], (Int, Int)) -> [Version]) -> ([Version] -> ([Version], (Int, Int))) -> [Version] -> [Version] forall b c a. (b -> c) -> (a -> b) -> a -> c . (([Version], (Int, Int)) -> Version -> ([Version], (Int, Int))) -> ([Version], (Int, Int)) -> [Version] -> ([Version], (Int, Int)) forall (t :: * -> *) b a. Foldable t => (b -> a -> b) -> b -> t a -> b foldl ([Version], (Int, Int)) -> Version -> ([Version], (Int, Int)) step ([], (Int 0, Int 0)) where step :: ([Version], (Int, Int)) -> Version -> ([Version], (Int, Int)) step ([Version] z, (Int, Int) cur) Version a | Just (Int, Int) pre <- Version -> Maybe (Int, Int) majorParts Version a , (Int, Int) pre (Int, Int) -> (Int, Int) -> Bool forall a. Eq a => a -> a -> Bool /= (Int, Int) cur = ([Version Item [Version] a], (Int, Int) pre) | Bool otherwise = (Version a Version -> [Version] -> [Version] forall a. a -> [a] -> [a] : [Version] z, (Int, Int) cur) lastMajorBefore :: Int -> Int -> [Version] -> [Version] lastMajorBefore :: Int -> Int -> [Version] -> [Version] lastMajorBefore Int s Int m = [Version] -> [Version] forall a. [a] -> [a] reverse ([Version] -> [Version]) -> ([Version] -> [Version]) -> [Version] -> [Version] forall b c a. (b -> c) -> (a -> b) -> a -> c . ([Version], (Int, Int)) -> [Version] forall a b. (a, b) -> a fst (([Version], (Int, Int)) -> [Version]) -> ([Version] -> ([Version], (Int, Int))) -> [Version] -> [Version] forall b c a. (b -> c) -> (a -> b) -> a -> c . (([Version], (Int, Int)) -> Version -> ([Version], (Int, Int))) -> ([Version], (Int, Int)) -> [Version] -> ([Version], (Int, Int)) forall (t :: * -> *) b a. Foldable t => (b -> a -> b) -> b -> t a -> b foldl ([Version], (Int, Int)) -> Version -> ([Version], (Int, Int)) step ([], (Int 0, Int 0)) where step :: ([Version], (Int, Int)) -> Version -> ([Version], (Int, Int)) step ([Version] z, (Int, Int) cur) Version a | Just (Int s', Int m') <- Maybe (Int, Int) mp , Int s' Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int s Bool -> Bool -> Bool || (Int s' Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int s Bool -> Bool -> Bool && Int m' Int -> Int -> Bool forall a. Ord a => a -> a -> Bool >= Int m) = ([Version] z, (Int, Int) cur) | Just (Int, Int) pre <- Maybe (Int, Int) mp , (Int, Int) pre (Int, Int) -> (Int, Int) -> Bool forall a. Eq a => a -> a -> Bool /= (Int, Int) cur = ([Version Item [Version] a], (Int, Int) pre) | Bool otherwise = (Version a Version -> [Version] -> [Version] forall a. a -> [a] -> [a] : [Version] z, (Int, Int) cur) where mp :: Maybe (Int, Int) mp = Version -> Maybe (Int, Int) majorParts Version a nextMajor :: Version -> Version nextMajor :: Version -> Version nextMajor = ([Int] -> [Int]) -> Version -> Version alterVersion \case [] -> [Int Item [Int] 0, Int Item [Int] 1] [Item [Int] s] -> [Item [Int] s, Int Item [Int] 1] Int s : Int m : [Int] _ -> [Int Item [Int] s, Int m Int -> Int -> Int forall a. Num a => a -> a -> a + Int 1] prevMajor :: Version -> Version prevMajor :: Version -> Version prevMajor = ([Int] -> [Int]) -> Version -> Version alterVersion \case [Item [Int] s] | Int Item [Int] s Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int 0 -> [Int Item [Int] s Int -> Int -> Int forall a. Num a => a -> a -> a - Int 1, Int Item [Int] 99] Int s : Int 0 : [Int] _ | Int s Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int 0 -> [Int s Int -> Int -> Int forall a. Num a => a -> a -> a - Int 1, Int Item [Int] 99] Int s : Int m : [Int] _ | Int s Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int 0, Int m Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int 0 -> [Int Item [Int] s, Int m Int -> Int -> Int forall a. Num a => a -> a -> a - Int 1] [Int] _ -> [Int Item [Int] 0] currentMajor :: Version -> Version currentMajor :: Version -> Version currentMajor = ([Int] -> [Int]) -> Version -> Version alterVersion (Int -> [Int] -> [Int] forall a. Int -> [a] -> [a] take Int 2) isMajor :: Int -> Int -> Major -> Bool isMajor :: Int -> Int -> Major -> Bool isMajor Int s Int m Major {Version prefix :: Version prefix :: Major -> Version prefix} = Version prefix Version -> Version -> Bool forall a. Eq a => a -> a -> Bool == [Int Item Version s, Int Item Version m] majorOlder :: Int -> Int -> Major -> Bool majorOlder :: Int -> Int -> Major -> Bool majorOlder Int s Int m Major {Version prefix :: Major -> Version prefix :: Version prefix} = Version prefix Version -> Version -> Bool forall a. Ord a => a -> a -> Bool < [Int Item Version s, Int Item Version m] majorNewer :: Int -> Int -> Major -> Bool majorNewer :: Int -> Int -> Major -> Bool majorNewer Int s Int m Major {Version prefix :: Major -> Version prefix :: Version prefix} = Version prefix Version -> Version -> Bool forall a. Ord a => a -> a -> Bool > [Int Item Version s, Int Item Version m] allMajors :: [Version] -> [Major] allMajors :: [Version] -> [Major] allMajors = ((Version, [Version]) -> Maybe Major) -> [(Version, [Version])] -> [Major] forall a b. (a -> Maybe b) -> [a] -> [b] mapMaybe ((Version -> [Version] -> Maybe Major) -> (Version, [Version]) -> Maybe Major forall a b c. (a -> b -> c) -> (a, b) -> c uncurry Version -> [Version] -> Maybe Major cons) ([(Version, [Version])] -> [Major]) -> ([Version] -> [(Version, [Version])]) -> [Version] -> [Major] forall b c a. (b -> c) -> (a -> b) -> a -> c . (Version -> Version) -> [Version] -> [(Version, [Version])] forall k a. Eq k => (a -> k) -> [a] -> [(k, [a])] groupOnKey Version -> Version currentMajor where cons :: Version -> [Version] -> Maybe Major cons Version prefix = \case (Version h : [Version] t) -> Major -> Maybe Major forall a. a -> Maybe a Just (Major {Version prefix :: Version prefix :: Version prefix, versions :: NonEmpty Version versions = Version h Version -> [Version] -> NonEmpty Version forall a. a -> [a] -> NonEmpty a :| [Version] t}) [] -> Maybe Major forall a. Maybe a Nothing majorsBefore :: Int -> Int -> [Version] -> [Major] majorsBefore :: Int -> Int -> [Version] -> [Major] majorsBefore Int s Int m = (Major -> Bool) -> [Major] -> [Major] forall a. (a -> Bool) -> [a] -> [a] takeWhile (Int -> Int -> Major -> Bool majorOlder Int s Int m) ([Major] -> [Major]) -> ([Version] -> [Major]) -> [Version] -> [Major] forall b c a. (b -> c) -> (a -> b) -> a -> c . [Version] -> [Major] allMajors majorsFrom :: Int -> Int -> [Version] -> [Major] majorsFrom :: Int -> Int -> [Version] -> [Major] majorsFrom Int s Int m = (Major -> Bool) -> [Major] -> [Major] forall a. (a -> Bool) -> [a] -> [a] dropWhile (Int -> Int -> Major -> Bool majorOlder Int s Int m) ([Major] -> [Major]) -> ([Version] -> [Major]) -> [Version] -> [Major] forall b c a. (b -> c) -> (a -> b) -> a -> c . [Version] -> [Major] allMajors onlyMajor :: Int -> Int -> [Version] -> Maybe Major onlyMajor :: Int -> Int -> [Version] -> Maybe Major onlyMajor Int s Int m = (Major -> Bool) -> [Major] -> Maybe Major forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a find (Int -> Int -> Major -> Bool isMajor Int s Int m) ([Major] -> Maybe Major) -> ([Version] -> [Major]) -> [Version] -> Maybe Major forall b c a. (b -> c) -> (a -> b) -> a -> c . [Version] -> [Major] allMajors versionsFrom :: Version -> [Version] -> [Major] versionsFrom :: Version -> [Version] -> [Major] versionsFrom Version start = [Version] -> [Major] allMajors ([Version] -> [Major]) -> ([Version] -> [Version]) -> [Version] -> [Major] forall b c a. (b -> c) -> (a -> b) -> a -> c . (Version -> Bool) -> [Version] -> [Version] forall a. (a -> Bool) -> [a] -> [a] dropWhile (Version -> Version -> Bool forall a. Ord a => a -> a -> Bool < Version start) versionsBetween :: Version -> Version -> [Version] -> [Major] versionsBetween :: Version -> Version -> [Version] -> [Major] versionsBetween Version l Version u = [Version] -> [Major] allMajors ([Version] -> [Major]) -> ([Version] -> [Version]) -> [Version] -> [Major] forall b c a. (b -> c) -> (a -> b) -> a -> c . (Version -> Bool) -> [Version] -> [Version] forall a. (a -> Bool) -> [a] -> [a] takeWhile (Version -> Version -> Bool forall a. Ord a => a -> a -> Bool < Version u) ([Version] -> [Version]) -> ([Version] -> [Version]) -> [Version] -> [Version] forall b c a. (b -> c) -> (a -> b) -> a -> c . (Version -> Bool) -> [Version] -> [Version] forall a. (a -> Bool) -> [a] -> [a] dropWhile (Version -> Version -> Bool forall a. Ord a => a -> a -> Bool < Version l)