Skip to content

Commit e970f79

Browse files
authored
xcparse logs does not include logs for App target (#35)
Change Description: These changes fix #33 & modify the logs subcommand so that it now will include the Diagnostics folder (which has things like the app target logs for specific test runs on individual simulators). As there can be multiple Diagnostics folder (one per action), we've adopted a folder structure that is similar to Xcode 10 xcresult where we will number & tag the action name ("1_Run", "2_Test", etc.). The log text file we used to output is now put into this folder structure, in addition to any Diagnostics directory & files associated with that action. Test Plan/Testing Performed: Tested with these changes that I can now get the Diagnostics folder for various test actions & have them properly divided by folders. Also confirmed that change to create destination directory works for the codecov & logs subcommands.
1 parent 9d0c482 commit e970f79

5 files changed

Lines changed: 42 additions & 17 deletions

File tree

Docs/Images/screenshots_logs.png

1020 KB
Loading

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ This will export the action.xccovreport & action.xccovarchive into your output d
108108
xcparse logs /path/to/Test.xcresult /path/to/exportLogFiles
109109
```
110110

111+
This will export logs & diagnostic files into a per-action folder structure similar to Xcode 10's xcresult format.
112+
113+
![Logs exported into folders](Docs/Images/screenshots_logs.png?raw=true)
114+
111115
### Help
112116

113117
```

Sources/XCParseCore/Console.swift

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,6 @@ open class Console {
3737
}
3838
}
3939

40-
public func printInteractiveUsage() {
41-
writeMessage("usage (interactive mode): xcparse\n")
42-
writeMessage("Interactive Mode only accepts a single option at a time.\n")
43-
writeMessage(" -s, --screenshots : Extracts screenshots from xcresult file at xcresultPath and saves it in destination folder.")
44-
writeMessage(" -x, --xcov : Extracts coverage from xcresult file at xcresultPath and saves it in destination folder.")
45-
writeMessage(" -l, --logs : Extracts logs from xcresult file at xcresultPath and saves them to destination folder.")
46-
writeMessage(" -v, --verbose : Run in verbose mode.")
47-
writeMessage(" -h, --help : Prints usage message.")
48-
writeMessage(" -q, --quit : Exits interactive mode. Cannot be used in static mode.")
49-
}
50-
5140
// MARK: -
5241
// MARK: Shell
5342
@discardableResult public func shellCommand(_ command: [String]) -> String {

Sources/xcparse/LogsCommand.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import SPMUtility
1212

1313
struct LogsCommand: Command {
1414
let command = "logs"
15-
let overview = "Extracts logs from xcresult and saves it in output folder."
15+
let overview = "Extracts logs & diagnostics from xcresult and saves it in output folder."
1616
let usage = "[OPTIONS] xcresult [outputDirectory]"
1717

1818
var path: PositionalArgument<PathArgument>

Sources/xcparse/XCPParser.swift

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Foundation
1111
import SPMUtility
1212
import XCParseCore
1313

14-
let xcparseCurrentVersion = Version(1, 0, 1)
14+
let xcparseCurrentVersion = Version(2, 0, 0)
1515

1616
extension Foundation.URL {
1717
func fileExistsAsDirectory() -> Bool {
@@ -303,6 +303,12 @@ class XCPParser {
303303
guard let invocationRecord = xcresult.invocationRecord else {
304304
return
305305
}
306+
307+
// Let's make sure the destinations is available
308+
let destinationURL = URL.init(fileURLWithPath: destination)
309+
if destinationURL.createDirectoryIfNecessary() != true {
310+
return
311+
}
306312

307313
var coverageReferenceIDs: [String] = []
308314
var coverageArchiveIDs: [String] = []
@@ -331,7 +337,33 @@ class XCPParser {
331337
return
332338
}
333339

340+
let xcresulttoolCompatability = self.checkXCResultToolCompatability(destination: destination)
341+
if xcresulttoolCompatability.supportsExport != true {
342+
return
343+
}
344+
345+
// Let's make sure the destinations is available
346+
let destinationURL = URL.init(fileURLWithPath: destination)
347+
if destinationURL.createDirectoryIfNecessary() != true {
348+
return
349+
}
350+
334351
for (index, actionRecord) in invocationRecord.actions.enumerated() {
352+
let actionRecordDestinationURL = destinationURL.appendingPathComponent("\(index + 1)_\(actionRecord.schemeCommandName)")
353+
if actionRecordDestinationURL.createDirectoryIfNecessary(createIntermediates: false, console: self.console) != true {
354+
return
355+
}
356+
357+
if let buildDiagnosticsRef = actionRecord.buildResult.diagnosticsRef {
358+
let buildDiagnosticsURL = actionRecordDestinationURL.appendingPathComponent("Diagnostics")
359+
XCResultToolCommand.Export(withXCResult: xcresult, id: buildDiagnosticsRef.id, outputPath: buildDiagnosticsURL.path, type: .directory).run()
360+
}
361+
362+
if let actionDiagnosticsRef = actionRecord.actionResult.diagnosticsRef {
363+
let actionDiagnosticsURL = actionRecordDestinationURL.appendingPathComponent("Diagnostics")
364+
XCResultToolCommand.Export(withXCResult: xcresult, id: actionDiagnosticsRef.id, outputPath: actionDiagnosticsURL.path, type: .directory).run()
365+
}
366+
335367
// TODO: Alex - note that these aren't actually log files but ActivityLogSection objects. User from StackOverflow was just exporting those
336368
// out as text files as for the most party they can be human readable, but it won't match what Xcode exports if you open the XCResult
337369
// and attempt to export out the log. That seems like it may involve having to create our own pretty printer similar to Xcode's to export
@@ -342,15 +374,15 @@ class XCPParser {
342374
if let buildResultLogRef = actionRecord.buildResult.logRef {
343375
// let activityLogSectionJSON = XCResultToolCommand.Get(withXCResult: xcresult, id: buildResultLogRef.id, outputPath: "", format: .json).run()
344376
// let activityLogSection = try decoder.decode(ActivityLogSection.self, from: Data(activityLogSectionJSON.utf8))
345-
346-
XCResultToolCommand.Export(withXCResult: xcresult, id: buildResultLogRef.id, outputPath: "\(destination)/\(index + 1)_build.txt", type: .file).run()
377+
let buildLogURL = actionRecordDestinationURL.appendingPathComponent("build.txt")
378+
XCResultToolCommand.Export(withXCResult: xcresult, id: buildResultLogRef.id, outputPath: buildLogURL.path, type: .file).run()
347379
}
348380

349381
if let actionResultLogRef = actionRecord.actionResult.logRef {
350382
// let activityLogSectionJSON = XCResultToolCommand.Get(withXCResult: xcresult, id: actionResultLogRef.id, outputPath: "", format: .json).run()
351383
// let activityLogSection = try decoder.decode(ActivityLogSection.self, from: Data(activityLogSectionJSON.utf8))
352-
353-
XCResultToolCommand.Export(withXCResult: xcresult, id: actionResultLogRef.id, outputPath: "\(destination)/\(index + 1)_action.txt", type: .file).run()
384+
let actionLogURL = actionRecordDestinationURL.appendingPathComponent("action.txt")
385+
XCResultToolCommand.Export(withXCResult: xcresult, id: actionResultLogRef.id, outputPath: actionLogURL.path, type: .file).run()
354386
}
355387
}
356388
}

0 commit comments

Comments
 (0)