Skip to content

Commit

Permalink
fix parsing bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Allen Nelson committed Oct 28, 2015
1 parent 9614cce commit ccd118d
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 14 deletions.
2 changes: 1 addition & 1 deletion project.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
, cabal-install, unordered-containers }:
mkDerivation {
pname = "semver-range";
version = "0.1.0";
version = "0.1.1";
src = ./.;
isLibrary = true;
buildDepends = [ base classy-prelude parsec text cabal-install
Expand Down
2 changes: 1 addition & 1 deletion semver-range.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: semver-range
version: 0.1.0
version: 0.1.1
synopsis: An implementation of semver and semantic version ranges.
license: MIT
license-file: LICENSE
Expand Down
27 changes: 17 additions & 10 deletions src/Data/SemVer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ tuplesOf = map toTuple . versionsOf
rangeReleaseTags :: SemVerRange -> [ReleaseTag]
rangeReleaseTags = concatMap releaseTags . versionsOf

-- | Get the range release tags if they're all the same; otherwise
-- Nothing.
sharedReleaseTags :: SemVerRange -> Maybe [ReleaseTag]
sharedReleaseTags range = case map releaseTags $ versionsOf range of
[] -> Nothing -- shouldn't happen but in case
[]:_ -> Nothing -- no release tags, so that seals it
tagList:otherLists
| all (== tagList) otherLists -> Just tagList
| otherwise -> Nothing

-- | Satisfies any version.
anyVersion :: SemVerRange
anyVersion = Gt $ semver 0 0 0
Expand Down Expand Up @@ -92,18 +102,15 @@ instance Show SemVerRange where
-- Note that there are special cases when there are release tags. For detauls
-- see https://github.com/npm/node-semver#prerelease-tags.
matches :: SemVerRange -> SemVer -> Bool
matches range ver = case (rangeReleaseTags range, releaseTags ver) of
matches range version = case (sharedReleaseTags range, releaseTags version) of
-- This is the simple case, where neither the range nor the version has given
-- any release tags. Then we can just do regular predicate calculus.
([], []) -> matchesSimple range ver
-- If the version has release tags but the range doesn't, it's not a match.
([], _) -> False
-- If the version has release tags but none of the comparators have the same
-- (major, minor, patch) tuples, it's not a match. For now, we're being even
-- more strict, saying that there has to be exactly one comparator as well.
(_, _) | tuplesOf range /= [toTuple ver] -> False
-- If they have the same tuples, we can compare the version tags.
(rTags, vTags) -> matchesTags range rTags vTags
(Nothing, []) -> matchesSimple range version
(Just rTags, vTags)
| rTags == vTags -> matchesSimple range version
| tuplesOf range /= [toTuple version] -> False
| otherwise -> matchesTags range rTags vTags
(_, _) -> False

-- | Simple predicate calculus matching, doing AND and OR combination with
-- numerical comparison.
Expand Down
14 changes: 12 additions & 2 deletions src/Data/SemVer/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{-# LANGUAGE LambdaCase #-}
module Data.SemVer.Parser (
parseSemVer, parseSemVerRange, pSemVerRange, pSemVer,
fromHaskellVersion
fromHaskellVersion, matchText
) where

import qualified Prelude as P
Expand Down Expand Up @@ -107,7 +107,7 @@ pWildCard = try $ do
tag = fmap pack $ many1 $ letter <|> digit <|> char '-'
-- Versions can optionally start with the character 'v'
optional (char 'v')
takeWhile isJust <$> sepBy1 bound (sstring ".") >>= \case
res <- takeWhile isJust <$> sepBy1 bound (sstring ".") >>= \case
[] -> return Any
[Just n] -> return $ One n
[Just n, Just m] -> return $ Two n m
Expand All @@ -116,6 +116,7 @@ pWildCard = try $ do
tags <- tag `sepBy1` char '.'
return $ Three n m o tags
w -> unexpected ("Invalid version " ++ show w)
spaces *> return res

-- | Parses a tilde range (~1.2.3).
pTildeRange :: Parser Wildcard
Expand Down Expand Up @@ -143,3 +144,12 @@ fromHaskellVersion v = case versionBranch v of
bad -> do
let badVer = intercalate "." (map show bad)
Left $ pack ("Not a SemVer version: " <> badVer)

-- | Parses the first argument as a range and the second argument as a semver,
-- and returns whether they match.
matchText :: Text -> Text -> Either Text Bool
matchText rangeTxt verTxt = case parseSemVerRange rangeTxt of
Left err -> Left ("Could not parse range: " <> pack (show err))
Right range -> case parseSemVer verTxt of
Left err -> Left ("Could not parse version: " <> pack (show err))
Right version -> Right $ matches range version

0 comments on commit ccd118d

Please sign in to comment.