semver (Semantic Version) Swift µFramework.
A µ-framework for representing, comparing, encoding and utilizing semantic versions, eg.
1.2.3or
2.0.0-beta.
This is
Version.swiftfrom the Swift Package Manager, with some minor adjustments:
Codableimplementation †
LosslessStringConvertible‡
Bundleand
ProcessInfo
ExpressibleByStringLiteralconformance
10.0or
v3
Range
StringProtocol, not just
String
We have automatic monitoring for changes at Apple’s repo to alert us if we should need merge any fixes.
† Semantic versions can be losslessly expressed as strings; thus we do so.
‡ LikeIntwe can losslessly store a semantic version from a valid string, so we conform to the same protocol.
Hey there, I’m Max Howell. I’m a prolific producer of open source software and probably you already use some of it (for example, I created
brew). I work full-time on open source and it’s hard; currently I earn less than minimum wage. Please help me continue my work, I appreciate it 🙏🏻
Other ways to say thanks.
import Version
// these two initializers are the same, use whichever suits the code context let v1 = Version(1,0,0) let v2 = Version(major: 1, minor: 0, patch: 0)
let v3 = Version("1.2.3") // => 1.2.3: Version? let v4 = Version(tolerant: "10.1") // => 10.1.0: Version? let v5 = Version(tolerant: "10") // => 10.0.0: Version?
// a real Version object from your app’s Info.plist let v6 = Bundle.main.version
let range = Version(1,2,3).. Version(0,0,0)
let foo = Version(1,2,3) < Version(2,0,0) // => true
SwiftPM:
package.append(.package(url: "", from: "2.0.0"))
Carthage:
Waiting on: @Carthage#1945.
Ranges work as you expect, but there are caveats for prerelease identifiers, here are the rules:
1.0.0..<2.0.0does not include eg.2.0.0-alpha
This is probably what you expected. However:
1.0.0..<2.0.0also does not include eg.1.5.0-alpha
However:
1.0.0..<2.0.0-betadoes include eg.2.0.0-alpha
This is how the majority of Semantic Version libraries work.
Both comparable and equatable ignore build metadata as per the specification. Thus:
Version("1.2.3+14") == Version("1.2.3+15") // => true Version("1.2.3+14") <= Version("1.2.3+15") // => true Version("1.2.3+14") < Version("1.2.3+15") // => false
This also means that
Hashablemust mirror this behavior, thus:
dict[Version("1.2.3+14")] = 1 dict[Version("1.2.3+15")] = 2 dict.count // => 1 dict // => ["1.2.3+15": 2]
Be aware of this as it may catch you out, naturally this will also effect structures that depend on
Hashable, eg.
Set.