From c9c589c5eef4f151a1a52a78be66da794cbe57ac Mon Sep 17 00:00:00 2001 From: Yonas Kolb Date: Mon, 25 Sep 2017 13:23:47 +0200 Subject: [PATCH 1/2] add optional replace syntax when merging includes --- Fixtures/include_test.yml | 4 +++- Fixtures/included.yml | 4 ++++ Sources/XcodeGenKit/SpecLoader.swift | 5 ++++- Tests/XcodeGenKitTests/SpecLoadingTests.swift | 3 ++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Fixtures/include_test.yml b/Fixtures/include_test.yml index 02fa473e..dcfb4df8 100644 --- a/Fixtures/include_test.yml +++ b/Fixtures/include_test.yml @@ -6,6 +6,8 @@ settingGroups: MY_SETTING3: VALUE3 new: MY_SETTING: VALUE + toReplace:REPLACE: + MY_SETTING2: VALUE2 targets: NewTarget: type: application @@ -13,4 +15,4 @@ targets: IncludedTarget: name: IncludedTargetNew platform: tvOS - sources: Target + sources:REPLACE: NewSource diff --git a/Fixtures/included.yml b/Fixtures/included.yml index 1619d813..b82d395c 100644 --- a/Fixtures/included.yml +++ b/Fixtures/included.yml @@ -3,7 +3,11 @@ settingGroups: test: MY_SETTING1: VALUE1 MY_SETTING2: VALUE2 + toReplace: + MY_SETTING1: VALUE1 targets: IncludedTarget: type: application platform: iOS + sources: + - Target diff --git a/Sources/XcodeGenKit/SpecLoader.swift b/Sources/XcodeGenKit/SpecLoader.swift index 4ecab1fe..043b59ca 100644 --- a/Sources/XcodeGenKit/SpecLoader.swift +++ b/Sources/XcodeGenKit/SpecLoader.swift @@ -52,7 +52,10 @@ public struct SpecLoader { var merged = base for (key, value) in dictionary { - if let dictionary = value as? JSONDictionary, let base = merged[key] as? JSONDictionary { + if key.hasSuffix(":REPLACE") { + let newKey = key.replacingOccurrences(of: ":REPLACE", with: "") + merged[newKey] = value + } else if let dictionary = value as? JSONDictionary, let base = merged[key] as? JSONDictionary { merged[key] = merge(dictionary: dictionary, onto: base) } else if let array = value as? [Any], let base = merged[key] as? [Any] { merged[key] = base + array diff --git a/Tests/XcodeGenKitTests/SpecLoadingTests.swift b/Tests/XcodeGenKitTests/SpecLoadingTests.swift index 8a10deaf..7679ad31 100644 --- a/Tests/XcodeGenKitTests/SpecLoadingTests.swift +++ b/Tests/XcodeGenKitTests/SpecLoadingTests.swift @@ -39,9 +39,10 @@ func specLoadingTests() { try expect(spec.settingGroups) == [ "test": Settings(dictionary: ["MY_SETTING1": "NEW VALUE", "MY_SETTING2": "VALUE2", "MY_SETTING3": "VALUE3"]), "new": Settings(dictionary: ["MY_SETTING": "VALUE"]), + "toReplace": Settings(dictionary: ["MY_SETTING2": "VALUE2"]), ] try expect(spec.targets) == [ - Target(name: "IncludedTargetNew", type: .application, platform: .tvOS, sources: ["Target"]), + Target(name: "IncludedTargetNew", type: .application, platform: .tvOS, sources: ["NewSource"]), Target(name: "NewTarget", type: .application, platform: .iOS), ] } From 8dd3864d1491c49d61ed3c92e67286b473fdfb5f Mon Sep 17 00:00:00 2001 From: Yonas Kolb Date: Mon, 25 Sep 2017 13:35:59 +0200 Subject: [PATCH 2/2] add Include documentation to ProjectSpec.md --- docs/ProjectSpec.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/ProjectSpec.md b/docs/ProjectSpec.md index 817bc526..cc85dff7 100644 --- a/docs/ProjectSpec.md +++ b/docs/ProjectSpec.md @@ -8,6 +8,7 @@ Required properties are marked 🔵 and optional properties with ⚪️. ### Index - [Project](#project) + - [Include](#include) - [Options](#options) - [Configs](#configs) - [Setting Groups](#setting-groups) @@ -25,7 +26,7 @@ Required properties are marked 🔵 and optional properties with ⚪️. ## Project - 🔵 **name**: `String` - Name of the generated project -- ⚪️ **include**: `[String]` - The paths to other specs. They will be merged in order and then the current spec will be merged on top. Target names can be changed by adding a `name` property. This can also be set as a single path string +- ⚪️ **include**: [Include](#include) - One or more paths to other specs - ⚪️ **options**: [Options](#options) - Various options to override default behaviour - ⚪️ **attributes**: `map` - The PBXProject attributes. This is for advanced use. Defaults to ``{"LastUpgradeCheck": "0900"}`` - ⚪️ **configs**: [Configs](#configs) - Project build configurations. Defaults to `Debug` and `Release` configs @@ -35,6 +36,31 @@ Required properties are marked 🔵 and optional properties with ⚪️. - ⚪️ **targets**: [Target](#target) - The list of targets in the project mapped by name - ⚪️ **fileGroups**: `[String]` - A list of paths to add to the top level groups. These are files that aren't build files but that you'd like in the project hierachy. For example a folder xcconfig files that aren't already added by any target sources. +### Include +One or more specs can be included in the project spec. This can be used to split your project spec into multiple files, for easier structuring or sharing between multiple specs. Included specs can also include other specs and so on. + +Include can either be a list of string paths or a single string path. They will be merged in order and then the current spec will be merged on top. +By default specs are merged additively. That is for every value: + +- if existing value and new value are both dictionaries merge them and continue down the hierachy +- if existing value and new value are both an array then add the new value to the end of the array +- otherwise replace the existing value with the new value + +This merging behaviour can be overriden on a value basis. If you wish to replace a whole value (set a new dictionary or new array instead of merging them) then just affix `:REPLACE` to the key + + +```yaml +include: + - base.yml +name: CustomSpec +targets: + MyTarget: # target lives in base.yml + sources:REPLACE: + - my_new_sources +``` + +Note that target names can also be changed by adding a `name` property to a target. + ### Options - ⚪️ **carthageBuildPath**: `String` - The path to the carthage build directory. Defaults to `Carthage/Build`. This is used when specifying target carthage dependencies