-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPackage.Manager+Resolution.swift
More file actions
69 lines (64 loc) · 2.63 KB
/
Copy pathPackage.Manager+Resolution.swift
File metadata and controls
69 lines (64 loc) · 2.63 KB
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
internal import File_System
private import JSON
public import SPM_Standard
extension Package.Manager {
/// Reads SwiftPM's resolved state for a package.
///
/// Unlike ``manifest(at:)`` and ``evaluation(at:)``, this spawns nothing.
/// Resolved state is a file SwiftPM already wrote, so reading it is an
/// observation rather than an invocation — which also means it is free of
/// the `.build` locking hazard those two carry.
///
/// - Parameters:
/// - directory: The package directory.
/// - scratch: The scratch directory SwiftPM used. Defaults to
/// `<directory>/.build`, which is where an unredirected SwiftPM writes
/// and where the machine coordinator's package actions leave it — the
/// coordinator passes no scratch redirect and runs with the package as
/// the working directory. Supply it explicitly for any build that was
/// redirected, rather than relying on that default holding.
/// - Returns: The resolved state.
/// - Throws: ``Package/Manager/Error``.
public func resolution(
at directory: Swift.String,
scratch: Swift.String? = nil
) throws(Error) -> Package.Resolution {
let path = "\(scratch ?? "\(directory)/.build")/workspace-state.json"
let location: File.Path
do throws(File.Path.Error) {
location = try File.Path(path)
} catch {
throw .state
}
let bytes: [Byte]
// The closure is non-throwing, so `E` infers as `Never` and the
// closure arm of the thrown `Either` is statically uninhabited.
do throws(Either<File.System.Read.Full.Error, Never>) {
bytes = try File(location).read.full { span in
var storage = [Byte]()
storage.reserveCapacity(span.count)
// `span.indices` rather than a `0..<count` counter: the intent
// is "every element of this span", and the counter is only the
// mechanism. A `Span` is non-escapable, so it cannot be handed
// to a closure-taking iteration form.
for index in span.indices {
storage.append(span[index])
}
return storage
}
} catch {
throw .state
}
let json: JSON
do throws(JSON.Error) {
json = try JSON.parse(Swift.String(decoding: bytes, as: UTF8.self))
} catch {
throw .state
}
do throws(DecodingError) {
return try json.decode(Package.Resolution.self)
} catch {
throw .state
}
}
}