|
11 | 11 | import TSCBasic
|
12 | 12 |
|
13 | 13 | /// A struct representing a semver version.
|
14 |
| -public struct Version: Hashable { |
| 14 | +public struct Version { |
15 | 15 |
|
16 | 16 | /// The major version.
|
17 | 17 | public let major: Int
|
@@ -45,7 +45,7 @@ public struct Version: Hashable {
|
45 | 45 | }
|
46 | 46 | }
|
47 | 47 |
|
48 |
| -extension Version: Comparable { |
| 48 | +extension Version: Comparable, Hashable { |
49 | 49 |
|
50 | 50 | func isEqualWithoutPrerelease(_ other: Version) -> Bool {
|
51 | 51 | return major == other.major && minor == other.minor && patch == other.patch
|
@@ -95,6 +95,14 @@ extension Version: Comparable {
|
95 | 95 | return lhs.prereleaseIdentifiers.count < rhs.prereleaseIdentifiers.count
|
96 | 96 | }
|
97 | 97 |
|
| 98 | + // Custom `Equatable` conformance leads to custom `Hashable` conformance. |
| 99 | + // [SR-11588](https://bugs.swift.org/browse/SR-11588) |
| 100 | + public func hash(into hasher: inout Hasher) { |
| 101 | + hasher.combine(major) |
| 102 | + hasher.combine(minor) |
| 103 | + hasher.combine(patch) |
| 104 | + hasher.combine(prereleaseIdentifiers) |
| 105 | + } |
98 | 106 | }
|
99 | 107 |
|
100 | 108 | extension Version: CustomStringConvertible {
|
@@ -138,22 +146,22 @@ extension Version: LosslessStringConvertible {
|
138 | 146 | self.minor = minor
|
139 | 147 | self.patch = patch
|
140 | 148 |
|
141 |
| - if prereleaseDelimiterIndex == nil { |
142 |
| - self.prereleaseIdentifiers = [] |
143 |
| - } else { |
144 |
| - let prereleaseStartIndex = prereleaseDelimiterIndex.map(versionString.index(after:)) ?? metadataDelimiterIndex ?? versionString.endIndex |
| 149 | + if let prereleaseDelimiterIndex = prereleaseDelimiterIndex { |
| 150 | + let prereleaseStartIndex = versionString.index(after: prereleaseDelimiterIndex) |
145 | 151 | let prereleaseIdentifiers = versionString[prereleaseStartIndex..<(metadataDelimiterIndex ?? versionString.endIndex)].split(separator: ".", omittingEmptySubsequences: false)
|
146 | 152 | guard prereleaseIdentifiers.allSatisfy( { $0.allSatisfy { $0.isLetter || $0.isNumber || $0 == "-" } } ) else { return nil }
|
147 | 153 | self.prereleaseIdentifiers = prereleaseIdentifiers.map { String($0) }
|
| 154 | + } else { |
| 155 | + self.prereleaseIdentifiers = [] |
148 | 156 | }
|
149 | 157 |
|
150 |
| - if metadataDelimiterIndex == nil { |
151 |
| - self.buildMetadataIdentifiers = [] |
152 |
| - } else { |
153 |
| - let metadataStartIndex = metadataDelimiterIndex.map(versionString.index(after:)) ?? versionString.endIndex |
| 158 | + if let metadataDelimiterIndex = metadataDelimiterIndex { |
| 159 | + let metadataStartIndex = versionString.index(after: metadataDelimiterIndex) |
154 | 160 | let buildMetadataIdentifiers = versionString[metadataStartIndex...].split(separator: ".", omittingEmptySubsequences: false)
|
155 | 161 | guard buildMetadataIdentifiers.allSatisfy( { $0.allSatisfy { $0.isLetter || $0.isNumber || $0 == "-" } } ) else { return nil }
|
156 | 162 | self.buildMetadataIdentifiers = buildMetadataIdentifiers.map { String($0) }
|
| 163 | + } else { |
| 164 | + self.buildMetadataIdentifiers = [] |
157 | 165 | }
|
158 | 166 | }
|
159 | 167 | }
|
|
0 commit comments