@@ -352,6 +352,36 @@ extension __CommandLineArguments_v0: Codable {
352
352
}
353
353
}
354
354
355
+ extension RandomAccessCollection < String > {
356
+ /// Get the value of the command line argument named at the given index.
357
+ ///
358
+ /// - Parameters:
359
+ /// - key: The key or name of the argument, e.g. `"--attachments-path"`.
360
+ ///
361
+ /// - Returns: The value of the argument named by `key`. If no value is
362
+ /// available, returns `nil`.
363
+ ///
364
+ /// This function handles arguments of the form `--key value` and
365
+ /// `--key=value`. Other argument syntaxes are not supported.
366
+ fileprivate func argumentValue( forKey key: String ) -> String ? {
367
+ if let index = firstIndex ( of: key) {
368
+ let nextIndex = self . index ( after: index)
369
+ if nextIndex < endIndex {
370
+ return self [ nextIndex]
371
+ }
372
+ } else {
373
+ // Find an element equal to something like "--foo=bar" and split it.
374
+ let prefix = " \( key) = "
375
+ let index = self . firstIndex { $0. hasPrefix ( prefix) }
376
+ if let index, case let key = self [ index] , let equalsIndex = key. firstIndex ( of: " = " ) {
377
+ return String ( key [ equalsIndex... ] . dropFirst ( ) )
378
+ }
379
+ }
380
+
381
+ return nil
382
+ }
383
+ }
384
+
355
385
/// Initialize this instance given a sequence of command-line arguments passed
356
386
/// from Swift Package Manager.
357
387
///
@@ -366,10 +396,6 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
366
396
// Do not consider the executable path AKA argv[0].
367
397
let args = args. dropFirst ( )
368
398
369
- func isLastArgument( at index: [ String ] . Index) -> Bool {
370
- args. index ( after: index) >= args. endIndex
371
- }
372
-
373
399
#if !SWT_NO_FILE_IO
374
400
#if canImport(Foundation)
375
401
// Configuration for the test run passed in as a JSON file (experimental)
@@ -379,9 +405,7 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
379
405
// NOTE: While the output event stream is opened later, it is necessary to
380
406
// open the configuration file early (here) in order to correctly construct
381
407
// the resulting __CommandLineArguments_v0 instance.
382
- if let configurationIndex = args. firstIndex ( of: " --configuration-path " ) ?? args. firstIndex ( of: " --experimental-configuration-path " ) ,
383
- !isLastArgument( at: configurationIndex) {
384
- let path = args [ args. index ( after: configurationIndex) ]
408
+ if let path = args. argumentValue ( forKey: " --configuration-path " ) ?? args. argumentValue ( forKey: " --experimental-configuration-path " ) {
385
409
let file = try FileHandle ( forReadingAtPath: path)
386
410
let configurationJSON = try file. readToEnd ( )
387
411
result = try configurationJSON. withUnsafeBufferPointer { configurationJSON in
@@ -394,24 +418,22 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
394
418
}
395
419
396
420
// Event stream output
397
- if let eventOutputIndex = args. firstIndex ( of: " --event-stream-output-path " ) ?? args. firstIndex ( of: " --experimental-event-stream-output " ) ,
398
- !isLastArgument( at: eventOutputIndex) {
399
- result. eventStreamOutputPath = args [ args. index ( after: eventOutputIndex) ]
421
+ if let path = args. argumentValue ( forKey: " --event-stream-output-path " ) ?? args. argumentValue ( forKey: " --experimental-event-stream-output " ) {
422
+ result. eventStreamOutputPath = path
400
423
}
424
+
401
425
// Event stream version
402
426
do {
403
- var eventOutputVersionIndex : Array < String > . Index ?
427
+ var versionString : String ?
404
428
var allowExperimental = false
405
- eventOutputVersionIndex = args. firstIndex ( of : " --event-stream-version " )
406
- if eventOutputVersionIndex == nil {
407
- eventOutputVersionIndex = args. firstIndex ( of : " --experimental-event-stream-version " )
408
- if eventOutputVersionIndex != nil {
429
+ versionString = args. argumentValue ( forKey : " --event-stream-version " )
430
+ if versionString == nil {
431
+ versionString = args. argumentValue ( forKey : " --experimental-event-stream-version " )
432
+ if versionString != nil {
409
433
allowExperimental = true
410
434
}
411
435
}
412
- if let eventOutputVersionIndex, !isLastArgument( at: eventOutputVersionIndex) {
413
- let versionString = args [ args. index ( after: eventOutputVersionIndex) ]
414
-
436
+ if let versionString {
415
437
// If the caller specified a version that could not be parsed, treat it as
416
438
// an invalid argument.
417
439
guard let eventStreamVersion = VersionNumber ( versionString) else {
@@ -432,14 +454,13 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
432
454
#endif
433
455
434
456
// XML output
435
- if let xunitOutputIndex = args. firstIndex ( of : " --xunit-output " ) , !isLastArgument ( at : xunitOutputIndex ) {
436
- result. xunitOutput = args [ args . index ( after : xunitOutputIndex ) ]
457
+ if let xunitOutputPath = args. argumentValue ( forKey : " --xunit-output " ) {
458
+ result. xunitOutput = xunitOutputPath
437
459
}
438
460
439
461
// Attachment output
440
- if let attachmentsPathIndex = args. firstIndex ( of: " --attachments-path " ) ?? args. firstIndex ( of: " --experimental-attachments-path " ) ,
441
- !isLastArgument( at: attachmentsPathIndex) {
442
- result. attachmentsPath = args [ args. index ( after: attachmentsPathIndex) ]
462
+ if let attachmentsPath = args. argumentValue ( forKey: " --attachments-path " ) ?? args. argumentValue ( forKey: " --experimental-attachments-path " ) {
463
+ result. attachmentsPath = attachmentsPath
443
464
}
444
465
#endif
445
466
@@ -457,13 +478,12 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
457
478
}
458
479
459
480
// Whether or not to symbolicate backtraces in the event stream.
460
- if let symbolicateBacktracesIndex = args. firstIndex ( of : " --symbolicate-backtraces " ) , !isLastArgument ( at : symbolicateBacktracesIndex ) {
461
- result. symbolicateBacktraces = args [ args . index ( after : symbolicateBacktracesIndex ) ]
481
+ if let symbolicateBacktraces = args. argumentValue ( forKey : " --symbolicate-backtraces " ) {
482
+ result. symbolicateBacktraces = symbolicateBacktraces
462
483
}
463
484
464
485
// Verbosity
465
- if let verbosityIndex = args. firstIndex ( of: " --verbosity " ) , !isLastArgument( at: verbosityIndex) ,
466
- let verbosity = Int ( args [ args. index ( after: verbosityIndex) ] ) {
486
+ if let verbosity = args. argumentValue ( forKey: " --verbosity " ) . flatMap ( Int . init) {
467
487
result. verbosity = verbosity
468
488
}
469
489
if args. contains ( " --verbose " ) || args. contains ( " -v " ) {
@@ -492,11 +512,11 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
492
512
}
493
513
494
514
// Set up the iteration policy for the test run.
495
- if let repetitionsIndex = args. firstIndex ( of : " --repetitions " ) , !isLastArgument ( at : repetitionsIndex ) {
496
- result. repetitions = Int ( args [ args . index ( after : repetitionsIndex ) ] )
515
+ if let repetitions = args. argumentValue ( forKey : " --repetitions " ) . flatMap ( Int . init ) {
516
+ result. repetitions = repetitions
497
517
}
498
- if let repeatUntilIndex = args. firstIndex ( of : " --repeat-until " ) , !isLastArgument ( at : repeatUntilIndex ) {
499
- result. repeatUntil = args [ args . index ( after : repeatUntilIndex ) ]
518
+ if let repeatUntil = args. argumentValue ( forKey : " --repeat-until " ) {
519
+ result. repeatUntil = repeatUntil
500
520
}
501
521
502
522
return result
0 commit comments