Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import PackageDescription

let package = Package(
name: "SemanticVersion",
platforms: [.macOS("13.0")],
products: [
.library(
name: "SemanticVersion",
Expand Down
48 changes: 0 additions & 48 deletions Sources/SemanticVersion/NSRegularExpression+ext.swift

This file was deleted.

4 changes: 4 additions & 0 deletions Sources/SemanticVersion/SemanticVersion+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#if canImport(Foundation)

import Foundation

public enum SemanticVersionStrategy {
Expand Down Expand Up @@ -100,3 +102,5 @@ extension SemanticVersion: Codable {
}
}
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright Dave Verwer, Sven A. Schmidt, and other contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


extension SemanticVersion: LosslessStringConvertible {

/// Initialize a version from a string. Returns `nil` if the string is not a semantic version.
/// - Parameter string: Version string.
public init?(_ string: String) {
guard let match = string.wholeMatch(of: semVerRegex) else { return nil }
guard
let major = Int(match.major),
let minor = Int(match.minor),
let patch = Int(match.patch)
else { return nil }
self = .init(major, minor, patch,
match.prerelease.map(String.init) ?? "",
match.buildmetadata.map(String.init) ?? "")
}

public var description: String {
let pre = preRelease.isEmpty ? "" : "-" + preRelease
let bld = build.isEmpty ? "" : "+" + build
return "\(major).\(minor).\(patch)\(pre)\(bld)"
}
}


// Source: https://regex101.com/r/Ly7O1x/3/
// Linked from https://semver.org
let semVerRegex = #/
^
v? # SPI extension: allow leading 'v'
(?<major>0|[1-9]\d*)
\.
(?<minor>0|[1-9]\d*)
\.
(?<patch>0|[1-9]\d*)
(?:-
(?<prerelease>
(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)
(?:\.
(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)
)
*)
)?
(?:\+
(?<buildmetadata>[0-9a-zA-Z-]+
(?:\.[0-9a-zA-Z-]+)
*)
)?
$
/#
83 changes: 1 addition & 82 deletions Sources/SemanticVersion/SemanticVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation


/// `SemanticVersion` is a struct representing a software or project version according to ["Semantic Versioning"](https://semver.org).
///
Expand Down Expand Up @@ -50,28 +48,6 @@ public struct SemanticVersion: Equatable, Hashable {
}
}

extension SemanticVersion: LosslessStringConvertible {

/// Initialize a version from a string. Returns `nil` if the string is not a semantic version.
/// - Parameter string: Version string.
public init?(_ string: String) {
let groups = semVerRegex.matchGroups(string)
guard
groups.count == semVerRegex.numberOfCaptureGroups,
let major = Int(groups[0]),
let minor = Int(groups[1]),
let patch = Int(groups[2])
else { return nil }
self = .init(major, minor, patch, groups[3], groups[4])
}

public var description: String {
let pre = preRelease.isEmpty ? "" : "-" + preRelease
let bld = build.isEmpty ? "" : "+" + build
return "\(major).\(minor).\(patch)\(pre)\(bld)"
}
}


extension SemanticVersion: Comparable {
public static func < (lhs: SemanticVersion, rhs: SemanticVersion) -> Bool {
Expand Down Expand Up @@ -140,7 +116,7 @@ extension SemanticVersion.PreReleaseIdentifier: Comparable {
}


extension Array: Comparable where Element == SemanticVersion.PreReleaseIdentifier {
extension Array: @retroactive Comparable where Element == SemanticVersion.PreReleaseIdentifier {
public static func < (lhs: Self, rhs: Self) -> Bool {
// Per section 11.4 of the semver spec, compare left to right until a
// difference is found.
Expand All @@ -158,60 +134,3 @@ extension Array: Comparable where Element == SemanticVersion.PreReleaseIdentifie
#if swift(>=5.5)
extension SemanticVersion: Sendable {}
#endif


// Source: https://regex101.com/r/Ly7O1x/3/
// Linked from https://semver.org
#if swift(>=5)

let semVerRegex = NSRegularExpression(#"""
^
v? # SPI extension: allow leading 'v'
(?<major>0|[1-9]\d*)
\.
(?<minor>0|[1-9]\d*)
\.
(?<patch>0|[1-9]\d*)
(?:-
(?<prerelease>
(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)
(?:\.
(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)
)
*)
)?
(?:\+
(?<buildmetadata>[0-9a-zA-Z-]+
(?:\.[0-9a-zA-Z-]+)
*)
)?
$
"""#, options: [.allowCommentsAndWhitespace])

#else

let semVerRegex = NSRegularExpression("""
^
v? # SPI extension: allow leading 'v'
(?<major>0|[1-9]\\d*)
\\.
(?<minor>0|[1-9]\\d*)
\\.
(?<patch>0|[1-9]\\d*)
(?:-
(?<prerelease>
(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)
(?:\\.
(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)
)
*)
)?
(?:\\+
(?<buildmetadata>[0-9a-zA-Z-]+
(?:\\.[0-9a-zA-Z-]+)
*)
)?
$
""", options: [.allowCommentsAndWhitespace])

#endif
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
// Copyright Dave Verwer, Sven A. Schmidt, and other contributors.
//
// SemanticVersionCodingTests.swift
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// Created by Chris Eplett on 11/3/23.
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#if canImport(Foundation)

import XCTest

import SemanticVersion

final class SemanticVersionCodingTests: XCTestCase {
final class SemanticVersionCodableTests: XCTestCase {
func test_defaultCodable_is_default() throws {
XCTAssertEqual(.defaultCodable, JSONEncoder().semanticVersionEncodingStrategy)
XCTAssertEqual(.defaultCodable, JSONDecoder().semanticVersionDecodingStrategy)
Expand Down Expand Up @@ -191,3 +200,5 @@ final class SemanticVersionCodingTests: XCTestCase {
}
}
}

#endif
Loading
Loading