File: Workspace%2BDelegation.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (425 lines) | stat: -rw-r--r-- 17,038 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import struct Basics.AbsolutePath
import struct Basics.Diagnostic
import enum Dispatch.DispatchTimeInterval
import struct Foundation.URL
import class PackageLoading.ManifestLoader
import class PackageModel.Manifest
import struct PackageModel.PackageIdentity
import struct PackageModel.PackageReference
import struct PackageModel.Registry
import class PackageRegistry.RegistryClient
import class PackageRegistry.RegistryDownloadsManager
import class SourceControl.RepositoryManager
import struct SourceControl.RepositorySpecifier
import struct TSCUtility.Version

/// The delegate interface used by the workspace to report status information.
public protocol WorkspaceDelegate: AnyObject {
    /// The workspace is about to load a package manifest (which might be in the cache, or might need to be parsed).
    /// Note that this does not include speculative loading of manifests that may occur during
    /// dependency resolution; rather, it includes only the final manifest loading that happens after a particular
    /// package version has been checked out into a working directory.
    func willLoadManifest(
        packageIdentity: PackageIdentity,
        packagePath: AbsolutePath,
        url: String,
        version: Version?,
        packageKind: PackageReference.Kind
    )
    /// The workspace has loaded a package manifest, either successfully or not. The manifest is nil if an error occurs,
    /// in which case there will also be at least one error in the list of diagnostics (there may be warnings even if a
    /// manifest is loaded successfully).
    func didLoadManifest(
        packageIdentity: PackageIdentity,
        packagePath: AbsolutePath,
        url: String,
        version: Version?,
        packageKind: PackageReference.Kind,
        manifest: Manifest?,
        diagnostics: [Diagnostic],
        duration: DispatchTimeInterval
    )

    /// The workspace is about to compile a package manifest, as reported by the assigned manifest loader. this happens
    /// for non-cached manifests
    func willCompileManifest(packageIdentity: PackageIdentity, packageLocation: String)
    /// The workspace successfully compiled a package manifest, as reported by the assigned manifest loader. this
    /// happens for non-cached manifests
    func didCompileManifest(packageIdentity: PackageIdentity, packageLocation: String, duration: DispatchTimeInterval)

    /// The workspace is about to evaluate (execute) a compiled package manifest, as reported by the assigned manifest
    /// loader. this happens for non-cached manifests
    func willEvaluateManifest(packageIdentity: PackageIdentity, packageLocation: String)
    /// The workspace successfully evaluated (executed) a compiled package manifest, as reported by the assigned
    /// manifest loader. this happens for non-cached manifests
    func didEvaluateManifest(packageIdentity: PackageIdentity, packageLocation: String, duration: DispatchTimeInterval)

    /// The workspace has started fetching this package.
    func willFetchPackage(package: PackageIdentity, packageLocation: String?, fetchDetails: PackageFetchDetails)
    /// The workspace has finished fetching this package.
    func didFetchPackage(
        package: PackageIdentity,
        packageLocation: String?,
        result: Result<PackageFetchDetails, Error>,
        duration: DispatchTimeInterval
    )
    /// Called every time the progress of the package fetch operation updates.
    func fetchingPackage(package: PackageIdentity, packageLocation: String?, progress: Int64, total: Int64?)

    /// The workspace has started updating this repository.
    func willUpdateRepository(package: PackageIdentity, repository url: String)
    /// The workspace has finished updating this repository.
    func didUpdateRepository(package: PackageIdentity, repository url: String, duration: DispatchTimeInterval)

    /// The workspace has finished updating and all the dependencies are already up-to-date.
    func dependenciesUpToDate()

    /// The workspace is about to clone a repository from the local cache to a working directory.
    func willCreateWorkingCopy(package: PackageIdentity, repository url: String, at path: AbsolutePath)
    /// The workspace has cloned a repository from the local cache to a working directory. The error indicates whether
    /// the operation failed or succeeded.
    func didCreateWorkingCopy(
        package: PackageIdentity,
        repository url: String,
        at path: AbsolutePath,
        duration: DispatchTimeInterval
    )

    /// The workspace is about to check out a particular revision of a working directory.
    func willCheckOut(package: PackageIdentity, repository url: String, revision: String, at path: AbsolutePath)
    /// The workspace has checked out a particular revision of a working directory. The error indicates whether the
    /// operation failed or succeeded.
    func didCheckOut(
        package: PackageIdentity,
        repository url: String,
        revision: String,
        at path: AbsolutePath,
        duration: DispatchTimeInterval
    )

    /// The workspace is removing this repository because it is no longer needed.
    func removing(package: PackageIdentity, packageLocation: String?)

    /// Called when the resolver is about to be run.
    func willResolveDependencies(reason: WorkspaceResolveReason)

    /// Called when the resolver begins to be compute the version for the repository.
    func willComputeVersion(package: PackageIdentity, location: String)
    /// Called when the resolver finished computing the version for the repository.
    func didComputeVersion(package: PackageIdentity, location: String, version: String, duration: DispatchTimeInterval)

