Skip to content

Commit 0010bc3

Browse files
committed
Transition away from Foundation.URL
The parser of `NSURL` is changing in macOS Sonoma and will no longer be compatible with the GitHub-style SSH URLs which means we have to transition back to using our own URL type (which is a wrapper of `String` for now) in order to continue to support SSH URLs. rdar://112482783
1 parent 0100d60 commit 0010bc3

39 files changed

+218
-170
lines changed

Sources/Basics/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ add_library(Basics
3131
FileSystem/TemporaryFile.swift
3232
FileSystem/TSCAdapters.swift
3333
FileSystem/VFSOverlay.swift
34+
SourceControlURL.swift
3435
HTTPClient/HTTPClient.swift
3536
HTTPClient/HTTPClientConfiguration.swift
3637
HTTPClient/HTTPClientError.swift
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
public struct SourceControlURL: Codable, Equatable, Hashable, Sendable {
16+
private let urlString: String
17+
18+
public init(stringLiteral: String) {
19+
self.urlString = stringLiteral
20+
}
21+
22+
public init(_ urlString: String) {
23+
self.urlString = urlString
24+
}
25+
26+
public init(_ url: URL) {
27+
self.urlString = url.absoluteString
28+
}
29+
30+
public var absoluteString: String {
31+
return self.urlString
32+
}
33+
34+
public var lastPathComponent: String {
35+
return (self.urlString as NSString).lastPathComponent
36+
}
37+
38+
public var url: URL? {
39+
return URL(string: self.urlString)
40+
}
41+
}
42+
43+
extension SourceControlURL: CustomStringConvertible {
44+
public var description: String {
45+
return self.urlString
46+
}
47+
}
48+
49+
extension SourceControlURL: ExpressibleByStringInterpolation {
50+
}
51+
52+
extension SourceControlURL: ExpressibleByStringLiteral {
53+
}

Sources/PackageCollections/PackageCollections+Validation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ extension PackageCollectionModel.V1 {
8282

8383
// TODO: validate package url?
8484
private func validate(package: Collection.Package, messages: inout [ValidationMessage]) {
85-
let packageID = "\(PackageIdentity(url: package.url).description) (\(package.url.absoluteString))"
85+
let packageID = "\(PackageIdentity(url: SourceControlURL(package.url)).description) (\(package.url.absoluteString))"
8686

8787
guard !package.versions.isEmpty else {
8888
messages.append(.error("Package \(packageID) does not have any versions.", property: "package.versions"))

Sources/PackageCollections/Providers/GitHubPackageMetadataProvider.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider, Closable {
6262
callback: @escaping (Result<Model.PackageBasicMetadata, Error>, PackageMetadataProviderContext?) -> Void
6363
) {
6464
guard let baseURL = Self.apiURL(location) else {
65-
return self.errorCallback(GitHubPackageMetadataProviderError.invalidGitURL(location), apiHost: nil, callback: callback)
65+
return self.errorCallback(GitHubPackageMetadataProviderError.invalidSourceControlURL(location), apiHost: nil, callback: callback)
6666
}
6767

6868
if let cached = try? self.cache?.get(key: identity.description) {
@@ -334,7 +334,7 @@ struct GitHubPackageMetadataProvider: PackageMetadataProvider, Closable {
334334
}
335335

336336
enum GitHubPackageMetadataProviderError: Error, Equatable {
337-
case invalidGitURL(String)
337+
case invalidSourceControlURL(String)
338338
case invalidResponse(URL, String)
339339
case permissionDenied(URL)
340340
case invalidAuthToken(URL)

Sources/PackageCollections/Providers/JSONPackageCollectionProvider.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ struct JSONPackageCollectionProvider: PackageCollectionProvider {
371371

372372
// If package identity is set, use that. Otherwise create one from URL.
373373
return .init(
374-
identity: package.identity.map { PackageIdentity.plain($0) } ?? PackageIdentity(url: package.url),
374+
identity: package.identity.map { PackageIdentity.plain($0) } ?? PackageIdentity(url: SourceControlURL(package.url)),
375375
location: package.url.absoluteString,
376376
summary: package.summary,
377377
keywords: package.keywords,

Sources/PackageFingerprint/FilePackageFingerprintStorage.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,15 +265,14 @@ private enum StorageModel {
265265

266266
let fingerprintsByContentType = try Dictionary(
267267
throwingUniqueKeysWithValues: fingerprintsForKind.map { _, storedFingerprint in
268-
guard let originURL = URL(string: storedFingerprint.origin) else {
269-
throw SerializationError.invalidURL(storedFingerprint.origin)
270-
}
271-
272268
let origin: Fingerprint.Origin
273269
switch kind {
274270
case .sourceControl:
275-
origin = .sourceControl(originURL)
271+
origin = .sourceControl(SourceControlURL(storedFingerprint.origin))
276272
case .registry:
273+
guard let originURL = URL(string: storedFingerprint.origin) else {
274+
throw SerializationError.invalidURL(storedFingerprint.origin)
275+
}
277276
origin = .registry(originURL)
278277
}
279278

Sources/PackageFingerprint/Model.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import struct Foundation.URL
1414

15+
import Basics
1516
import PackageModel
1617
import struct TSCUtility.Version
1718

@@ -34,7 +35,7 @@ extension Fingerprint {
3435
}
3536

3637
public enum Origin: Equatable, CustomStringConvertible {
37-
case sourceControl(URL)
38+
case sourceControl(SourceControlURL)
3839
case registry(URL)
3940

4041
public var kind: Fingerprint.Kind {
@@ -46,12 +47,12 @@ extension Fingerprint {
4647
}
4748
}
4849

49-
public var url: URL? {
50+
public var url: SourceControlURL? {
5051
switch self {
5152
case .sourceControl(let url):
5253
return url
5354
case .registry(let url):
54-
return url
55+
return SourceControlURL(url.absoluteString)
5556
}
5657
}
5758

Sources/PackageGraph/DependencyMirrors.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,8 @@ public final class DependencyMirrors: Equatable {
166166
return PackageIdentity.plain(location)
167167
} else if let path = try? AbsolutePath(validating: location) {
168168
return PackageIdentity(path: path)
169-
} else if let url = URL(string: location) {
170-
return PackageIdentity(url: url)
171169
} else {
172-
throw StringError("invalid location \(location), cannot extract identity")
170+
return PackageIdentity(url: SourceControlURL(location))
173171
}
174172
}
175173
}

Sources/PackageGraph/PinsStore.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -428,10 +428,8 @@ extension PinsStore.Pin {
428428
var packageRef: PackageReference
429429
if let path = try? AbsolutePath(validating: location) {
430430
packageRef = .localSourceControl(identity: identity, path: path)
431-
} else if let url = URL(string: location) {
432-
packageRef = .remoteSourceControl(identity: identity, url: url)
433431
} else {
434-
throw StringError("invalid package location \(location)")
432+
packageRef = .remoteSourceControl(identity: identity, url: SourceControlURL(location))
435433
}
436434
if let newName = pin.package {
437435
packageRef = packageRef.withName(newName)
@@ -466,10 +464,7 @@ extension PinsStore.Pin {
466464
case .localSourceControl:
467465
packageRef = try .localSourceControl(identity: identity, path: AbsolutePath(validating: location))
468466
case .remoteSourceControl:
469-
guard let url = URL(string: location) else {
470-
throw StringError("invalid url location: \(location)")
471-
}
472-
packageRef = .remoteSourceControl(identity: identity, url: url)
467+
packageRef = .remoteSourceControl(identity: identity, url: SourceControlURL(location))
473468
case .registry:
474469
packageRef = .registry(identity: identity)
475470
}

Sources/PackageLoading/ManifestJSONParser.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import PackageModel
1515

1616
import struct Basics.AbsolutePath
1717
import protocol Basics.FileSystem
18+
import struct Basics.SourceControlURL
1819
import struct Basics.InternalError
1920
import struct Basics.RelativePath
2021

@@ -237,7 +238,8 @@ enum ManifestJSONParser {
237238
requirement: requirement,
238239
productFilter: .everything
239240
)
240-
} else if let url = URL(string: location){
241+
} else {
242+
let url = SourceControlURL(location)
241243
// in the future this will check with the registries for the identity of the URL
242244
let identity = try identityResolver.resolveIdentity(for: url)
243245
return .remoteSourceControl(
@@ -247,8 +249,6 @@ enum ManifestJSONParser {
247249
requirement: requirement,
248250
productFilter: .everything
249251
)
250-
} else {
251-
throw StringError("invalid location: \(location)")
252252
}
253253
}
254254

@@ -268,8 +268,9 @@ enum ManifestJSONParser {
268268
productFilter: .everything
269269
)
270270
} else if let url = URL(string: location){
271+
let SourceControlURL = SourceControlURL(url)
271272
// in the future this will check with the registries for the identity of the URL
272-
let identity = try identityResolver.resolveIdentity(for: url)
273+
let identity = try identityResolver.resolveIdentity(for: SourceControlURL)
273274
let sourceControlRequirement: PackageDependency.SourceControl.Requirement
274275
switch requirement {
275276
case .exact(let value):
@@ -280,7 +281,7 @@ enum ManifestJSONParser {
280281
return .remoteSourceControl(
281282
identity: identity,
282283
nameForTargetDependencyResolutionOnly: identity.description,
283-
url: url,
284+
url: SourceControlURL,
284285
requirement: sourceControlRequirement,
285286
productFilter: .everything
286287
)

0 commit comments

Comments
 (0)