Skip to content

Commit 6f52ce9

Browse files
committed
initialization warnings
1 parent ea8d247 commit 6f52ce9

File tree

8 files changed

+97
-35
lines changed

8 files changed

+97
-35
lines changed

Sources/Basics/FileSystem+Extensions.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ extension FileSystem {
8989
}
9090

9191
extension FileSystem {
92-
public func getOrCreateSwiftPMConfigurationDirectory() throws -> AbsolutePath {
92+
public func getOrCreateSwiftPMConfigurationDirectory(warningHandler: (String) -> Void) throws -> AbsolutePath {
9393
let idiomaticConfigurationDirectory = self.swiftPMConfigurationDirectory
9494

9595
// temporary 5.6, remove on next version: transition from previous configuration location
@@ -111,9 +111,7 @@ extension FileSystem {
111111
if !self.exists(destination) {
112112
try self.copy(from: file, to: destination)
113113
}
114-
// FIXME: We should emit a warning here using the diagnostic engine.
115-
TSCBasic.stderrStream.write("warning: Usage of \(file) has been deprecated. Please delete it and use the new \(destination) instead.\n")
116-
TSCBasic.stderrStream.flush()
114+
warningHandler("Usage of \(file) has been deprecated. Please delete it and use the new \(destination) instead.")
117115
}
118116
}
119117
// in the case where ~/.swiftpm/configuration is the idiomatic location (eg on Linux)
@@ -130,9 +128,7 @@ extension FileSystem {
130128
if !self.exists(destination) {
131129
try self.copy(from: file, to: destination)
132130
}
133-
// FIXME: We should emit a warning here using the diagnostic engine.
134-
TSCBasic.stderrStream.write("warning: Usage of \(file) has been deprecated. Please delete it and use the new \(destination) instead.\n")
135-
TSCBasic.stderrStream.flush()
131+
warningHandler("Usage of \(file) has been deprecated. Please delete it and use the new \(destination) instead.")
136132
}
137133
}
138134
}

Sources/Commands/SwiftTool.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ public class SwiftTool {
515515
sharedRepositoriesCacheEnabled: self.options.useRepositoriesCache,
516516
fingerprintCheckingMode: self.options.resolverFingerprintCheckingMode
517517
),
518+
initializationWarningHandler: { self.observabilityScope.emit(warning: $0) },
518519
customManifestLoader: self.getManifestLoader(), // FIXME: ideally we would not customize the manifest loader
519520
customRepositoryProvider: repositoryProvider, // FIXME: ideally we would not customize the repository provider. its currently done for shutdown handling which can be better abstracted
520521
delegate: delegate

