diff --git a/.gitignore b/.gitignore index caf10c28..1f55464b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ xcuserdata *.xcuserstate XcodeGen.xcodeproj xcodegen.zip +.vscode/launch.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 68b1b5e8..c5394630 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,22 @@ ## Next Version +### Fixed + +- Fixed crash caused by a simultaneous write during a glob processing [#1177](https://github.com/yonaskolb/XcodeGen/issues/1177) @tr1ckyf0x + +## 2.26.0 + +### Added + +- Added the option to specify a `location` in a test target [#1150](https://github.com/yonaskolb/XcodeGen/issues/1150) @KrisRJack + ### Changed - Speed up source inclusion checking for big projects [#1122](https://github.com/yonaskolb/XcodeGen/pull/1122) @PaulTaykalo +[Commits](https://github.com/yonaskolb/XcodeGen/compare/2.25.0...2.26.0) + ## 2.25.0 ### Added diff --git a/Docs/ProjectSpec.md b/Docs/ProjectSpec.md index c99f1462..1874c94d 100644 --- a/Docs/ProjectSpec.md +++ b/Docs/ProjectSpec.md @@ -834,6 +834,7 @@ A multiline script can be written using the various YAML multiline methods, for - [x] **name**: **String** - The name of the target - [ ] **parallelizable**: **Bool** - Whether to run tests in parallel. Defaults to false - [ ] **randomExecutionOrder**: **Bool** - Whether to run tests in a random order. Defaults to false +- [ ] **location**: **String** - GPX file or predefined value for simulating location. See [Simulate Location](#simulate-location) for location examples. - [ ] **skipped**: **Bool** - Whether to skip all of the test target tests. Defaults to false - [ ] **skippedTests**: **[String]** - List of tests in the test target to skip. Defaults to empty - [ ] **selectedTests**: **[String]** - List of tests in the test target to whitelist and select. Defaults to empty. This will override `skippedTests` if provided diff --git a/Makefile b/Makefile index 79567119..aa515b3d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ TOOL_NAME = XcodeGen export EXECUTABLE_NAME = xcodegen -VERSION = 2.25.0 +VERSION = 2.26.0 PREFIX = /usr/local INSTALL_PATH = $(PREFIX)/bin/$(EXECUTABLE_NAME) @@ -46,4 +46,4 @@ brew: brew bump-formula-pr --url=$(RELEASE_TAR) XcodeGen archive: build - ./scripts/archive.sh $(EXECUTABLE_PATH) + ./scripts/archive.sh "$(EXECUTABLE_PATH)" diff --git a/Package.resolved b/Package.resolved index 4d75c731..e883890e 100644 --- a/Package.resolved +++ b/Package.resolved @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/tuist/XcodeProj.git", "state": { "branch": null, - "revision": "446f3a0db73e141c7f57e26fcdb043096b1db52c", - "version": "8.3.1" + "revision": "aa2a42c7a744ca18b5918771fdd6cf40f9753db5", + "version": "8.6.0" } }, { diff --git a/Package.swift b/Package.swift index d4cc5201..c1d72975 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( .package(url: "https://github.com/yonaskolb/JSONUtilities.git", from: "4.2.0"), .package(url: "https://github.com/kylef/Spectre.git", from: "0.9.2"), .package(url: "https://github.com/onevcat/Rainbow.git", from: "3.0.0"), - .package(url: "https://github.com/tuist/XcodeProj.git", from: "8.3.1"), + .package(url: "https://github.com/tuist/XcodeProj.git", from: "8.6.0"), .package(url: "https://github.com/jakeheis/SwiftCLI.git", from: "6.0.3"), .package(url: "https://github.com/mxcl/Version", from: "2.0.0"), .package(url: "https://github.com/SwiftDocOrg/GraphViz.git", .exact("0.2.0")), diff --git a/README.md b/README.md index ca78aaf0..6b036a52 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ swift run xcodegen Add the following to your Package.swift file's dependencies: ```swift -.package(url: "https://github.com/yonaskolb/XcodeGen.git", from: "2.25.0"), +.package(url: "https://github.com/yonaskolb/XcodeGen.git", from: "2.26.0"), ``` And then import wherever needed: `import XcodeGenKit` diff --git a/Sources/ProjectSpec/Scheme.swift b/Sources/ProjectSpec/Scheme.swift index ed921c89..25ce697c 100644 --- a/Sources/ProjectSpec/Scheme.swift +++ b/Sources/ProjectSpec/Scheme.swift @@ -184,6 +184,7 @@ public struct Scheme: Equatable { public var deleteScreenshotsWhenEachTestSucceeds: Bool public struct TestTarget: Equatable, ExpressibleByStringLiteral { + public static let randomExecutionOrderDefault = false public static let parallelizableDefault = false @@ -191,6 +192,7 @@ public struct Scheme: Equatable { public let targetReference: TargetReference public var randomExecutionOrder: Bool public var parallelizable: Bool + public var location: String? public var skipped: Bool public var skippedTests: [String] public var selectedTests: [String] @@ -199,6 +201,7 @@ public struct Scheme: Equatable { targetReference: TargetReference, randomExecutionOrder: Bool = randomExecutionOrderDefault, parallelizable: Bool = parallelizableDefault, + location: String? = nil, skipped: Bool = false, skippedTests: [String] = [], selectedTests: [String] = [] @@ -206,6 +209,7 @@ public struct Scheme: Equatable { self.targetReference = targetReference self.randomExecutionOrder = randomExecutionOrder self.parallelizable = parallelizable + self.location = location self.skipped = skipped self.skippedTests = skippedTests self.selectedTests = selectedTests @@ -216,6 +220,7 @@ public struct Scheme: Equatable { targetReference = try TargetReference(value) randomExecutionOrder = false parallelizable = false + location = nil skipped = false skippedTests = [] selectedTests = [] @@ -536,6 +541,7 @@ extension Scheme.Test.TestTarget: JSONObjectConvertible { targetReference = try TargetReference(jsonDictionary.json(atKeyPath: "name")) randomExecutionOrder = jsonDictionary.json(atKeyPath: "randomExecutionOrder") ?? Scheme.Test.TestTarget.randomExecutionOrderDefault parallelizable = jsonDictionary.json(atKeyPath: "parallelizable") ?? Scheme.Test.TestTarget.parallelizableDefault + location = jsonDictionary.json(atKeyPath: "location") ?? nil skipped = jsonDictionary.json(atKeyPath: "skipped") ?? false skippedTests = jsonDictionary.json(atKeyPath: "skippedTests") ?? [] selectedTests = jsonDictionary.json(atKeyPath: "selectedTests") ?? [] @@ -559,6 +565,9 @@ extension Scheme.Test.TestTarget: JSONEncodable { if parallelizable != Scheme.Test.TestTarget.parallelizableDefault { dict["parallelizable"] = parallelizable } + if let location = location { + dict["location"] = location + } if skipped { dict["skipped"] = skipped } diff --git a/Sources/XcodeGen/main.swift b/Sources/XcodeGen/main.swift index 2de4bb42..8ba636bf 100644 --- a/Sources/XcodeGen/main.swift +++ b/Sources/XcodeGen/main.swift @@ -3,6 +3,6 @@ import ProjectSpec import XcodeGenCLI import Version -let version = Version("2.25.0") +let version = Version("2.26.0") let cli = XcodeGenCLI(version: version) cli.execute() diff --git a/Sources/XcodeGenCore/Atomic.swift b/Sources/XcodeGenCore/Atomic.swift new file mode 100644 index 00000000..c7911ca4 --- /dev/null +++ b/Sources/XcodeGenCore/Atomic.swift @@ -0,0 +1,27 @@ +// +// Atomic.swift +// +// +// Created by Vladislav Lisianskii on 23.02.2022. +// + +import Foundation + +@propertyWrapper +struct Atomic { + private let queue = DispatchQueue(label: "com.xcodegencore.atomic") + private var value: Value + + init(wrappedValue: Value) { + self.value = wrappedValue + } + + var wrappedValue: Value { + get { + return queue.sync { value } + } + set { + queue.sync { value = newValue } + } + } +} diff --git a/Sources/XcodeGenCore/Glob.swift b/Sources/XcodeGenCore/Glob.swift index 596e986c..e3025eab 100644 --- a/Sources/XcodeGenCore/Glob.swift +++ b/Sources/XcodeGenCore/Glob.swift @@ -57,7 +57,7 @@ public class Glob: Collection { public static let defaultBlacklistedDirectories = ["node_modules", "Pods"] - private var isDirectoryCache = [String: Bool]() + @Atomic private var isDirectoryCache = [String: Bool]() public let behavior: Behavior public let blacklistedDirectories: [String] diff --git a/Sources/XcodeGenKit/SchemeGenerator.swift b/Sources/XcodeGenKit/SchemeGenerator.swift index 67f68196..e5fa2d54 100644 --- a/Sources/XcodeGenKit/SchemeGenerator.swift +++ b/Sources/XcodeGenKit/SchemeGenerator.swift @@ -187,12 +187,28 @@ public class SchemeGenerator { runPostActionsOnFailure: scheme.build.runPostActionsOnFailure ) - let testables = zip(testTargets, testBuildTargetEntries).map { testTarget, testBuilEntries in - XCScheme.TestableReference( + let testables: [XCScheme.TestableReference] = zip(testTargets, testBuildTargetEntries).map { testTarget, testBuildEntries in + + var locationScenarioReference: XCScheme.LocationScenarioReference? + if var location = testTarget.location { + + if location.contains(".gpx") { + var path = Path(components: [project.options.schemePathPrefix, location]) + path = path.simplifyingParentDirectoryReferences() + location = path.string + } + + let referenceType = location.contains(".gpx") ? "0" : "1" + locationScenarioReference = XCScheme.LocationScenarioReference(identifier: location, referenceType: referenceType) + + } + + return XCScheme.TestableReference( skipped: testTarget.skipped, parallelizable: testTarget.parallelizable, randomExecutionOrdering: testTarget.randomExecutionOrder, - buildableReference: testBuilEntries.buildableReference, + buildableReference: testBuildEntries.buildableReference, + locationScenarioReference: locationScenarioReference, skippedTests: testTarget.skippedTests.map(XCScheme.TestItem.init), selectedTests: testTarget.selectedTests.map(XCScheme.TestItem.init), useTestSelectionWhitelist: !testTarget.selectedTests.isEmpty ? true : nil diff --git a/Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_Scheme.xcscheme b/Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_Scheme.xcscheme index 47aae221..5aa4973c 100644 --- a/Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_Scheme.xcscheme +++ b/Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_Scheme.xcscheme @@ -53,6 +53,10 @@ BlueprintName = "App_iOS_Tests" ReferencedContainer = "container:Project.xcodeproj"> + + diff --git a/Tests/Fixtures/TestProject/project.yml b/Tests/Fixtures/TestProject/project.yml index 85662468..ff6d045c 100644 --- a/Tests/Fixtures/TestProject/project.yml +++ b/Tests/Fixtures/TestProject/project.yml @@ -426,6 +426,7 @@ schemes: - name: App_iOS_Tests parallelizable: true randomExecutionOrder: true + location: New York, NY, USA customLLDBInit: ${SRCROOT}/.lldbinit targetTemplates: MyTemplate: diff --git a/Tests/ProjectSpecTests/SpecLoadingTests.swift b/Tests/ProjectSpecTests/SpecLoadingTests.swift index 2282a8fa..d1c0e6c6 100644 --- a/Tests/ProjectSpecTests/SpecLoadingTests.swift +++ b/Tests/ProjectSpecTests/SpecLoadingTests.swift @@ -790,6 +790,7 @@ class SpecLoadingTests: XCTestCase { "name": "ExternalProject/Target2", "parallelizable": true, "skipped": true, + "location": "test.gpx", "randomExecutionOrder": true, "skippedTests": ["Test/testExample()"], ], @@ -836,6 +837,7 @@ class SpecLoadingTests: XCTestCase { targetReference: "ExternalProject/Target2", randomExecutionOrder: true, parallelizable: true, + location: "test.gpx", skipped: true, skippedTests: ["Test/testExample()"] ), @@ -856,6 +858,7 @@ class SpecLoadingTests: XCTestCase { [ "name": "ExternalProject/Target2", "parallelizable": true, + "location": "New York, NY, USA", "randomExecutionOrder": true, "selectedTests": ["Test/testExample()"], ], @@ -877,6 +880,7 @@ class SpecLoadingTests: XCTestCase { targetReference: "ExternalProject/Target2", randomExecutionOrder: true, parallelizable: true, + location: "New York, NY, USA", selectedTests: ["Test/testExample()"] ), ] diff --git a/Tests/XcodeGenKitTests/SchemeGeneratorTests.swift b/Tests/XcodeGenKitTests/SchemeGeneratorTests.swift index 3c27b8a9..b78a6177 100644 --- a/Tests/XcodeGenKitTests/SchemeGeneratorTests.swift +++ b/Tests/XcodeGenKitTests/SchemeGeneratorTests.swift @@ -49,11 +49,14 @@ class SchemeGeneratorTests: XCTestCase { let preAction = Scheme.ExecutionAction(name: "Script", script: "echo Starting", settingsTarget: app.name) let simulateLocation = Scheme.SimulateLocation(allow: true, defaultLocation: "New York, NY, USA") let storeKitConfiguration = "Configuration.storekit" - let scheme = Scheme( + let scheme = try Scheme( name: "MyScheme", build: Scheme.Build(targets: [buildTarget], preActions: [preAction]), run: Scheme.Run(config: "Debug", askForAppToLaunch: true, launchAutomaticallySubstyle: "2", simulateLocation: simulateLocation, storeKitConfiguration: storeKitConfiguration, customLLDBInit: "/sample/.lldbinit"), - test: Scheme.Test(config: "Debug", customLLDBInit: "/test/.lldbinit"), + test: Scheme.Test(config: "Debug", targets: [ + Scheme.Test.TestTarget(targetReference: TargetReference(framework.name), location: "test.gpx"), + Scheme.Test.TestTarget(targetReference: TargetReference(framework.name), location: "New York, NY, USA") + ], customLLDBInit: "/test/.lldbinit"), profile: Scheme.Profile(config: "Release", askForAppToLaunch: true) ) let project = Project( @@ -109,6 +112,13 @@ class SchemeGeneratorTests: XCTestCase { try expect(xcscheme.launchAction?.customLLDBInitFile) == "/sample/.lldbinit" try expect(xcscheme.testAction?.customLLDBInitFile) == "/test/.lldbinit" try expect(xcscheme.testAction?.systemAttachmentLifetime).to.beNil() + + try expect(xcscheme.testAction?.testables[0].locationScenarioReference?.referenceType) == "0" + try expect(xcscheme.testAction?.testables[0].locationScenarioReference?.identifier) == "../test.gpx" + + try expect(xcscheme.testAction?.testables[1].locationScenarioReference?.referenceType) == "1" + try expect(xcscheme.testAction?.testables[1].locationScenarioReference?.identifier) == "New York, NY, USA" + } let frameworkTarget = Scheme.BuildTarget(target: .local(framework.name), buildTypes: [.archiving]) diff --git a/scripts/archive.sh b/scripts/archive.sh index ad335507..0a9ebb58 100755 --- a/scripts/archive.sh +++ b/scripts/archive.sh @@ -10,7 +10,7 @@ LICENSE=LICENSE # copy mkdir -p $BINDIR -cp -f $1 $BINDIR +cp -f "$1" $BINDIR mkdir -p $SHAREDIR cp -R SettingPresets $SHAREDIR/SettingPresets