    /// Called when the Package.resolved file is changed *outside* of libSwiftPM operations.
    ///
    /// This is only fired when activated using Workspace's watchResolvedFile() method.
    func resolvedFileChanged()

    /// The workspace has started downloading a binary artifact.
    func willDownloadBinaryArtifact(from url: String, fromCache: Bool)
    /// The workspace has finished downloading a binary artifact.
    func didDownloadBinaryArtifact(
        from url: String,
        result: Result<(path: AbsolutePath, fromCache: Bool), Error>,
        duration: DispatchTimeInterval
    )
    /// The workspace is downloading a binary artifact.
    func downloadingBinaryArtifact(from url: String, bytesDownloaded: Int64, totalBytesToDownload: Int64?)
    /// The workspace finished downloading all binary artifacts.
    func didDownloadAllBinaryArtifacts()

    // handlers for unsigned and untrusted registry based dependencies
    func onUnsignedRegistryPackage(
        registryURL: URL,
        package: PackageModel.PackageIdentity,
        version: TSCUtility.Version,
        completion: (Bool) -> Void
    )
    func onUntrustedRegistryPackage(
        registryURL: URL,
        package: PackageModel.PackageIdentity,
        version: TSCUtility.Version,
        completion: (Bool) -> Void
    )

    /// The workspace has started updating dependencies
    func willUpdateDependencies()
    /// The workspace has finished updating dependencies
    func didUpdateDependencies(duration: DispatchTimeInterval)

    /// The workspace has started resolving dependencies
    func willResolveDependencies()
    /// The workspace has finished resolving dependencies
    func didResolveDependencies(duration: DispatchTimeInterval)

    /// The workspace has started loading the graph to memory
    func willLoadGraph()
    /// The workspace has finished loading the graph to memory
    func didLoadGraph(duration: DispatchTimeInterval)
}

// FIXME: default implementation until the feature is stable, at which point we should remove this and force the clients to implement
extension WorkspaceDelegate {
    public func onUnsignedRegistryPackage(
        registryURL: URL,
        package: PackageModel.PackageIdentity,
        version: TSCUtility.Version,
        completion: (Bool) -> Void
    ) {
        // true == continue resolution
        // false == stop dependency resolution
        completion(true)
    }

    public func onUntrustedRegistryPackage(
        registryURL: URL,
        package: PackageModel.PackageIdentity,
        version: TSCUtility.Version,
        completion: (Bool) -> Void
    ) {
        // true == continue resolution
        // false == stop dependency resolution
        completion(true)
    }
}

struct WorkspaceManifestLoaderDelegate: ManifestLoader.Delegate {
    private weak var workspaceDelegate: Workspace.Delegate?

    init(workspaceDelegate: Workspace.Delegate) {
        self.workspaceDelegate = workspaceDelegate
    }

    func willLoad(packageIdentity: PackageIdentity, packageLocation: String, manifestPath: AbsolutePath) {
        // handled by workspace directly
    }

    func didLoad(
        packageIdentity: PackageIdentity,
        packageLocation: String,
        manifestPath: AbsolutePath,
        duration: DispatchTimeInterval
    ) {
        // handled by workspace directly
    }

    func willParse(packageIdentity: PackageIdentity, packageLocation: String) {
        // noop
    }

    func didParse(packageIdentity: PackageIdentity, packageLocation: String, duration: DispatchTimeInterval) {
        // noop
    }

    func willCompile(packageIdentity: PackageIdentity, packageLocation: String, manifestPath: AbsolutePath) {
        self.workspaceDelegate?.willCompileManifest(packageIdentity: packageIdentity, packageLocation: packageLocation)
    }

    func didCompile(
        packageIdentity: PackageIdentity,
        packageLocation: String,
        manifestPath: AbsolutePath,
        duration: DispatchTimeInterval
    ) {
        self.workspaceDelegate?.didCompileManifest(
            packageIdentity: packageIdentity,
            packageLocation: packageLocation,
            duration: duration
        )
    }

    func willEvaluate(packageIdentity: PackageIdentity, packageLocation: String, manifestPath: AbsolutePath) {
        self.workspaceDelegate?.willCompileManifest(packageIdentity: packageIdentity, packageLocation: packageLocation)
    }

    func didEvaluate(
        packageIdentity: PackageIdentity,
        packageLocation: String,
        manifestPath: AbsolutePath,
        duration: DispatchTimeInterval
    ) {
        self.workspaceDelegate?.didEvaluateManifest(
            packageIdentity: packageIdentity,
            packageLocation: packageLocation,
            duration: duration
        )
    }
}

struct WorkspaceRepositoryManagerDelegate: RepositoryManager.Delegate {
    private weak var workspaceDelegate: Workspace.Delegate?

    init(workspaceDelegate: Workspace.Delegate) {
        self.workspaceDelegate = workspaceDelegate
    }

    func willFetch(package: PackageIdentity, repository: RepositorySpecifier, details: RepositoryManager.FetchDetails) {
        self.workspaceDelegate?.willFetchPackage(
            package: package,
            packageLocation: repository.location.description,
            fetchDetails: PackageFetchDetails(fromCache: details.fromCache, updatedCache: details.updatedCache)
        )
    }

