@@ -49,39 +49,59 @@ public struct PackageIdentity: CustomStringConvertible, Sendable {
4949 PackageIdentity ( value)
5050 }
5151
52- // TODO: formalize package registry identifier
52+ @ available ( * , deprecated , message : " use . registry instead " )
5353 public var scopeAndName : ( scope: Scope , name: Name ) ? {
54- let components = description. split ( separator: " . " , maxSplits: 1 , omittingEmptySubsequences: true )
54+ self . registry. flatMap { ( scope: $0. scope, name: $0. name) }
55+ }
56+
57+ public var registry : RegistryIdentity ? {
58+ let components = self . description. split ( separator: " . " , maxSplits: 1 , omittingEmptySubsequences: true )
5559 guard components. count == 2 ,
5660 let scope = Scope ( components. first) ,
5761 let name = Name ( components. last)
58- else { return . none }
62+ else {
63+ return . none
64+ }
65+
66+ return RegistryIdentity (
67+ scope: scope,
68+ name: name,
69+ underlying: self
70+ )
71+ }
72+
73+ public var isRegistry : Bool {
74+ self . registry != nil
75+ }
5976
60- return ( scope: scope, name: name)
77+ public struct RegistryIdentity {
78+ public let scope : PackageIdentity . Scope
79+ public let name : PackageIdentity . Name
80+ public let underlying : PackageIdentity
6181 }
6282}
6383
6484extension PackageIdentity : Equatable , Comparable {
6585 private func compare( to other: PackageIdentity ) -> ComparisonResult {
66- return self . description. caseInsensitiveCompare ( other. description)
86+ self . description. caseInsensitiveCompare ( other. description)
6787 }
6888
6989 public static func == ( lhs: PackageIdentity , rhs: PackageIdentity ) -> Bool {
70- return lhs. compare ( to: rhs) == . orderedSame
90+ lhs. compare ( to: rhs) == . orderedSame
7191 }
7292
7393 public static func < ( lhs: PackageIdentity , rhs: PackageIdentity ) -> Bool {
74- return lhs. compare ( to: rhs) == . orderedAscending
94+ lhs. compare ( to: rhs) == . orderedAscending
7595 }
7696
7797 public static func > ( lhs: PackageIdentity , rhs: PackageIdentity ) -> Bool {
78- return lhs. compare ( to: rhs) == . orderedDescending
98+ lhs. compare ( to: rhs) == . orderedDescending
7999 }
80100}
81101
82102extension PackageIdentity : Hashable {
83103 public func hash( into hasher: inout Hasher ) {
84- hasher. combine ( description. lowercased ( ) )
104+ hasher. combine ( self . description. lowercased ( ) )
85105 }
86106}
87107
@@ -116,9 +136,9 @@ extension PackageIdentity {
116136
117137 for (index, character) in zip ( description. indices, description) {
118138 guard character. isASCII,
119- character. isLetter ||
120- character. isNumber ||
121- character == " - "
139+ character. isLetter ||
140+ character. isNumber ||
141+ character == " - "
122142 else {
123143 throw StringError ( " A package scope consists of alphanumeric characters and hyphens. " )
124144 }
@@ -154,25 +174,25 @@ extension PackageIdentity {
154174
155175 private func compare( to other: Scope ) -> ComparisonResult {
156176 // Package scopes are case-insensitive (for example, `mona` ≍ `MONA`).
157- return self . description. caseInsensitiveCompare ( other. description)
177+ self . description. caseInsensitiveCompare ( other. description)
158178 }
159179
160180 public static func == ( lhs: Scope , rhs: Scope ) -> Bool {
161- return lhs. compare ( to: rhs) == . orderedSame
181+ lhs. compare ( to: rhs) == . orderedSame
162182 }
163183
164184 public static func < ( lhs: Scope , rhs: Scope ) -> Bool {
165- return lhs. compare ( to: rhs) == . orderedAscending
185+ lhs. compare ( to: rhs) == . orderedAscending
166186 }
167187
168188 public static func > ( lhs: Scope , rhs: Scope ) -> Bool {
169- return lhs. compare ( to: rhs) == . orderedDescending
189+ lhs. compare ( to: rhs) == . orderedDescending
170190 }
171191
172192 // MARK: - Hashable
173193
174194 public func hash( into hasher: inout Hasher ) {
175- hasher. combine ( description. lowercased ( ) )
195+ hasher. combine ( self . description. lowercased ( ) )
176196 }
177197
178198 // MARK: - ExpressibleByStringLiteral
@@ -197,10 +217,10 @@ extension PackageIdentity {
197217
198218 for (index, character) in zip ( description. indices, description) {
199219 guard character. isASCII,
200- character. isLetter ||
201- character. isNumber ||
202- character == " - " ||
203- character == " _ "
220+ character. isLetter ||
221+ character. isNumber ||
222+ character == " - " ||
223+ character == " _ "
204224 else {
205225 throw StringError ( " A package name consists of alphanumeric characters, underscores, and hyphens. " )
206226 }
@@ -236,25 +256,25 @@ extension PackageIdentity {
236256
237257 private func compare( to other: Name ) -> ComparisonResult {
238258 // Package scopes are case-insensitive (for example, `LinkedList` ≍ `LINKEDLIST`).
239- return self . description. caseInsensitiveCompare ( other. description)
259+ self . description. caseInsensitiveCompare ( other. description)
240260 }
241261
242262 public static func == ( lhs: Name , rhs: Name ) -> Bool {
243- return lhs. compare ( to: rhs) == . orderedSame
263+ lhs. compare ( to: rhs) == . orderedSame
244264 }
245265
246266 public static func < ( lhs: Name , rhs: Name ) -> Bool {
247- return lhs. compare ( to: rhs) == . orderedAscending
267+ lhs. compare ( to: rhs) == . orderedAscending
248268 }
249269
250270 public static func > ( lhs: Name , rhs: Name ) -> Bool {
251- return lhs. compare ( to: rhs) == . orderedDescending
271+ lhs. compare ( to: rhs) == . orderedDescending
252272 }
253273
254274 // MARK: - Hashable
255275
256276 public func hash( into hasher: inout Hasher ) {
257- hasher. combine ( description. lowercased ( ) )
277+ hasher. combine ( self . description. lowercased ( ) )
258278 }
259279
260280 // MARK: - ExpressibleByStringLiteral
@@ -289,9 +309,9 @@ struct PackageIdentityParser {
289309 /// Compute the default name of a package given its location.
290310 public static func computeDefaultName( fromLocation url: String ) -> String {
291311 #if os(Windows)
292- let isSeparator : ( Character ) -> Bool = { $0 == " / " || $0 == " \\ " }
312+ let isSeparator : ( Character ) -> Bool = { $0 == " / " || $0 == " \\ " }
293313 #else
294- let isSeparator : ( Character ) -> Bool = { $0 == " / " }
314+ let isSeparator : ( Character ) -> Bool = { $0 == " / " }
295315 #endif
296316
297317 // Get the last path component of the URL.
@@ -303,7 +323,7 @@ struct PackageIdentityParser {
303323
304324 let separatorIndex = url [ ..< endIndex] . lastIndex ( where: isSeparator)
305325 let startIndex = separatorIndex. map { url. index ( after: $0) } ?? url. startIndex
306- var lastComponent = url [ startIndex..< endIndex]
326+ var lastComponent = url [ startIndex ..< endIndex]
307327
308328 // Strip `.git` suffix if present.
309329 if lastComponent. hasSuffix ( " .git " ) {
@@ -443,8 +463,8 @@ fileprivate let isSeparator: (Character) -> Bool = { $0 == "/" || $0 == "\\" }
443463fileprivate let isSeparator : ( Character ) -> Bool = { $0 == " / " }
444464#endif
445465
446- private extension Character {
447- var isDigit : Bool {
466+ extension Character {
467+ fileprivate var isDigit : Bool {
448468 switch self {
449469 case " 0 " , " 1 " , " 2 " , " 3 " , " 4 " , " 5 " , " 6 " , " 7 " , " 8 " , " 9 " :
450470 return true
@@ -453,31 +473,31 @@ private extension Character {
453473 }
454474 }
455475
456- var isAllowedInURLScheme : Bool {
457- return isLetter || self . isDigit || self == " + " || self == " - " || self == " . "
476+ fileprivate var isAllowedInURLScheme : Bool {
477+ isLetter || self . isDigit || self == " + " || self == " - " || self == " . "
458478 }
459479}
460480
461- private extension String {
481+ extension String {
462482 @discardableResult
463- mutating func removePrefixIfPresent< T: StringProtocol > ( _ prefix: T ) -> Bool {
483+ private mutating func removePrefixIfPresent< T: StringProtocol > ( _ prefix: T ) -> Bool {
464484 guard hasPrefix ( prefix) else { return false }
465485 removeFirst ( prefix. count)
466486 return true
467487 }
468488
469489 @discardableResult
470- mutating func removeSuffixIfPresent< T: StringProtocol > ( _ suffix: T ) -> Bool {
490+ fileprivate mutating func removeSuffixIfPresent< T: StringProtocol > ( _ suffix: T ) -> Bool {
471491 guard hasSuffix ( suffix) else { return false }
472492 removeLast ( suffix. count)
473493 return true
474494 }
475495
476496 @discardableResult
477- mutating func dropSchemeComponentPrefixIfPresent( ) -> String ? {
497+ fileprivate mutating func dropSchemeComponentPrefixIfPresent( ) -> String ? {
478498 if let rangeOfDelimiter = range ( of: " :// " ) ,
479499 self [ startIndex] . isLetter,
480- self [ ..< rangeOfDelimiter. lowerBound] . allSatisfy ( { $0 . isAllowedInURLScheme } )
500+ self [ ..< rangeOfDelimiter. lowerBound] . allSatisfy ( \ . isAllowedInURLScheme)
481501 {
482502 defer { self . removeSubrange ( ..< rangeOfDelimiter. upperBound) }
483503
@@ -488,7 +508,7 @@ private extension String {
488508 }
489509
490510 @discardableResult
491- mutating func dropUserinfoSubcomponentPrefixIfPresent( ) -> ( user: String , password: String ? ) ? {
511+ fileprivate mutating func dropUserinfoSubcomponentPrefixIfPresent( ) -> ( user: String , password: String ? ) ? {
492512 if let indexOfAtSign = firstIndex ( of: " @ " ) ,
493513 let indexOfFirstPathComponent = firstIndex ( where: isSeparator) ,
494514 indexOfAtSign < indexOfFirstPathComponent
@@ -508,7 +528,7 @@ private extension String {
508528 }
509529
510530 @discardableResult
511- mutating func removePortComponentIfPresent( ) -> Bool {
531+ fileprivate mutating func removePortComponentIfPresent( ) -> Bool {
512532 if let indexOfFirstPathComponent = firstIndex ( where: isSeparator) ,
513533 let startIndexOfPort = firstIndex ( of: " : " ) ,
514534 startIndexOfPort < endIndex,
@@ -523,7 +543,7 @@ private extension String {
523543 }
524544
525545 @discardableResult
526- mutating func removeFragmentComponentIfPresent( ) -> Bool {
546+ fileprivate mutating func removeFragmentComponentIfPresent( ) -> Bool {
527547 if let index = firstIndex ( of: " # " ) {
528548 self . removeSubrange ( index... )
529549 }
@@ -532,7 +552,7 @@ private extension String {
532552 }
533553
534554 @discardableResult
535- mutating func removeQueryComponentIfPresent( ) -> Bool {
555+ fileprivate mutating func removeQueryComponentIfPresent( ) -> Bool {
536556 if let index = firstIndex ( of: " ? " ) {
537557 self . removeSubrange ( index... )
538558 }
@@ -541,7 +561,7 @@ private extension String {
541561 }
542562
543563 @discardableResult
544- mutating func replaceFirstOccurenceIfPresent< T: StringProtocol , U: StringProtocol > (
564+ fileprivate mutating func replaceFirstOccurenceIfPresent< T: StringProtocol , U: StringProtocol > (
545565 of string: T ,
546566 before index: Index ? = nil ,
547567 with replacement: U
@@ -556,4 +576,3 @@ private extension String {
556576 return true
557577 }
558578}
559-
0 commit comments