Include unique file only once

Fixes #574
This commit is contained in:
haritowa 2019-06-15 18:26:29 +03:00 committed by Brentley Jones
parent 331c8e5c23
commit 8e21cdfdb1
6 changed files with 72 additions and 6 deletions

View File

@ -2,6 +2,9 @@
## Next Version
#### Fixed
- Fixed spec array properties (scripts, sources, dependencies, test suites, etc.) duplication [#599](https://github.com/yonaskolb/XcodeGen/pull/599) @haritowa
## 2.6.0
#### Added

View File

@ -8,6 +8,8 @@ public struct SpecFile {
public let jsonDictionary: JSONDictionary
public let subSpecs: [SpecFile]
private let filename: String
fileprivate struct Include {
let path: Path
let relativePaths: Bool
@ -42,11 +44,12 @@ public struct SpecFile {
try self.init(filename: path.lastComponent, basePath: path.parent())
}
public init(jsonDictionary: JSONDictionary, basePath: Path = "", relativePath: Path = "", subSpecs: [SpecFile] = []) {
public init(filename: String, jsonDictionary: JSONDictionary, basePath: Path = "", relativePath: Path = "", subSpecs: [SpecFile] = []) {
self.basePath = basePath
self.relativePath = relativePath
self.jsonDictionary = jsonDictionary
self.subSpecs = subSpecs
self.filename = filename
}
fileprivate init(include: Include, basePath: Path, relativePath: Path) throws {
@ -65,7 +68,7 @@ public struct SpecFile {
try SpecFile(include: include, basePath: basePath, relativePath: relativePath)
}
self.init(jsonDictionary: jsonDictionary, basePath: basePath, relativePath: relativePath, subSpecs: subSpecs)
self.init(filename: filename, jsonDictionary: jsonDictionary, basePath: basePath, relativePath: relativePath, subSpecs: subSpecs)
}
static func loadDictionary(path: Path) throws -> JSONDictionary {
@ -83,17 +86,36 @@ public struct SpecFile {
}
public func resolvedDictionary(variables: [String: String] = [:]) -> JSONDictionary {
var resolvedSpec = resolvingPaths().mergedDictionary()
let resolvedDictionary = resolvedDictionaryWithUniqueTargets()
return substitute(variables: variables, in: resolvedDictionary)
}
private func resolvedDictionaryWithUniqueTargets() -> JSONDictionary {
let resolvedSpec = resolvingPaths()
var value = Set<String>()
return resolvedSpec.mergedDictionary(set: &value)
}
private func substitute(variables: [String: String], in mergedDictionary: JSONDictionary) -> JSONDictionary {
var resolvedSpec = mergedDictionary
for (key, value) in variables {
resolvedSpec = resolvedSpec.replaceString("${\(key)}", with: value)
}
return resolvedSpec
}
func mergedDictionary() -> JSONDictionary {
func mergedDictionary(set mergedTargets: inout Set<String>) -> JSONDictionary {
let name = (basePath + relativePath + Path(filename)).description
guard !mergedTargets.contains(name) else { return [:] }
mergedTargets.insert(name)
return jsonDictionary.merged(onto:
subSpecs
.map { $0.mergedDictionary() }
.map { $0.mergedDictionary(set: &mergedTargets) }
.reduce([:]) { $1.merged(onto: $0) })
}
@ -105,6 +127,7 @@ public struct SpecFile {
let jsonDictionary = Project.pathProperties.resolvingPaths(in: self.jsonDictionary, relativeTo: relativePath)
return SpecFile(
filename: filename,
jsonDictionary: jsonDictionary,
relativePath: self.relativePath,
subSpecs: subSpecs.map { $0.resolvingPaths(relativeTo: relativePath) }

View File

@ -0,0 +1,13 @@
name: DuplicatedImportRoot
fileGroups:
- First
- Second
targetTemplates:
IncludedTemplate:
type: application
platform: iOS
sources:
- template
preBuildScripts:
- script: swiftlint
name: Swiftlint

View File

@ -0,0 +1,9 @@
include:
- duplicated_import_transitive.yml
- duplicated_import_root.yml
- duplicated_import_root.yml
name: DuplicatedImportDependent
targets:
IncludedTarget:
templates:
- IncludedTemplate

View File

@ -0,0 +1,3 @@
include:
- duplicated_import_root.yml
name: DuplicatedImportTransitive

View File

@ -9,6 +9,21 @@ import Yams
class SpecLoadingTests: XCTestCase {
func testSpecLoaderDuplicateImports() {
describe {
$0.it("merges each file only once") {
let path = fixturePath + "duplicated_include/duplicated_import_sut.yml"
let project = try loadSpec(path: path)
try expect(project.fileGroups) == ["First", "Second"]
let sutTarget = project.targets.first
try expect(sutTarget?.sources) == [TargetSource(path: "template")]
try expect(sutTarget?.preBuildScripts) == [BuildScript(script: .script("swiftlint"), name: "Swiftlint")]
}
}
}
func testSpecLoader() {
describe {
$0.it("merges includes") {