    func fetching(
        package: PackageIdentity,
        repository: RepositorySpecifier,
        objectsFetched: Int,
        totalObjectsToFetch: Int
    ) {
        self.workspaceDelegate?.fetchingPackage(
            package: package,
            packageLocation: repository.location.description,
            progress: Int64(objectsFetched),
            total: Int64(totalObjectsToFetch)
        )
    }

    func didFetch(
        package: PackageIdentity,
        repository: RepositorySpecifier,
        result: Result<RepositoryManager.FetchDetails, Error>,
        duration: DispatchTimeInterval
    ) {
        self.workspaceDelegate?.didFetchPackage(
            package: package,
            packageLocation: repository.location.description,
            result: result.map { PackageFetchDetails(fromCache: $0.fromCache, updatedCache: $0.updatedCache) },
            duration: duration
        )
    }

    func willUpdate(package: PackageIdentity, repository: RepositorySpecifier) {
        self.workspaceDelegate?.willUpdateRepository(package: package, repository: repository.location.description)
    }

    func didUpdate(package: PackageIdentity, repository: RepositorySpecifier, duration: DispatchTimeInterval) {
        self.workspaceDelegate?.didUpdateRepository(
            package: package,
            repository: repository.location.description,
            duration: duration
        )
    }
}

struct WorkspaceRegistryDownloadsManagerDelegate: RegistryDownloadsManager.Delegate {
    private weak var workspaceDelegate: Workspace.Delegate?

    init(workspaceDelegate: Workspace.Delegate) {
        self.workspaceDelegate = workspaceDelegate
    }

    func willFetch(package: PackageIdentity, version: Version, fetchDetails: RegistryDownloadsManager.FetchDetails) {
        self.workspaceDelegate?.willFetchPackage(
            package: package,
            packageLocation: .none,
            fetchDetails: PackageFetchDetails(
                fromCache: fetchDetails.fromCache,
                updatedCache: fetchDetails.updatedCache
            )
        )
    }

    func didFetch(
        package: PackageIdentity,
        version: Version,
        result: Result<RegistryDownloadsManager.FetchDetails, Error>,
        duration: DispatchTimeInterval
    ) {
        self.workspaceDelegate?.didFetchPackage(
            package: package,
            packageLocation: .none,
            result: result.map { PackageFetchDetails(fromCache: $0.fromCache, updatedCache: $0.updatedCache) },
            duration: duration
        )
    }

    func fetching(package: PackageIdentity, version: Version, bytesDownloaded: Int64, totalBytesToDownload: Int64?) {
        self.workspaceDelegate?.fetchingPackage(
            package: package,
            packageLocation: .none,
            progress: bytesDownloaded,
            total: totalBytesToDownload
        )
    }
}

struct WorkspaceRegistryClientDelegate: RegistryClient.Delegate {
    private weak var workspaceDelegate: Workspace.Delegate?

    init(workspaceDelegate: Workspace.Delegate?) {
        self.workspaceDelegate = workspaceDelegate
    }

    func onUnsigned(registry: Registry, package: PackageIdentity, version: Version, completion: (Bool) -> Void) {
        if let delegate = self.workspaceDelegate {
            delegate.onUnsignedRegistryPackage(
                registryURL: registry.url,
                package: package,
                version: version,
                completion: completion
            )
        } else {
            // true == continue resolution
            // false == stop dependency resolution
            completion(true)
        }
    }

    func onUntrusted(registry: Registry, package: PackageIdentity, version: Version, completion: (Bool) -> Void) {
        if let delegate = self.workspaceDelegate {
            delegate.onUntrustedRegistryPackage(
                registryURL: registry.url,
                package: package,
                version: version,
                completion: completion
            )
        } else {
            // true == continue resolution
            // false == stop dependency resolution
            completion(true)
        }
    }
}

struct WorkspaceBinaryArtifactsManagerDelegate: Workspace.BinaryArtifactsManager.Delegate {
    private weak var workspaceDelegate: Workspace.Delegate?

    init(workspaceDelegate: Workspace.Delegate) {
        self.workspaceDelegate = workspaceDelegate
    }

    func willDownloadBinaryArtifact(from url: String, fromCache: Bool) {
        self.workspaceDelegate?.willDownloadBinaryArtifact(from: url, fromCache: fromCache)
    }

    func didDownloadBinaryArtifact(
        from url: String,
        result: Result<(path: AbsolutePath, fromCache: Bool), Error>,
        duration: DispatchTimeInterval
    ) {
        self.workspaceDelegate?.didDownloadBinaryArtifact(from: url, result: result, duration: duration)
    }

    func downloadingBinaryArtifact(from url: String, bytesDownloaded: Int64, totalBytesToDownload: Int64?) {
        self.workspaceDelegate?.downloadingBinaryArtifact(
            from: url,
            bytesDownloaded: bytesDownloaded,
            totalBytesToDownload: totalBytesToDownload
        )
    }

    func didDownloadAllBinaryArtifacts() {
        self.workspaceDelegate?.didDownloadAllBinaryArtifacts()
    }
}