salve 0.0.1 → 0.0.2
raw patch · 3 files changed
+320/−168 lines, 3 files
Files
- library/Salve.hs +257/−111
- library/Salve/Internal.hs +56/−56
- salve.cabal +7/−1
library/Salve.hs view
@@ -28,12 +28,78 @@ -- -- >>> satisfies <$> parseVersion "1.2.3" <*> parseConstraint ">1.2.0" -- Just True------ == __Examples__------ === Versions++-- * Types+Version,+PreRelease,+Build,+Constraint,++-- * Constructors+makeVersion,+initialVersion,+constraintLT,+constraintLE,+constraintEQ,+constraintGE,+constraintGT,+constraintAnd,+constraintOr,+constraintHyphen,+constraintTilde,+constraintCaret,++-- * Parsing+parseVersion,+parsePreRelease,+parseBuild,+parseConstraint,++-- ** Unsafe+-- | These functions can be used to unsafely parse strings. Instead of+-- returning 'Nothing', they raise an exception. Only use these if you are sure+-- the string can be successfully parsed!+unsafeParseVersion,+unsafeParsePreRelease,+unsafeParseBuild,+unsafeParseConstraint,++-- * Rendering+renderVersion,+renderPreRelease,+renderBuild,+renderConstraint,++-- * Predicates+isUnstable,+isStable,++-- * Helpers+bumpMajor,+bumpMinor,+bumpPatch,+satisfies,++-- * Lenses+-- | These lenses can be used to access and modify specific parts of a+-- 'Version'. ----- No leading zeros.+-- Don't be scared by these type signatures. They are provided in full to avoid+-- the @RankNTypes@ language extension. The type signature+-- @'Functor' f => (a -> f a) -> 'Version' -> f 'Version'@ is the same as+-- @'Lens.Micro.Lens'' 'Version' a@ (from "Lens.Micro"), which you may already+-- be familiar with.+majorLens,+minorLens,+patchLens,+preReleasesLens,+buildsLens,++-- * Examples+-- | TODO++-- ** Versions+-- | Leading zeros are not allowed. -- -- >>> parseVersion "01.0.0" -- Nothing@@ -42,7 +108,7 @@ -- >>> parseVersion "0.0.01" -- Nothing ----- No negative numbers.+-- Negative numbers are not allowed. -- -- >>> parseVersion "-1.0.0" -- Nothing@@ -51,7 +117,7 @@ -- >>> parseVersion "0.0.-1" -- Nothing ----- No non-digits.+-- Non-digits are not allowed. -- -- >>> parseVersion "a.0.0" -- Nothing@@ -60,24 +126,23 @@ -- >>> parseVersion "0.0.a" -- Nothing ----- No partial version numbers.+-- Partial version numbers are not allowed. -- -- >>> parseVersion "0.0" -- Nothing ----- No extra version numbers.+-- Extra version numbers are not allowed. -- -- >>> parseVersion "0.0.0.0" -- Nothing------ === Constraints------ No partial version numbers.++-- ** Constraints+-- | Partial version numbers are not allowed. -- -- >>> parseConstraint "1.2" -- Nothing ----- No wildcards.+-- Wildcards (also known as "x-ranges") are not allowed. -- -- >>> parseConstraint "1.2.x" -- Nothing@@ -86,127 +151,208 @@ -- >>> parseConstraint "1.2.*" -- Nothing ----- Round-tripping.+-- Extra spaces are not allowed. ----- >>> renderConstraint <$> parseConstraint "<=1.2.3"--- Just "<=1.2.3"+-- >>> parseConstraint " 1.2.3 "+-- Nothing+-- >>> parseConstraint "> 1.2.3"+-- Nothing+-- >>> parseConstraint "1.2.3 - 2.3.4"+-- Nothing+-- >>> parseConstraint "1.2.3 2.3.4"+-- Nothing+-- >>> parseConstraint "1.2.3 || 2.3.4"+-- Nothing+--+-- Most constraints can be round-tripped through parsing and rendering.+-- -- >>> renderConstraint <$> parseConstraint "<1.2.3" -- Just "<1.2.3"--- >>> renderConstraint <$> parseConstraint "=1.2.3"+-- >>> renderConstraint <$> parseConstraint "<=1.2.3"+-- Just "<=1.2.3"+-- >>> renderConstraint <$> parseConstraint "1.2.3" -- Just "1.2.3" -- >>> renderConstraint <$> parseConstraint ">=1.2.3" -- Just ">=1.2.3" -- >>> renderConstraint <$> parseConstraint ">1.2.3" -- Just ">1.2.3"+-- >>> renderConstraint <$> parseConstraint "1.2.3 - 2.3.4"+-- Just "1.2.3 - 2.3.4"+-- >>> renderConstraint <$> parseConstraint "~1.2.3"+-- Just "~1.2.3"+-- >>> renderConstraint <$> parseConstraint "^1.2.3"+-- Just "^1.2.3" -- >>> renderConstraint <$> parseConstraint ">1.2.3 <2.0.0" -- Just ">1.2.3 <2.0.0" -- >>> renderConstraint <$> parseConstraint "1.2.3 || >1.2.3" -- Just "1.2.3 || >1.2.3" ----- Implicit equals.+-- Explicit equal signs do not get round-tripped. ----- >>> renderConstraint <$> parseConstraint "1.2.3"+-- >>> renderConstraint <$> parseConstraint "=1.2.3" -- Just "1.2.3" ----- Hyphens.------ >>> renderConstraint <$> parseConstraint "1.2.3 - 2.3.4"--- Just ">=1.2.3 <=2.3.4"------ Tildes.------ >>> renderConstraint <$> parseConstraint "~1.2.3"--- Just ">=1.2.3 <1.3.0"--- >>> renderConstraint <$> parseConstraint "~1.2.0"--- Just ">=1.2.0 <1.3.0"--- >>> renderConstraint <$> parseConstraint "~1.0.0"--- Just ">=1.0.0 <1.1.0"------ Carets.------ >>> renderConstraint <$> parseConstraint "^1.2.3"--- Just ">=1.2.3 <2.0.0"--- >>> renderConstraint <$> parseConstraint "^0.2.3"--- Just ">=0.2.3 <0.3.0"--- >>> renderConstraint <$> parseConstraint "^0.0.3"--- Just ">=0.0.3 <0.0.4"------ Pre-releases and builds.+-- Pre-releases and builds are allowed on any constraints. -- -- >>> renderConstraint <$> parseConstraint "1.2.3-p+b" -- Just "1.2.3-p+b"+-- >>> renderConstraint <$> parseConstraint ">1.2.3-p+b"+-- Just ">1.2.3-p+b" -- >>> renderConstraint <$> parseConstraint "1.2.3-p+b - 2.3.4-p+b"--- Just ">=1.2.3-p+b <=2.3.4-p+b"+-- Just "1.2.3-p+b - 2.3.4-p+b" -- >>> renderConstraint <$> parseConstraint "~1.2.3-p+b"--- Just ">=1.2.3-p+b <1.3.0"+-- Just "~1.2.3-p+b" -- >>> renderConstraint <$> parseConstraint "^1.2.3-p+b"--- Just ">=1.2.3-p+b <2.0.0"---- * Types-Version,-PreRelease,-Build,-Constraint,---- * Constructors-makeVersion,-initialVersion,-constraintLT,-constraintLE,-constraintEQ,-constraintGE,-constraintGT,-constraintAnd,-constraintOr,-constraintHyphen,-constraintTilde,-constraintCaret,---- * Parsing-parseVersion,-parsePreRelease,-parseBuild,-parseConstraint,---- ** Unsafe--- | These functions can be used to unsafely parse strings. Instead of--- returning 'Nothing', they raise an exception. Only use these if you are sure--- the string can be successfully parsed!-unsafeParseVersion,-unsafeParsePreRelease,-unsafeParseBuild,-unsafeParseConstraint,---- * Rendering-renderVersion,-renderPreRelease,-renderBuild,-renderConstraint,---- * Predicates-isUnstable,-isStable,---- * Helpers-bumpMajor,-bumpMinor,-bumpPatch,-satisfies,+-- Just "^1.2.3-p+b"+--+-- These examples show every type of constraint in a single expression.+--+-- >>> renderConstraint <$> parseConstraint "<1.2.0 <=1.2.1 =1.2.2 >=1.2.3 >1.2.4 1.2.5 1.2.6 - 1.2.7 ~1.2.8 ^1.2.9"+-- Just "<1.2.0 <=1.2.1 1.2.2 >=1.2.3 >1.2.4 1.2.5 1.2.6 - 1.2.7 ~1.2.8 ^1.2.9"+-- >>> renderConstraint <$> parseConstraint "<1.2.0 <=1.2.1 || =1.2.2 >=1.2.3 || >1.2.4 1.2.5 || 1.2.6 - 1.2.7 ~1.2.8 || ^1.2.9"+-- Just "<1.2.0 <=1.2.1 || 1.2.2 >=1.2.3 || >1.2.4 1.2.5 || 1.2.6 - 1.2.7 ~1.2.8 || ^1.2.9"+-- >>> renderConstraint <$> parseConstraint "<1.2.0 || <=1.2.1 =1.2.2 || >=1.2.3 >1.2.4 || 1.2.5 1.2.6 - 1.2.7 || ~1.2.8 ^1.2.9"+-- Just "<1.2.0 || <=1.2.1 1.2.2 || >=1.2.3 >1.2.4 || 1.2.5 1.2.6 - 1.2.7 || ~1.2.8 ^1.2.9"+-- >>> renderConstraint <$> parseConstraint "<1.2.0 || <=1.2.1 || =1.2.2 || >=1.2.3 || >1.2.4 || 1.2.5 || 1.2.6 - 1.2.7 || ~1.2.8 || ^1.2.9"+-- Just "<1.2.0 || <=1.2.1 || 1.2.2 || >=1.2.3 || >1.2.4 || 1.2.5 || 1.2.6 - 1.2.7 || ~1.2.8 || ^1.2.9" --- * Lenses--- | These lenses can be used to access and modify specific parts of a--- 'Version'.+-- ** Satisfying constraints+-- | Although in general you should use 'satisfies', 'parseVersion', and+-- 'parseConstraint', doing that here makes it hard to tell what the examples+-- are doing. An operator makes things clearer. ----- Don't be scared by these type signatures. They are provided in full to avoid--- the @RankNTypes@ language extension. The type signature--- @'Functor' f => (a -> f a) -> 'Version' -> f 'Version'@ is the same as--- @'Lens.Micro.Lens'' 'Version' a@ (from "Lens.Micro"), which you may already--- be familiar with.-majorLens,-minorLens,-patchLens,-preReleasesLens,-buildsLens,+-- >>> satisfies <$> parseVersion "1.2.3" <*> parseConstraint "=1.2.3"+-- Just True+-- >>> let version ? constraint = satisfies (unsafeParseVersion version) (unsafeParseConstraint constraint)+-- >>> "1.2.3" ? "=1.2.3"+-- True+--+-- - Less than:+--+-- >>> "1.2.2" ? "<1.2.3"+-- True+-- >>> "1.2.3" ? "<1.2.3"+-- False+-- >>> "1.2.4" ? "<1.2.3"+-- False+-- >>> "1.2.3-pre" ? "<1.2.3"+-- True+--+-- - Less than or equal to:+--+-- >>> "1.2.2" ? "<=1.2.3"+-- True+-- >>> "1.2.3" ? "<=1.2.3"+-- True+-- >>> "1.2.4" ? "<=1.2.3"+-- False+--+-- - Equal to:+--+-- >>> "1.2.2" ? "=1.2.3"+-- False+-- >>> "1.2.3" ? "=1.2.3"+-- True+-- >>> "1.2.4" ? "=1.2.3"+-- False+-- >>> "1.2.3-pre" ? "=1.2.3"+-- False+-- >>> "1.2.3+build" ? "=1.2.3"+-- True+--+-- - Greater than or equal to:+--+-- >>> "1.2.2" ? ">=1.2.3"+-- False+-- >>> "1.2.3" ? ">=1.2.3"+-- True+-- >>> "1.2.4" ? ">=1.2.3"+-- True+--+-- - Greater than:+--+-- >>> "1.2.2" ? ">1.2.3"+-- False+-- >>> "1.2.3" ? ">1.2.3"+-- False+-- >>> "1.2.4" ? ">1.2.3"+-- True+-- >>> "1.2.4-pre" ? ">1.2.3"+-- True+--+-- >>> "1.2.4" ? ">1.2.3-pre"+-- True+--+-- - And:+--+-- >>> "1.2.3" ? ">1.2.3 <1.2.5"+-- False+-- >>> "1.2.4" ? ">1.2.3 <1.2.5"+-- True+-- >>> "1.2.5" ? ">1.2.3 <1.2.5"+-- False+--+-- - Or:+--+-- >>> "1.2.2" ? "1.2.3 || 1.2.4"+-- False+-- >>> "1.2.3" ? "1.2.3 || 1.2.4"+-- True+-- >>> "1.2.4" ? "1.2.3 || 1.2.4"+-- True+-- >>> "1.2.5" ? "1.2.3 || 1.2.4"+-- False+--+-- - Hyphen:+--+-- >>> "1.2.2" ? "1.2.3 - 1.2.4"+-- False+-- >>> "1.2.3" ? "1.2.3 - 1.2.4"+-- True+-- >>> "1.2.4" ? "1.2.3 - 1.2.4"+-- True+-- >>> "1.2.5" ? "1.2.3 - 1.2.4"+-- False+--+-- - Tilde:+--+-- >>> "1.2.2" ? "~1.2.3"+-- False+-- >>> "1.2.3" ? "~1.2.3"+-- True+-- >>> "1.2.4" ? "~1.2.3"+-- True+-- >>> "1.3.0" ? "~1.2.3"+-- False+--+-- - Caret:+--+-- >>> "1.2.2" ? "^1.2.3"+-- False+-- >>> "1.2.3" ? "^1.2.3"+-- True+-- >>> "1.2.4" ? "^1.2.3"+-- True+-- >>> "1.3.0" ? "^1.2.3"+-- True+-- >>> "2.0.0" ? "^1.2.3"+-- False+--+-- >>> "0.2.2" ? "^0.2.3"+-- False+-- >>> "0.2.3" ? "^0.2.3"+-- True+-- >>> "0.2.4" ? "^0.2.3"+-- True+-- >>> "0.3.0" ? "^0.2.3"+-- False+--+-- >>> "0.0.2" ? "^0.0.3"+-- False+-- >>> "0.0.3" ? "^0.0.3"+-- True+-- >>> "0.0.4" ? "^0.0.3"+-- False ) where import Salve.Internal
library/Salve/Internal.hs view
@@ -126,7 +126,8 @@ -- Use 'parseConstraint' to create constraints and 'satisfies' to see if a -- version number satisfies a constraint. data Constraint- = ConstraintCompare Operator Version+ = ConstraintOperator Operator Version+ | ConstraintHyphen Version Version | ConstraintAnd Constraint Constraint | ConstraintOr Constraint Constraint deriving (Eq, Show)@@ -157,103 +158,95 @@ -- | Makes a new constraint that must be less than the version number. -- -- >>> constraintLT <$> parseVersion "1.2.3"--- Just (ConstraintCompare OperatorLT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorLT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) -- >>> parseConstraint "<1.2.3"--- Just (ConstraintCompare OperatorLT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorLT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) constraintLT :: Version -> Constraint-constraintLT v = ConstraintCompare OperatorLT v+constraintLT v = ConstraintOperator OperatorLT v -- | Makes a new constraint that must be less than or euqal to the version -- number. -- -- >>> constraintLE <$> parseVersion "1.2.3"--- Just (ConstraintCompare OperatorLE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorLE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) -- >>> parseConstraint "<=1.2.3"--- Just (ConstraintCompare OperatorLE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorLE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) constraintLE :: Version -> Constraint-constraintLE v = ConstraintCompare OperatorLE v+constraintLE v = ConstraintOperator OperatorLE v -- | Makes a new constraint that must be equal to the version number. -- -- >>> constraintEQ <$> parseVersion "1.2.3"--- Just (ConstraintCompare OperatorEQ (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorEQ (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) -- >>> parseConstraint "=1.2.3"--- Just (ConstraintCompare OperatorEQ (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorEQ (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) constraintEQ :: Version -> Constraint-constraintEQ v = ConstraintCompare OperatorEQ v+constraintEQ v = ConstraintOperator OperatorEQ v -- | Makes a new constraint that must be greater than or equal to the version -- number. -- -- >>> constraintGE <$> parseVersion "1.2.3"--- Just (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) -- >>> parseConstraint ">=1.2.3"--- Just (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) constraintGE :: Version -> Constraint-constraintGE v = ConstraintCompare OperatorGE v+constraintGE v = ConstraintOperator OperatorGE v -- | Makes a new constraint that must be greater than the version number. -- -- >>> constraintGT <$> parseVersion "1.2.3"--- Just (ConstraintCompare OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) -- >>> parseConstraint ">1.2.3"--- Just (ConstraintCompare OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) constraintGT :: Version -> Constraint-constraintGT v = ConstraintCompare OperatorGT v+constraintGT v = ConstraintOperator OperatorGT v -- | Makes a new constraint that must satisfy both constraints. -- -- >>> constraintAnd <$> (constraintGE <$> parseVersion "1.2.3") <*> (constraintLT <$> parseVersion "2.0.0")--- Just (ConstraintAnd (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorLT (Version {versionMajor = 2, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintAnd (ConstraintOperator OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintOperator OperatorLT (Version {versionMajor = 2, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []}))) -- >>> parseConstraint ">=1.2.3 <2.0.0"--- Just (ConstraintAnd (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorLT (Version {versionMajor = 2, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintAnd (ConstraintOperator OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintOperator OperatorLT (Version {versionMajor = 2, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []}))) constraintAnd :: Constraint -> Constraint -> Constraint constraintAnd l r = ConstraintAnd l r -- | Makes a new constraint that must satisfy either constraint. -- -- >>> constraintOr <$> (constraintEQ <$> parseVersion "1.2.3") <*> (constraintGT <$> parseVersion "1.2.3")--- Just (ConstraintOr (ConstraintCompare OperatorEQ (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintOr (ConstraintOperator OperatorEQ (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintOperator OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))) -- >>> parseConstraint "=1.2.3 || >1.2.3"--- Just (ConstraintOr (ConstraintCompare OperatorEQ (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintOr (ConstraintOperator OperatorEQ (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintOperator OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))) constraintOr :: Constraint -> Constraint -> Constraint constraintOr l r = ConstraintOr l r -- | Makes a new constraint that must be between the versions, inclusive. -- -- >>> constraintHyphen <$> parseVersion "1.2.3" <*> parseVersion "2.3.4"--- Just (ConstraintAnd (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorLE (Version {versionMajor = 2, versionMinor = 3, versionPatch = 4, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintHyphen (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}) (Version {versionMajor = 2, versionMinor = 3, versionPatch = 4, versionPreReleases = [], versionBuilds = []})) -- >>> parseConstraint "1.2.3 - 2.3.4"--- Just (ConstraintAnd (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorLE (Version {versionMajor = 2, versionMinor = 3, versionPatch = 4, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintHyphen (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}) (Version {versionMajor = 2, versionMinor = 3, versionPatch = 4, versionPreReleases = [], versionBuilds = []})) constraintHyphen :: Version -> Version -> Constraint-constraintHyphen v w = constraintAnd (constraintGE v) (constraintLE w)+constraintHyphen v w = ConstraintHyphen v w -- | Makes a new constraint that allows changes to the patch version number. -- -- >>> constraintTilde <$> parseVersion "1.2.3"--- Just (ConstraintAnd (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorLT (Version {versionMajor = 1, versionMinor = 3, versionPatch = 0, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintOperator OperatorTilde (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) -- >>> parseConstraint "~1.2.3"--- Just (ConstraintAnd (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorLT (Version {versionMajor = 1, versionMinor = 3, versionPatch = 0, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintOperator OperatorTilde (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) constraintTilde :: Version -> Constraint-constraintTilde v = constraintAnd- (constraintGE v)- (constraintLT (makeVersion (versionMajor v) (versionMinor v + 1) 0 [] []))+constraintTilde v = ConstraintOperator OperatorTilde v -- | Makes a new constraint that allows changes that do not modify the -- left-most non-zero version number. -- -- >>> constraintCaret <$> parseVersion "1.2.3"--- Just (ConstraintAnd (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorLT (Version {versionMajor = 2, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintOperator OperatorCaret (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) -- >>> parseConstraint "^1.2.3"--- Just (ConstraintAnd (ConstraintCompare OperatorGE (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) (ConstraintCompare OperatorLT (Version {versionMajor = 2, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []})))+-- Just (ConstraintOperator OperatorCaret (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) constraintCaret :: Version -> Constraint-constraintCaret v = constraintAnd- (constraintGE v)- (constraintLT (if versionMajor v == 0- then if versionMinor v == 0- then makeVersion (versionMajor v) (versionMinor v) (versionPatch v + 1) [] []- else makeVersion (versionMajor v) (versionMinor v + 1) 0 [] []- else makeVersion (versionMajor v + 1) 0 0 [] []))+constraintCaret v = ConstraintOperator OperatorCaret v -- | Attempts to parse a version. This parser follows [SemVer's -- BNF](https://github.com/mojombo/semver/blob/eb9aac5/semver.md#backusnaur-form-grammar-for-valid-semver-versions).@@ -317,7 +310,7 @@ -- not supported. So you cannot use @1.2.x@ or @>1.2@ as version constraints. -- -- >>> parseConstraint ">1.2.3"--- Just (ConstraintCompare OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}))+-- Just (ConstraintOperator OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})) -- -- Returns 'Nothing' if the parse fails. --@@ -380,7 +373,7 @@ -- | Parses a constraint. -- -- >>> unsafeParseConstraint ">1.2.3"--- ConstraintCompare OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []})+-- ConstraintOperator OperatorGT (Version {versionMajor = 1, versionMinor = 2, versionPatch = 3, versionPreReleases = [], versionBuilds = []}) -- -- Raises an exception if the parse fails. --@@ -441,7 +434,7 @@ -- Just "1.2.3" renderConstraint :: Constraint -> String renderConstraint c = case c of- ConstraintCompare o v ->+ ConstraintOperator o v -> let s = renderVersion v in case o of OperatorLT -> '<' : s@@ -449,6 +442,9 @@ OperatorEQ -> s OperatorGE -> '>' : '=' : s OperatorGT -> '>' : s+ OperatorTilde -> '~' : s+ OperatorCaret -> '^' : s+ ConstraintHyphen l r -> join ' ' [renderVersion l, "-", renderVersion r] ConstraintAnd l r -> join ' ' (map renderConstraint [l, r]) ConstraintOr l r -> join ' ' [renderConstraint l, "||", renderConstraint r] @@ -537,12 +533,22 @@ -- Just True satisfies :: Version -> Constraint -> Bool satisfies v c = case c of- ConstraintCompare o w -> case o of- OperatorLE -> v <= w+ ConstraintOperator o w -> case o of OperatorLT -> v < w+ OperatorLE -> v <= w OperatorEQ -> compare v w == EQ- OperatorGT -> v > w OperatorGE -> v >= w+ OperatorGT -> v > w+ OperatorTilde -> (v >= w) && (v < makeVersion (versionMajor w) (versionMinor w + 1) 0 [] [])+ OperatorCaret ->+ let u =+ if versionMajor w == 0+ then if versionMinor w == 0+ then makeVersion (versionMajor w) (versionMinor w) (versionPatch w + 1) [] []+ else makeVersion (versionMajor w) (versionMinor w + 1) 0 [] []+ else makeVersion (versionMajor w + 1) 0 0 [] []+ in (v >= w) && (v < u)+ ConstraintHyphen l r -> (l <= v) && (v <= r) ConstraintAnd l r -> satisfies v l && satisfies v r ConstraintOr l r -> satisfies v l || satisfies v r @@ -611,6 +617,8 @@ | OperatorEQ | OperatorGE | OperatorGT+ | OperatorTilde+ | OperatorCaret deriving (Eq, Show) -- ** Parsing@@ -672,13 +680,13 @@ constraintsP :: Parser Constraint constraintsP = do- _ <- spacesP cs <- sepBy1P orP constraintP- _ <- spacesP pure (foldr1 constraintOr cs) constraintP :: Parser Constraint-constraintP = choiceP hyphenatedP simplesP+constraintP = do+ cs <- sepBy1P spaceP simpleP+ pure (foldr1 constraintAnd cs) hyphenatedP :: Parser Constraint hyphenatedP = do@@ -687,13 +695,8 @@ w <- versionP pure (constraintHyphen v w) -simplesP :: Parser Constraint-simplesP = do- cs <- sepBy1P spaceP simpleP- pure (foldr1 constraintAnd cs)- simpleP :: Parser Constraint-simpleP = choiceP caretP (choiceP tildeP primitiveP)+simpleP = oneOfP [hyphenatedP, caretP, tildeP, primitiveP] caretP :: Parser Constraint caretP = do@@ -711,7 +714,7 @@ primitiveP = do o <- operatorP v <- versionP- pure (ConstraintCompare o v)+ pure (ConstraintOperator o v) operatorP :: Parser Operator operatorP = oneOfP [leP, geP, ltP, gtP, eqP, pure OperatorEQ]@@ -746,9 +749,6 @@ orP :: Parser String orP = stringP " || "--spacesP :: Parser String-spacesP = manyP spaceP spaceP :: Parser Char spaceP = charP ' '
salve.cabal view
@@ -3,10 +3,12 @@ -- see: https://github.com/sol/hpack name: salve-version: 0.0.1+version: 0.0.2 synopsis: Semantic version numbers and constraints. description: Salve provides semantic version numbers and constraints. category: Distribution+homepage: https://github.com/tfausak/salve#readme+bug-reports: https://github.com/tfausak/salve/issues maintainer: Taylor Fausak license: MIT license-file: LICENSE.markdown@@ -16,6 +18,10 @@ extra-source-files: CHANGELOG.markdown README.markdown++source-repository head+ type: git+ location: https://github.com/tfausak/salve library hs-source-dirs: