versions 4.0.0 → 4.0.1
raw patch · 4 files changed
+57/−38 lines, 4 files
Files
- CHANGELOG.md +8/−0
- Data/Versions.hs +9/−24
- test/Test.hs +39/−13
- versions.cabal +1/−1
CHANGELOG.md view
@@ -1,5 +1,13 @@ # Changelog +## 4.0.1 (2020-10-22)++#### Fixed++- An infinite loop in `Version` comparison. [aura#652]++[aura#652]: https://github.com/fosskers/aura/issues/652+ ## 4.0.0 (2020-10-20) #### Changed
Data/Versions.hs view
@@ -80,6 +80,7 @@ import Data.List (intersperse) import Data.List.NonEmpty (NonEmpty(..)) import qualified Data.List.NonEmpty as NEL+import Data.Maybe (fromMaybe) import Data.Text (Text) import qualified Data.Text as T import Data.Void (Void)@@ -521,36 +522,20 @@ instance Semigroup Version where Version e c m r <> Version e' c' m' r' = Version ((+) <$> e <*> e') (c <> c') (m <> m') (r <> r') --- | Set a `Version`'s epoch to `Nothing`.-wipe :: Version -> Version-wipe v = v { _vEpoch = Nothing }- -- | Customized. instance Ord Version where -- | For the purposes of Versions with epochs, `Nothing` is the same as `Just 0`, -- so we need to compare their actual version numbers.- compare v0@(Version (Just 0) _ _ _) v1@(Version Nothing _ _ _) = compare (wipe v0) v1- compare v0@(Version Nothing _ _ _) v1@(Version (Just 0) _ _ _) = compare v0 (wipe v1)-- -- | If a version has an epoch > 1 and the other has no epoch, the first will- -- be considered greater.- compare (Version (Just _) _ _ _) (Version Nothing _ _ _) = GT- compare (Version Nothing _ _ _) (Version (Just _) _ _ _) = LT-- -- | If two epochs are equal, we need to compare their actual version numbers.- -- Otherwise, the comparison of the epochs is the only thing that matters.- compare v0@(Version (Just n) _ _ _) v1@(Version (Just m) _ _ _) | n == m = compare (wipe v0) (wipe v1)- | otherwise = compare n m-- -- | The usual case. If first VChunks of each Version is equal, then we keep- -- recursing. Otherwise, we don't need to check further. Consider @1.2@- -- compared to @1.1.3.4.5.6@.- compare (Version _ as _ rs) (Version _ bs _ rs') = g (NEL.toList as) (NEL.toList bs)+ compare (Version ae as _ rs) (Version be bs _ rs') = case compare (fromMaybe 0 ae) (fromMaybe 0 be) of+ EQ -> case g (NEL.toList as) (NEL.toList bs) of+ -- If the two Versions were otherwise equal and recursed down this far,+ -- we need to compare them by their "release" values.+ EQ -> g rs rs'+ ord -> ord+ ord -> ord where g :: [VChunk] -> [VChunk] -> Ordering- -- | If the two Versions were otherwise equal and recursed down this far,- -- we need to compare them by their "release" values.- g [] [] = g rs rs'+ g [] [] = EQ -- | If all chunks up until this point were equal, but one side continues -- on with "lettered" sections, these are considered to be indicating a
test/Test.hs view
@@ -20,6 +20,7 @@ import Test.Tasty.QuickCheck import Text.Megaparsec import Text.Megaparsec.Char+import Text.Printf (printf) --- @@ -56,13 +57,14 @@ goodVers :: [T.Text] goodVers = [ "1", "1.2", "1.0rc0", "1.0rc1", "1.1rc1", "1.58.0-3", "44.0.2403.157-1" , "0.25-2", "8.u51-1", "21-2", "7.1p1-1", "20150826-1", "1:0.10.16-3"- , "1.11.0.git.20200404-1", "1.11.0+20200830-1" ]+ , "1.11.0.git.20200404-1", "1.11.0+20200830-1", "1:3.20" ] badVers :: [T.Text] badVers = ["", "1.2 "] messes :: [T.Text]-messes = [ "10.2+0.93+1-1", "003.03-3", "002.000-7", "20.26.1_0-2", "1.6.0a+2014+m872b87e73dfb-1" ]+messes = [ "10.2+0.93+1-1", "003.03-3", "002.000-7", "20.26.1_0-2", "1.6.0a+2014+m872b87e73dfb-1"+ , "1.3.00.16851-1", "5.2.458699.0906-1" ] messComps :: [T.Text] messComps = [ "10.2+0.93+1-1", "10.2+0.93+1-2", "10.2+0.93+2-1"@@ -172,26 +174,41 @@ , testCase "0.25-2 is Version" $ check $ isVersion <$> versioning "0.25-2" , testCase "1:1.2.3-1 is Version" $ check $ isVersion <$> versioning "1:1.2.3-1" , testCase "1.2.3+1-1 is Version" $ check $ isVersion <$> versioning "1.2.3+1-1"+ , testCase "1:3.20.1-1 is Version" $ check $ isVersion <$> versioning "1:3.20.1-1" , testCase "000.007-1 is Mess" $ check $ isMess <$> versioning "000.007-1" , testCase "20.26.1_0-2 is Mess" $ check $ isMess <$> versioning "20.26.1_0-2"+ , testCase "1:3.20.1-1 is Version" $ check $ isVersion <$> versioning "1:3.20.1-1" ] , testGroup "Bad Versions" $ map (\s -> testCase (T.unpack s) $ assertBool "A bad version parsed" $ isLeft $ versioning s) badVers , testGroup "Isomorphisms" $ map (\s -> testCase (T.unpack s) $ isomorph s) $ goodSemVs ++ goodVers ++ messes , testGroup "Comparisons"- [ testCase "1.2.2r1-1 < 1.2.3-1" $ comp versioning "1.2.2r1-1" "1.2.3-1"- , testCase "1.2.3-1 < 1.2.4r1-1" $ comp versioning "1.2.3-1" "1.2.4r1-1"- , testCase "1.2.3-1 < 2+0007-1" $ comp versioning "1.2.3-1" "2+0007-1"- , testCase "1.2.3r1-1 < 2+0007-1" $ comp versioning "1.2.3r1-1" "2+0007-1"- , testCase "1.2-5 < 1.2.3-1" $ comp versioning "1.2-5" "1.2.3-1"- , testCase "1.6.0a+2014+m872b87e73dfb-1 < 1.6.0-1"- $ comp versioning "1.6.0a+2014+m872b87e73dfb-1" "1.6.0-1"- , testCase "1.11.0.git.20200404-1 < 1.11.0+20200830-1"- $ comp versioning "1.11.0.git.20200404-1" "1.11.0+20200830-1"- , testCase "0.17.0+r8+gc41db5f1-1 < 0.17.0+r157+g584760cf-1"- $ comp versioning "0.17.0+r8+gc41db5f1-1" "0.17.0+r157+g584760cf-1"+ [ compVer "1.2.2r1-1" "1.2.3-1"+ , compVer "1.2.3-1" "1.2.4r1-1"+ , compVer "1.2.3-1" "2+0007-1"+ , compVer "1.2.3r1-1" "2+0007-1"+ , compVer "1.2-5" "1.2.3-1"+ , compVer "1.6.0a+2014+m872b87e73dfb-1" "1.6.0-1"+ , compVer "1.11.0.git.20200404-1" "1.11.0+20200830-1"+ , compVer "0.17.0+r8+gc41db5f1-1" "0.17.0+r157+g584760cf-1"+ , compVer "0.4.8-1" "0.4.9-1"+ , compVer "7.42.13-4" "7.46.0-2"+ , compVer "1.15.2-1" "1.15.3-1"+ , compVer "2.1.16102-2" "2.1.17627-1"+ , compVer "8.64.0.81-1" "8.65.0.78-1"+ , compVer "1.3.00.16851-1" "1.3.00.25560-1"+ , compVer "10.0.4-1" "10.1.0-1"+ , compVer "1:3.20-1" "1:3.20.1-1"+ , compVer "5.2.458699.0906-1" "5.3.472687.1012-1" ]+ , testGroup "Equality"+ [ eqVer "1:3.20.1-1"+ , eqVer "1.3.00.25560-1"+ , eqVer "150_28-3"+ , eqVer "1.0.r15.g3fc772c-5"+ , eqVer "0.88-2"+ ] ] , testGroup "Lenses and Traversals" [ testCase "SemVer - Increment Patch" incPatch@@ -205,6 +222,12 @@ ] ] +compVer :: T.Text -> T.Text -> TestTree+compVer a b = testCase (printf "%s < %s" a b) $ comp versioning a b++eqVer :: T.Text -> TestTree+eqVer a = testCase (T.unpack a) $ equal versioning a+ -- | Does pretty-printing return a Versioning to its original form? isomorph :: T.Text -> Assertion isomorph t = case prettyV <$> versioning t of@@ -235,6 +258,9 @@ comp :: Ord b => (T.Text -> Either a b) -> T.Text -> T.Text -> Assertion comp f a b = check $ (<) <$> f a <*> f b++equal :: Ord r => (T.Text -> Either l r) -> T.Text -> Assertion+equal f a = check $ (\r -> compare r r == EQ) <$> f a check :: Either a Bool -> Assertion check = assertBool "Some Either-based assertion failed" . either (const False) id
versions.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: versions-version: 4.0.0+version: 4.0.1 synopsis: Types and parsers for software version numbers. description: A library for parsing and comparing software version numbers. We like to give