How to parse xcrun instruments devices

Issue #558

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
public class GetDestinations {
public init() {}

public func getAvailable(workflow: Workflow) throws -> [Destination] {
let processHandler = DefaultProcessHandler(filter: { $0.starts(with: "name=") })
let string = try CommandLine().runBash(
workflow: workflow,
program: "xcrun instruments",
arguments: [
"-s",
"devices"
],
processHandler: processHandler
)

// Ex: iPad Air (11.0.1) [7A5EAD29-D870-49FB-9A9B-C81079620AC9] (Simulator)
let destinations: [Destination] = try string
.split(separator: "\n")
.map({ String($0) })
.filter({ try $0.hasPattern(pattern: #"\[.+\]"#) })
.compactMap({ (line) -> Destination? in
parse(line)
})

return destinations
}

func parse(_ line: String) -> Destination? {
guard var id = try? line.matches(pattern: #"\[.+\]"#).first else {
return nil
}

var line = line
line = line.replacingOccurrences(of: id, with: "")
id = id
.replacingOccurrences(of: "[", with: "")
.replacingOccurrences(of: "]", with: "")

let isSimulator = line.contains("(Simulator)")
line = line.replacingOccurrences(of: "(Simulator)", with: "")

var os = (try? line.matches(pattern: #"\((\d+\.)?(\d+\.)?(\*|\d+)\)"#).first) ?? ""
let name = line
.replacingOccurrences(of: os, with: "")
.trimmingCharacters(in: .whitespacesAndNewlines)

os = os.replacingOccurrences(of: "(", with: "")
.replacingOccurrences(of: ")", with: "")

let device = self.device(name: name)

if os.isEmpty {
return Destination(name: name, id: id)
} else {
let platform = isSimulator ? "\(device) Simulator" : device
return Destination(name: name, platform: platform, os: os)
}
}

// MARK: - Private

private func device(name: String) -> String {
if name.starts(with: "iPad") || name.starts(with: "iPhone") {
return Destination.Platform.iOS
} else if name.starts(with: "Apple Watch") {
return Destination.Platform.watchOS
} else if name.starts(with: "Apple TV") {
return Destination.Platform.tvOS
} else if name.containsIgnoringCase("mac") {
return Destination.Platform.macOS
} else {
return Destination.Platform.iOS
}
}
}

Comments