Support Linux by upgrading XcodeProj and Spectre (#988)

* Bump XcodeProj and Spectre

* Add LinuxMain.swift

* Linux test fixups

* Add CI job for ubuntu-latest

* Use URLs in glob logic to avoid Linux/Mac foundation inconsistencies

* fatalError when --enable-test-discovery is not used

* Update fixtures

They changed because of a bugfix in XcodeProj: https://github.com/tuist/XcodeProj/pull/563

* Update CHANGELOG.md
This commit is contained in:
Elliott Williams 2020-11-23 16:28:41 -08:00 committed by GitHub
parent 1e7c1c2da0
commit 2601d39792
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 53 additions and 44 deletions

View File

@ -32,3 +32,10 @@ jobs:
run: scripts/diff-fixtures.sh
- name: Build fixtures
run: scripts/build-fixtures.sh
run-linux:
runs-on: ubuntu-latest
name: Linux
steps:
- uses: actions/checkout@master
- name: Build and run tests
run: swift test --enable-test-discovery

View File

@ -3,6 +3,7 @@
## Next Version
#### Added
- Support for building and running on Linux platforms. Tested for compatibility with Swift 5.3+ and Ubuntu 18.04. [#988](https://github.com/yonaskolb/XcodeGen/pull/988) @elliottwilliams
- Add `useBaseInternationalization` to Project Spec Options to opt out of Base Internationalization. [#961](https://github.com/yonaskolb/XcodeGen/pull/961) @liamnichols
#### Fixed

View File

@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/tadija/AEXML",
"state": {
"branch": null,
"revision": "e4d517844dd03dac557e35d77a8e9ab438de91a6",
"version": "4.4.0"
"revision": "8623e73b193386909566a9ca20203e33a09af142",
"version": "4.5.0"
}
},
{
@ -15,8 +15,8 @@
"repositoryURL": "https://github.com/SwiftDocOrg/GraphViz.git",
"state": {
"branch": null,
"revision": "08e0cddd013fa2272379d27ec3e0093db51f34fb",
"version": "0.1.0"
"revision": "c4746cb3ff6f5e7c5d5540c40b98555521c3ee43",
"version": "0.1.3"
}
},
{
@ -42,8 +42,8 @@
"repositoryURL": "https://github.com/onevcat/Rainbow.git",
"state": {
"branch": null,
"revision": "9c52c1952e9b2305d4507cf473392ac2d7c9b155",
"version": "3.1.5"
"revision": "626c3d4b6b55354b4af3aa309f998fae9b31a3d9",
"version": "3.2.0"
}
},
{
@ -51,8 +51,8 @@
"repositoryURL": "https://github.com/kylef/Spectre.git",
"state": {
"branch": null,
"revision": "f14ff47f45642aa5703900980b014c2e9394b6e5",
"version": "0.9.0"
"revision": "f79d4ecbf8bc4e1579fbd86c3e1d652fb6876c53",
"version": "0.9.2"
}
},
{
@ -60,8 +60,8 @@
"repositoryURL": "https://github.com/jakeheis/SwiftCLI.git",
"state": {
"branch": null,
"revision": "c72c4564f8c0a24700a59824880536aca45a4cae",
"version": "6.0.1"
"revision": "2816678bcc37f4833d32abeddbdf5e757fa891d8",
"version": "6.0.2"
}
},
{
@ -78,17 +78,8 @@
"repositoryURL": "https://github.com/tuist/XcodeProj.git",
"state": {
"branch": null,
"revision": "545bfa746b6eb4ea0ad8d3a12c6590445392bb50",
"version": "7.13.0"
}
},
{
"package": "XcodeProjCExt",
"repositoryURL": "https://github.com/tuist/XcodeProjCExt",
"state": {
"branch": null,
"revision": "21a510c225ff2bc83d5920a21d902af4b1e7e218",
"version": "0.1.0"
"revision": "82bf5efcaa27e94ed8c761c1eb3e397b6dea82b9",
"version": "7.18.0"
}
},
{

View File

@ -14,9 +14,9 @@ let package = Package(
.package(url: "https://github.com/kylef/PathKit.git", from: "1.0.0"),
.package(url: "https://github.com/jpsim/Yams.git", from: "4.0.0"),
.package(url: "https://github.com/yonaskolb/JSONUtilities.git", from: "4.2.0"),
.package(url: "https://github.com/kylef/Spectre.git", from: "0.9.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", .exact("7.13.0")),
.package(url: "https://github.com/tuist/XcodeProj.git", from: "7.18.0"),
.package(url: "https://github.com/jakeheis/SwiftCLI.git", from: "6.0.0"),
.package(url: "https://github.com/mxcl/Version", from: "2.0.0"),
.package(url: "https://github.com/SwiftDocOrg/GraphViz.git", from: "0.1.0"),

View File

@ -136,7 +136,7 @@ public class Glob: Collection {
let firstPart = parts.removeFirst()
var lastPart = parts.joined(separator: "**")
var directories: [String]
var directories: [URL]
if FileManager.default.fileExists(atPath: firstPart) {
do {
@ -151,7 +151,7 @@ public class Glob: Collection {
if behavior.includesFilesFromRootOfGlobstar {
// Check the base directory for the glob star as well.
directories.insert(firstPart, at: 0)
directories.insert(URL(fileURLWithPath: firstPart), at: 0)
// Include the globstar root directory ("dir/") in a pattern like "dir/**" or "dir/**/"
if lastPart.isEmpty {
@ -163,29 +163,30 @@ public class Glob: Collection {
lastPart = "*"
}
for directory in directories {
let partiallyResolvedPattern = NSString(string: directory).appendingPathComponent(lastPart)
results.append(contentsOf: expandGlobstar(pattern: partiallyResolvedPattern))
let partiallyResolvedPattern = directory.appendingPathComponent(lastPart)
let standardizedPattern = (partiallyResolvedPattern.relativePath as NSString).standardizingPath
results.append(contentsOf: expandGlobstar(pattern: standardizedPattern))
}
return results
}
private func exploreDirectories(path: String) throws -> [String] {
private func exploreDirectories(path: String) throws -> [URL] {
try FileManager.default.contentsOfDirectory(atPath: path)
.compactMap { subpath -> [String]? in
.compactMap { subpath -> [URL]? in
if blacklistedDirectories.contains(subpath) {
return nil
}
let firstLevelPath = NSString(string: path).appendingPathComponent(subpath)
guard isDirectory(path: firstLevelPath) else {
let firstLevel = URL(fileURLWithPath: path).appendingPathComponent(subpath, isDirectory: true)
guard isDirectory(path: firstLevel.path) else {
return nil
}
var subDirs: [String] = try FileManager.default.subpathsOfDirectory(atPath: firstLevelPath)
.compactMap { subpath -> String? in
let fullPath = NSString(string: firstLevelPath).appendingPathComponent(subpath)
return isDirectory(path: fullPath) ? fullPath : nil
var subDirs: [URL] = try FileManager.default.subpathsOfDirectory(atPath: firstLevel.path)
.compactMap { subpath -> URL? in
let full = firstLevel.appendingPathComponent(subpath, isDirectory: true)
return isDirectory(path: full.path) ? full : nil
}
subDirs.append(firstLevelPath)
subDirs.append(firstLevel)
return subDirs
}
.joined()
@ -211,7 +212,12 @@ public class Glob: Collection {
private func populateFiles(gt: glob_t, includeFiles: Bool) {
let includeDirectories = behavior.includesDirectoriesInResults
for i in 0..<Int(gt.gl_matchc) {
#if os(macOS)
let matches = Int(gt.gl_matchc)
#else
let matches = Int(gt.gl_pathc)
#endif
for i in 0..<matches {
if let path = String(validatingUTF8: gt.gl_pathv[i]!) {
if !includeFiles || !includeDirectories {
let isDirectory = self.isDirectory(path: path)

View File

@ -20,6 +20,7 @@ extension PBXProductType {
.intentsServiceExtension,
.messagesApplication,
.messagesExtension,
.metalLibrary,
.ocUnitTestBundle,
.onDemandInstallCapableApplication,
.stickerPack,

View File

@ -188,7 +188,7 @@ public class SchemeGenerator {
parallelizable: testTarget.parallelizable,
randomExecutionOrdering: testTarget.randomExecutionOrder,
buildableReference: testBuilEntries.buildableReference,
skippedTests: testTarget.skippedTests.map(XCScheme.SkippedTest.init)
skippedTests: testTarget.skippedTests.map(XCScheme.TestItem.init)
)
}

View File

@ -42,7 +42,7 @@ class GlobTests: XCTestCase {
}
private func newTmpDir() -> String {
var tmpDirTmpl = "/tmp/glob-test.XXXXX".cString(using: .utf8)!
var tmpDirTmpl = "/tmp/glob-test.XXXXXX".cString(using: .utf8)!
return String(validatingUTF8: mkdtemp(&tmpDirTmpl))!
}

View File

@ -7,7 +7,7 @@
objects = {
/* Begin PBXFileReference section */
6023D61BF2C57E6AE09CE7A3 /* BundleX.bundle */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.plug-in"; path = BundleX.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
6023D61BF2C57E6AE09CE7A3 /* BundleX.bundle */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = BundleX.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
60D6679FB526839EAFEA2EEE /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = config.xcconfig; sourceTree = "<group>"; };
D6340FC7DEBC81E0127BAFD6 /* ExternalTarget.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ExternalTarget.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

View File

@ -617,7 +617,7 @@
3FC04772130400920D68A167 /* App_Clip_Tests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = App_Clip_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
40863AE6202CFCD0529D8438 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
41FC82ED1C4C3B7B3D7B2FB7 /* Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
45C12576F5AA694DD0CE2132 /* BundleX.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = BundleX.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
45C12576F5AA694DD0CE2132 /* BundleX.bundle */ = {isa = PBXFileReference; lastKnownFileType = wrapper.cfbundle; path = BundleX.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
469B630D28015F0EDC456F6B /* libStaticLibrary_ObjC.a */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; path = libStaticLibrary_ObjC.a; sourceTree = BUILT_PRODUCTS_DIR; };
46DD8F9AAC104BDB63793625 /* libStaticLibrary_ObjC.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libStaticLibrary_ObjC.a; sourceTree = BUILT_PRODUCTS_DIR; };
4BF4D16042A80576D259160C /* Model 3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Model 3.xcdatamodel"; sourceTree = "<group>"; };
@ -636,7 +636,7 @@
70A8E15C81E454DC950C59F0 /* SomeXPCService.xpc */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.xpc-service"; path = SomeXPCService.xpc; sourceTree = "<group>"; };
72A14C887EF7E9C8CBE914AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
77C0C341F1865224E0596086 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
7B5068D64404C61A67A18458 /* MyBundle.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MyBundle.bundle; sourceTree = "<group>"; };
7B5068D64404C61A67A18458 /* MyBundle.bundle */ = {isa = PBXFileReference; lastKnownFileType = wrapper.cfbundle; path = MyBundle.bundle; sourceTree = "<group>"; };
7C176A8297AC2F5207352BA8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
7C7EC00B53FF878007F6ECAB /* App_Clip_UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = App_Clip_UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
7D67F1C1BFBACE101DE7DB51 /* Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -648,7 +648,7 @@
86169DEEDEAF09AB89C8A31D /* libStaticLibrary_ObjC.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libStaticLibrary_ObjC.a; sourceTree = BUILT_PRODUCTS_DIR; };
87DF9DCA8399E3214A7E27CF /* TestProjectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProjectTests.swift; sourceTree = "<group>"; };
8A9274BE42A03DC5DA1FAD04 /* Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8AF20308873AEEEC4D8C45D1 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
8AF20308873AEEEC4D8C45D1 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = wrapper.cfbundle; path = Settings.bundle; sourceTree = "<group>"; };
8CAF6C55B555E3E1352645B6 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = "<group>"; };
8CB86294FB939FE6E90932E1 /* libStaticLibrary_Swift.a */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; path = libStaticLibrary_Swift.a; sourceTree = BUILT_PRODUCTS_DIR; };
8D88C6BF7355702B74396791 /* TestProjectUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProjectUITests.swift; sourceTree = "<group>"; };

3
Tests/LinuxMain.swift Normal file
View File

@ -0,0 +1,3 @@
// LinuxMain.swift
fatalError("Run the tests with `swift test --enable-test-discovery`.")

View File

@ -202,7 +202,7 @@ class SpecLoadingTests: XCTestCase {
throw failure("\(key): \(parsedValue) does not equal \(expectedValue)")
}
}
if !(dictionary as NSDictionary).isEqual(expectedDictionary) {
if !(dictionary as NSDictionary).isEqual(expectedDictionary as NSDictionary) {
throw failure("parsed yaml types don't match:\n\nParsed:\n\t\(dictionary.map { "\($0.key): \($0.value)" }.joined(separator: "\n\t"))\nExpected:\n\t\(expectedDictionary.map { "\($0.key): \($0.value)" }.joined(separator: "\n\t"))")
}
}