Copyright | 2021 Thomas Bidne |
---|---|
License | BSD-3-Clause |
Stability | experimental |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This module provides functionality for reading a package's version
at compile-time, along with a type representing PVP version numbers.
If only the former is of interest then see packageVersionStringTH
, as
this is likely the most useful function.
The doctest examples use -XOverloadedLists
.
Since: 0.1.0.0
Synopsis
- newtype PackageVersion = MkPackageVersion {}
- mkPackageVersion :: [Int] -> Either ValidationError PackageVersion
- mkPackageVersionTH :: [Int] -> Code Q PackageVersion
- unsafePackageVersion :: HasCallStack => [Int] -> PackageVersion
- fromVersion :: Version -> Either ValidationError PackageVersion
- fromString :: String -> Either ReadStringError PackageVersion
- fromText :: Text -> Either ReadStringError PackageVersion
- toVersion :: PackageVersion -> Version
- toString :: PackageVersion -> String
- toText :: PackageVersion -> Text
- packageVersionTH :: FilePath -> Code Q PackageVersion
- packageVersionStringTH :: FilePath -> Code Q String
- packageVersionTextTH :: FilePath -> Code Q Text
- packageVersionThrowIO :: FilePath -> IO PackageVersion
- packageVersionStringIO :: FilePath -> IO String
- packageVersionTextIO :: FilePath -> IO Text
- packageVersionEitherIO :: FilePath -> IO (Either ReadFileError PackageVersion)
- data ValidationError
- data ReadStringError
- data ReadFileError
Type
newtype PackageVersion Source #
PackageVersion
represents PVP version
numbers. It is similar to Data.Version's Version
except:
PackageVersion
has noversionTags
.We enforce PVP invariants i.e.
- Tags must have at least one component.
- All components >= 0.
- Trailing zeroes are ignored in
Eq
,Ord
,Semigroup
, andMonoid
.
That is, we declare an equivalence class up to trailing zeroes.
In particular, the Monoid
identity is
[0] = { [0], [0,0], [0,0,0], ... }
and its Semigroup
instance takes the greatest version (based on Ord
).
Note: Because we export the underlying list in various ways,
(e.g. show
), Eq
's extensionality law,
x == y ==> f x == f y
can be broken. Take care that you do not rely on this law if you are
using its underlying NonEmpty
(or Word
String
) representation.
Examples
>>>
MkPackageVersion [0,0,0,0] == MkPackageVersion [0,0,0]
True
>>>
MkPackageVersion [4,0,0] > MkPackageVersion [1,2,0,0]
True
>>>
MkPackageVersion [5,6,0] <> MkPackageVersion [9,0,0]
MkPackageVersion {unPackageVersion = 9 :| [0,0]}
>>>
MkPackageVersion [0,9] <> MkPackageVersion [0,9,0,0]
MkPackageVersion {unPackageVersion = 0 :| [9]}
Since: 0.1.0.0
MkPackageVersion | |
|
Instances
Creation
mkPackageVersion :: [Int] -> Either ValidationError PackageVersion Source #
Constructs a PackageVersion
from an Int
list. The list must be
non-empty to match PVP's minimal A. Furthermore, all digits must be
non-negative.
Examples
>>>
mkPackageVersion [1,2]
Right (MkPackageVersion {unPackageVersion = 1 :| [2]})
>>>
mkPackageVersion [2,87,7,1]
Right (MkPackageVersion {unPackageVersion = 2 :| [87,7,1]})
>>>
mkPackageVersion [1,2,-3,-4,5]
Left (ValidationErrorNegative (-3))
>>>
mkPackageVersion [3]
Right (MkPackageVersion {unPackageVersion = 3 :| []})
>>>
mkPackageVersion []
Left ValidationErrorEmpty
Since: 0.1.0.0
mkPackageVersionTH :: [Int] -> Code Q PackageVersion Source #
Safely constructs a PackageVersion
at compile-time. If you know that
your input satisfies both invariants (non-empty and non-negative) at
compile-time, consider using the MkPackageVersion
constructor directly.
Examples
>>>
$$(mkPackageVersionTH [2,4,0])
MkPackageVersion {unPackageVersion = 2 :| [4,0]}
Since: 0.1.0.0
unsafePackageVersion :: HasCallStack => [Int] -> PackageVersion Source #
Unsafe version of mkPackageVersion
, intended to be used with
known constants. Maybe you should use mkPackageVersionTH
or
MkPackageVersion
?
WARNING: This function is not total. Exercise restraint!
Examples
>>>
unsafePackageVersion [1,2,3]
MkPackageVersion {unPackageVersion = 1 :| [2,3]}
Since: 0.1.0.0
fromVersion :: Version -> Either ValidationError PackageVersion Source #
Creates a PackageVersion
from Version
.
Note: Because PackageVersion
does not have a versionTags
,
fromVersion
is not injective even on "well-formed" Version
s
(i.e. non-negative and length > 1). That is,
is not an isomorphism.toVersion
. fromVersion
Examples
>>>
fromVersion (Version [2,13,0] ["alpha"])
Right (MkPackageVersion {unPackageVersion = 2 :| [13,0]})
>>>
fromVersion (Version [] [])
Left ValidationErrorEmpty
Since: 0.1.0.0
fromString :: String -> Either ReadStringError PackageVersion Source #
Attempts to read a String
into a PackageVersion
. Leading and/or
trailing dots will result in an error, as will the empty string.
Examples
>>>
fromString "1.4.27.3"
Right (MkPackageVersion {unPackageVersion = 1 :| [4,27,3]})
>>>
fromString ""
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromString "1.a.2"
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromString ".1.2"
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromString "1.2."
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromString "-3.1.2"
Left (ReadStringErrorValidate (ValidationErrorNegative (-3)))
Since: 0.1.0.0
fromText :: Text -> Either ReadStringError PackageVersion Source #
Attempts to read a Text
into a PackageVersion
. Leading and/or
trailing dots will result in an error, as will the empty string.
Examples
>>>
fromText "1.4.27.3"
Right (MkPackageVersion {unPackageVersion = 1 :| [4,27,3]})
>>>
fromText ""
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText "1.a.2"
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText ".1.2"
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText "1.2."
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText ""
Left (ReadStringErrorParse "Prelude.read: no parse")
>>>
fromText "-3.1.2"
Left (ReadStringErrorValidate (ValidationErrorNegative (-3)))
Since: 0.1.0.0
Elimination
toVersion :: PackageVersion -> Version Source #
Creates a Version
with empty versionTags
from
PackageVersion
.
Examples
>>>
toVersion (MkPackageVersion [3,2,0])
Version {versionBranch = [3,2,0], versionTags = []}
Since: 0.1.0.0
toString :: PackageVersion -> String Source #
Displays PackageVersion
in String
format.
Examples
>>>
toString (MkPackageVersion [2,7,10,0])
"2.7.10.0"
Since: 0.1.0.0
toText :: PackageVersion -> Text Source #
Displays PackageVersion
in Text
format.
Examples
>>>
toText (MkPackageVersion [2,7,10,0])
"2.7.10.0"
Since: 0.1.0.0
Reading Cabal Files
TemplateHaskell
These functions allow for reading a cabal's version at compile-time. If
the intention is to simply read the value so it can be printed during
runtime (e.g. for an executable's --version
flag), then
packageVersionStringTH
(or packageVersionTextTH
) is the best choice,
as any errors encountered will not prevent compilation.
packageVersionTH :: FilePath -> Code Q PackageVersion Source #
TemplateHaskell for reading the cabal file's version at compile-time. Errors encountered will be returned as compilation errors.
Examples
>>>
$$(packageVersionTH "package-version.cabal")
MkPackageVersion {unPackageVersion = 0 :| [4]}
Since: 0.1.0.0
packageVersionStringTH :: FilePath -> Code Q String Source #
Version of packageVersionTH
that returns a String
representation of
PackageVersion
at compile-time. Returns "UNKNOWN"
if any errors are
encountered.
Examples
>>>
$$(packageVersionStringTH "package-version.cabal")
"0.4"
>>>
$$(packageVersionStringTH "not-found.cabal")
"UNKNOWN"
Since: 0.1.0.0
packageVersionTextTH :: FilePath -> Code Q Text Source #
Version of packageVersionTH
that returns a Text
representation of
PackageVersion
at compile-time. Returns "UNKNOWN"
if any errors are
encountered.
Examples
>>>
$$(packageVersionTextTH "package-version.cabal")
"0.4"
>>>
$$(packageVersionTextTH "not-found.cabal")
"UNKNOWN"
Since: 0.1.0.0
IO
packageVersionThrowIO :: FilePath -> IO PackageVersion Source #
Version of packageVersionEitherIO
that throws an
Exception
if any errors are encountered.
Examples
>>>
packageVersionThrowIO "package-version.cabal"
MkPackageVersion {unPackageVersion = 0 :| [4]}
Since: 0.1.0.0
packageVersionStringIO :: FilePath -> IO String Source #
Version of packageVersionEitherIO
that returns a String
representation of
PackageVersion
at runtime. Returns "UNKNOWN"
if any errors are
encountered.
Examples
>>>
packageVersionStringIO "package-version.cabal"
"0.4"
>>>
packageVersionStringIO "not-found.cabal"
"UNKNOWN"
Since: 0.1.0.0
packageVersionTextIO :: FilePath -> IO Text Source #
Version of packageVersionEitherIO
that returns a Text
representation of
PackageVersion
at runtime. Returns "UNKNOWN"
if any errors are
encountered.
Examples
>>>
packageVersionTextIO "package-version.cabal"
"0.4"
>>>
packageVersionTextIO "not-found.cabal"
"UNKNOWN"
Since: 0.1.0.0
packageVersionEitherIO :: FilePath -> IO (Either ReadFileError PackageVersion) Source #
Reads the cabal-file's version.
Examples
>>>
packageVersionEitherIO "package-version.cabal"
Right (MkPackageVersion {unPackageVersion = 0 :| [4]})
Since: 0.1.0.0
Errors
data ValidationError Source #
Errors that can occur when validating PVP version numbers.
Since: 0.1.0.0
ValidationErrorEmpty | PVP version number cannot be empty. Since: 0.3 |
ValidationErrorNegative Int | PVP version numbers cannot be negative. Since: 0.2 |
Instances
data ReadStringError Source #
Errors that can occur when reading PVP version numbers.
Since: 0.1.0.0
ReadStringErrorParse String | Error when parsing a string. Since: 0.2 |
ReadStringErrorValidate ValidationError | Validation error. Since: 0.2 |
Instances
data ReadFileError Source #
Errors that can occur when reading PVP version numbers from a file.
Since: 0.1.0.0
ReadFileErrorGeneral String | General error when reading a file. Since: 0.2 |
ReadFileErrorVersionNotFound FilePath | Error for missing version. Since: 0.2 |
ReadFileErrorReadString ReadStringError | Read/Validation error. Since: 0.2 |