Sources/SourceControl/RepositoryManager.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,22 @@ public class RepositoryManager {
7272
/// Create a new empty manager.
7373
///
7474
/// - Parameters:
75+
/// - fileSystem: The filesystem to operate on.
7576
/// - path: The path under which to store repositories. This should be a
7677
/// directory in which the content can be completely managed by this
7778
/// instance.
7879
/// - provider: The repository provider.
80+
/// - cachePath: The repository cache location.
81+
/// - cacheLocalPackages: Should cache local packages as well. For testing purposes.
82+
/// - initializationWarningHandler: Initialization warnings handler.
7983
/// - delegate: The repository manager delegate.
80-
/// - fileSystem: The filesystem to operate on.
8184
public init(
8285
fileSystem: FileSystem,
8386
path: AbsolutePath,
8487
provider: RepositoryProvider,
8588
cachePath: AbsolutePath? = .none,
8689
cacheLocalPackages: Bool = false,
90+
initializationWarningHandler: (String) -> Void,
8791
delegate: RepositoryManagerDelegate? = .none
8892
) {
8993
self.fileSystem = fileSystem
@@ -107,9 +111,7 @@ public class RepositoryManager {
107111
} catch {
108112
self.repositories = [:]
109113
try? self.storage.reset()
110-
// FIXME: We should emit a warning here using the diagnostic engine.
111-
TSCBasic.stderrStream.write("warning: unable to restore checkouts state: \(error)\n")
112-
TSCBasic.stderrStream.flush()
114+
initializationWarningHandler("unable to restore checkouts state: \(error)")
113115
}
114116
}
115117

Sources/Workspace/Workspace.swift

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ public class Workspace {
254254
/// - location: Workspace location configuration.
255255
/// - authorizationProvider: Provider of authentication information for outbound network requests.
256256
/// - configuration: Configuration to fine tune the dependency resolution behavior.
257+
/// - initializationWarningHandler: Initialization warnings handler
257258
/// - customManifestLoader: Custom manifest loader. Used to customize how manifest are loaded.
258259
/// - customPackageContainerProvider: Custom package container provider. Used to provide specialized package providers.
259260
/// - customRepositoryProvider: Custom repository provider. Used to customize source control access.
@@ -263,6 +264,7 @@ public class Workspace {
263264
location: Location,
264265
authorizationProvider: AuthorizationProvider? = .none,
265266
configuration: WorkspaceConfiguration? = .none,
267+
initializationWarningHandler: ((String) -> Void)? = .none,
266268
// optional customization used for advanced integration situations
267269
customManifestLoader: ManifestLoaderProtocol? = .none,
268270
customPackageContainerProvider: PackageContainerProvider? = .none,
@@ -275,6 +277,7 @@ public class Workspace {
275277
location: location,
276278
authorizationProvider: authorizationProvider,
277279
configuration: configuration,
280+
initializationWarningHandler: initializationWarningHandler,
278281
customRegistriesConfiguration: .none,
279282
customFingerprints: .none,
280283
customMirrors: .none,
@@ -303,6 +306,7 @@ public class Workspace {
303306
/// - forRootPackage: The path for the root package.
304307
/// - authorizationProvider: Provider of authentication information for outbound network requests.
305308
/// - configuration: Configuration to fine tune the dependency resolution behavior.
309+
/// - initializationWarningHandler: Initialization warnings handler
306310
/// - customManifestLoader: Custom manifest loader. Used to customize how manifest are loaded.
307311
/// - customPackageContainerProvider: Custom package container provider. Used to provide specialized package providers.
308312
/// - customRepositoryProvider: Custom repository provider. Used to customize source control access.
@@ -312,6 +316,7 @@ public class Workspace {
312316
forRootPackage packagePath: AbsolutePath,
313317
authorizationProvider: AuthorizationProvider? = .none,
314318
configuration: WorkspaceConfiguration? = .none,
319+
initializationWarningHandler: ((String) -> Void)? = .none,
315320
// optional customization used for advanced integration situations
316321
customManifestLoader: ManifestLoaderProtocol? = .none,
317322
customPackageContainerProvider: PackageContainerProvider? = .none,
@@ -324,6 +329,7 @@ public class Workspace {
324329
try self.init(
325330
fileSystem: fileSystem,
326331
location: location,
332+
initializationWarningHandler: initializationWarningHandler,
327333
customManifestLoader: customManifestLoader,
328334
customPackageContainerProvider: customPackageContainerProvider,
329335
customRepositoryProvider: customRepositoryProvider,
@@ -342,6 +348,7 @@ public class Workspace {
342348
/// - forRootPackage: The path for the root package.
343349
/// - authorizationProvider: Provider of authentication information for outbound network requests.
344350
/// - configuration: Configuration to fine tune the dependency resolution behavior.
351+
/// - initializationWarningHandler: Initialization warnings handler
345352
/// - customToolchain: Custom toolchain. Used to create a customized ManifestLoader, customizing how manifest are loaded.
346353
/// - customPackageContainerProvider: Custom package container provider. Used to provide specialized package providers.
347354
/// - customRepositoryProvider: Custom repository provider. Used to customize source control access.
@@ -351,6 +358,7 @@ public class Workspace {
351358
forRootPackage packagePath: AbsolutePath,
352359
authorizationProvider: AuthorizationProvider? = .none,
353360
configuration: WorkspaceConfiguration? = .none,
361+
initializationWarningHandler: ((String) -> Void)? = .none,
354362
// optional customization used for advanced integration situations
355363
customToolchain: UserToolchain,
356364
customPackageContainerProvider: PackageContainerProvider? = .none,
@@ -369,15 +377,14 @@ public class Workspace {
369377
forRootPackage: packagePath,
370378
authorizationProvider: authorizationProvider,
371379
configuration: configuration,
380+
initializationWarningHandler: initializationWarningHandler,
372381
customManifestLoader: manifestLoader,
373382
customPackageContainerProvider: customPackageContainerProvider,
374383
customRepositoryProvider: customRepositoryProvider,
375384
delegate: delegate
376385
)
377386
}
378387

379-
380-
381388
// deprecate 12/21
382389
@_disfavoredOverload
383390
@available(*, deprecated, message: "use alternative initializer")
@@ -418,6 +425,7 @@ public class Workspace {
418425
location: location,
419426
authorizationProvider: authorizationProvider,
420427
configuration: configuration,
428+
initializationWarningHandler: .none,
421429
customRegistriesConfiguration: registries,
422430
customFingerprints: customFingerprintStorage,
423431
customMirrors: mirrors,
@@ -533,6 +541,7 @@ public class Workspace {
533541
location: Location,
534542
authorizationProvider: AuthorizationProvider? = .none,
535543
configuration: WorkspaceConfiguration? = .none,
544+
initializationWarningHandler: ((String) -> Void)? = .none,
536545
// optional customization, primarily designed for testing but also used in some cases by libSwiftPM consumers
537546
customRegistriesConfiguration: RegistryConfiguration? = .none,
538547
customFingerprints: PackageFingerprintStorage? = .none,
@@ -555,6 +564,7 @@ public class Workspace {
555564
location: location,
556565
authorizationProvider: authorizationProvider,
557566
configuration: configuration,
567+
initializationWarningHandler: initializationWarningHandler,
558568
customRegistriesConfiguration: customRegistriesConfiguration,
559569
customFingerprints: customFingerprints,
560570
customMirrors: customMirrors,
@@ -578,6 +588,7 @@ public class Workspace {
578588
location: Location,
579589
authorizationProvider: AuthorizationProvider?,
580590
configuration: WorkspaceConfiguration?,
591+
initializationWarningHandler: ((String) -> Void)?,
581592
// optional customization, primarily designed for testing but also used in some cases by libSwiftPM consumers
582593
customRegistriesConfiguration: RegistryConfiguration?,
583594
customFingerprints: PackageFingerprintStorage?,
@@ -595,11 +606,11 @@ public class Workspace {
595606
// delegate
596607
delegate: WorkspaceDelegate?
597608
) throws {
598-
// we do not store the observabilityScope in the workspace initializer as the workspace is designed to be long lived.
609+
// we do not store an observabilityScope in the workspace initializer as the workspace is designed to be long lived.
599610
// instead, observabilityScope is passed into the individual workspace methods which are short lived.
600-
611+
let initializationWarningHandler = initializationWarningHandler ?? warnToStderr
601612
// validate locations, returning a potentially modified one to deal with non-accessible or non-writable shared locations
602-
let location = try location.validatingSharedLocations(fileSystem: fileSystem)
613+
let location = try location.validatingSharedLocations(fileSystem: fileSystem, warningHandler: initializationWarningHandler)
603614

604615
let currentToolsVersion = customToolsVersion ?? ToolsVersion.currentToolsVersion
605616
let toolsVersionLoader = ToolsVersionLoader(currentToolsVersion: currentToolsVersion)
@@ -623,6 +634,7 @@ public class Workspace {
623634
path: location.repositoriesDirectory,
624635
provider: repositoryProvider,
625636
cachePath: configuration.sharedRepositoriesCacheEnabled ? location.sharedRepositoriesCacheDirectory : .none,
637+
initializationWarningHandler: initializationWarningHandler,
626638
delegate: delegate.map(WorkspaceRepositoryManagerDelegate.init(workspaceDelegate:))
627639
)
628640

@@ -680,7 +692,11 @@ public class Workspace {
680692

681693
self.configuration = configuration
682694

683-
self.state = WorkspaceState(fileSystem: fileSystem, storageDirectory: self.location.workingDirectory)
695+
self.state = WorkspaceState(
696+
fileSystem: fileSystem,
697+
storageDirectory: self.location.workingDirectory,
698+
initializationWarningHandler: initializationWarningHandler
699+
)
684700
}
685701
}
686702

@@ -4014,16 +4030,16 @@ extension FileSystem {
40144030
}
40154031

40164032
extension Workspace.Location {
4017-
func validatingSharedLocations(fileSystem: FileSystem) throws -> Self {
4033+
func validatingSharedLocations(
4034+
fileSystem: FileSystem,
4035+
warningHandler: (String) -> Void
4036+
) throws -> Self {
40184037
var location = self
40194038

4020-
// local configuration directory must be accessible, throw if we cannot access it
4021-
//try fileSystem.withLock(on: location.localConfigurationDirectory, type: .exclusive, {})
4022-
40234039
// check that shared configuration directory is accessible, or warn + reset if not
40244040
if let sharedConfigurationDirectory = self.sharedConfigurationDirectory {
40254041
// it may not always be possible to create default location (for example de to restricted sandbox)
4026-
let defaultDirectory = try? fileSystem.getOrCreateSwiftPMConfigurationDirectory()
4042+
let defaultDirectory = try? fileSystem.getOrCreateSwiftPMConfigurationDirectory(warningHandler: warningHandler)
40274043
if sharedConfigurationDirectory != defaultDirectory {
40284044
// custom location must be writable, throw if we cannot access it
40294045
try withTemporaryFile(dir: sharedConfigurationDirectory) { _ in }
@@ -4033,9 +4049,7 @@ extension Workspace.Location {
40334049
try withTemporaryFile(dir: sharedConfigurationDirectory) { _ in }
40344050
} catch {
40354051
location.sharedConfigurationDirectory = .none
4036-
// FIXME: We should emit a warning here using the diagnostic engine.
4037-
TSCBasic.stderrStream.write("warning: \(sharedConfigurationDirectory) is not accessible or not writable, disabling user-level configuration features. \(error)\n")
4038-
TSCBasic.stderrStream.flush()
4052+
warningHandler("\(sharedConfigurationDirectory) is not accessible or not writable, disabling user-level configuration features. \(error)")
40394053
}
40404054
}
40414055
}
@@ -4053,9 +4067,7 @@ extension Workspace.Location {
40534067
try withTemporaryFile(dir: sharedSecurityDirectory) { _ in }
40544068
} catch {
40554069
location.sharedSecurityDirectory = .none
4056-
// FIXME: We should emit a warning here using the diagnostic engine.
4057-
TSCBasic.stderrStream.write("warning: \(sharedSecurityDirectory) is not accessible or not writable, disabling user-level security features. \(error)\n")
4058-
TSCBasic.stderrStream.flush()
4070+
warningHandler("\(sharedSecurityDirectory) is not accessible or not writable, disabling user-level security features. \(error)")
40594071
}
40604072
}
40614073
}
@@ -4073,12 +4085,15 @@ extension Workspace.Location {
40734085
try withTemporaryFile(dir: sharedCacheDirectory) { _ in }
40744086
} catch {
40754087
location.sharedCacheDirectory = .none
4076-
// FIXME: We should emit a warning here using the diagnostic engine.
4077-
TSCBasic.stderrStream.write("warning: \(sharedCacheDirectory) is not accessible or not writable, disabling user-level cache features. \(error)\n")
4078-
TSCBasic.stderrStream.flush()
4088+
warningHandler("\(sharedCacheDirectory) is not accessible or not writable, disabling user-level cache features. \(error)")
40794089
}
40804090
}
40814091
}
40824092
return location
40834093
}
40844094
}
4095+
4096+
fileprivate func warnToStderr(_ message: String) {
4097+
TSCBasic.stderrStream.write("warning: \(message)\n")
4098+
TSCBasic.stderrStream.flush()
4099+
}

Sources/Workspace/WorkspaceState.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ public final class WorkspaceState {
2929
/// storage
3030
private let storage: WorkspaceStateStorage
3131

32-
init(fileSystem: FileSystem, storageDirectory: AbsolutePath) {
32+
init(
33+
fileSystem: FileSystem,
34+
storageDirectory: AbsolutePath,
35+
initializationWarningHandler: (String) -> Void
36+
) {
3337
self.storagePath = storageDirectory.appending(component: "workspace-state.json")
3438
self.storage = WorkspaceStateStorage(path: self.storagePath, fileSystem: fileSystem)
3539

@@ -49,9 +53,7 @@ public final class WorkspaceState {
4953
self.dependencies = Workspace.ManagedDependencies()
5054
self.artifacts = Workspace.ManagedArtifacts()
5155
try? self.storage.reset()
52-
// FIXME: We should emit a warning here using the diagnostic engine.
53-
TSCBasic.stderrStream.write("warning: unable to restore workspace state: \(error)\n")
54-
TSCBasic.stderrStream.flush()
56+
initializationWarningHandler("unable to restore workspace state: \(error)")
5557
}
5658
}
5759

Tests/SourceControlTests/RepositoryManagerTests.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,25 @@ class RepositoryManagerTests: XCTestCase {
705705
}
706706

707707
extension RepositoryManager {
708+
public convenience init(
709+
fileSystem: FileSystem,
710+
path: AbsolutePath,
711+
provider: RepositoryProvider,
712+
cachePath: AbsolutePath? = .none,
713+
cacheLocalPackages: Bool = false,
714+
delegate: RepositoryManagerDelegate? = .none
715+
) {
716+
self.init(
717+
fileSystem: fileSystem,
718+
path: path,
719+
provider: provider,
720+
cachePath: cachePath,
721+
cacheLocalPackages: cacheLocalPackages,
722+
initializationWarningHandler: { _ in },
723+
delegate: delegate
724+
)
725+
}
726+
708727
fileprivate func lookup(repository: RepositorySpecifier, skipUpdate: Bool = false) throws -> RepositoryHandle {
709728
return try tsc_await { self.lookup(repository: repository, skipUpdate: skipUpdate, on: .global(), completion: $0) }
710729
}

Tests/WorkspaceTests/SourceControlPackageContainerTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,3 +673,24 @@ extension PackageContainerProvider {
673673
try tsc_await { self.getContainer(for: package, skipUpdate: skipUpdate, observabilityScope: ObservabilitySystem.NOOP, on: .global(), completion: $0) }
674674
}
675675
}
676+
677+
extension RepositoryManager {
678+
fileprivate convenience init(
679+
fileSystem: FileSystem,
680+
path: AbsolutePath,
681+
provider: RepositoryProvider,
682+
cachePath: AbsolutePath? = .none,
683+
cacheLocalPackages: Bool = false,
684+
delegate: RepositoryManagerDelegate? = .none
685+
) {
686+
self.init(
687+
fileSystem: fileSystem,
688+
path: path,
689+
provider: provider,
690+
cachePath: cachePath,
691+
cacheLocalPackages: cacheLocalPackages,
692+
initializationWarningHandler: { _ in },
693+
delegate: delegate
694+
)
695+
}
696+
}

Tests/WorkspaceTests/WorkspaceStateTests.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,9 @@ final class WorkspaceStateTests: XCTestCase {
490490
XCTAssertTrue(state.artifacts.isEmpty)
491491
}
492492
}
493+
494+
extension WorkspaceState {
495+
fileprivate convenience init(fileSystem: FileSystem, storageDirectory: AbsolutePath) {
496+
self.init(fileSystem: fileSystem, storageDirectory: storageDirectory, initializationWarningHandler: { _ in })
497+
}
498+
}

0 commit comments

Comments
 (0)