Skip to content

Commit 283ab9d

Browse files
author
Eric Miller
committed
Update config decoding
1 parent a4daa45 commit 283ab9d

File tree

11 files changed

+228
-149
lines changed

11 files changed

+228
-149
lines changed

Sources/UBKit/Files/Config/config.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,18 @@ extension File {
2828
class func configFile() -> Data? {
2929
let file = """
3030
{
31-
"project_name": "",
32-
"bundle_id": "<com.example.project_name>",
33-
"unity_path": "<path_to_Unity>",
34-
"unity_version": "",
35-
"unity_scene_name": ""
31+
"ios": {
32+
"projectName": "",
33+
"bundleId": "<com.example.project_name>",
34+
"projectPath": ""
35+
},
36+
"unity": {
37+
"projectName": "",
38+
"applicationPath": "<path_to_Unity>",
39+
"version": "",
40+
"projectPath": "",
41+
"unity_scene_name": ""
42+
}
3643
}
3744
""".data(using: .utf8)
3845
return file

Sources/UBKit/Models/Config.swift

Lines changed: 97 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,64 +23,116 @@
2323

2424
import Foundation
2525

26-
struct Config {
27-
28-
struct Keys {
29-
static let projectName = "project_name"
30-
static let bundleID = "bundle_id"
31-
static let unityPath = "unity_path"
32-
static let unityVersion = "unity_version"
33-
static let unitySceneName = "unity_scene_name"
26+
struct Config: Decodable {
27+
28+
enum ConfigKeys: String, CodingKey {
29+
case ios
30+
case unity
3431
}
3532

33+
let iOS: iOSConfig
34+
let unity: UnityConfig
35+
36+
init(from decoder: Decoder) throws {
37+
let container = try decoder.container(keyedBy: ConfigKeys.self)
38+
self.iOS = try iOSConfig(from: container.superDecoder(forKey: .ios))
39+
self.unity = try UnityConfig(from: container.superDecoder(forKey: .unity))
40+
}
41+
}
42+
43+
struct iOSConfig: Decodable {
3644
let projectName: String
37-
let bundleID: String
38-
let unityPath: String
39-
let unityVersion: String
40-
let unitySceneName: String
41-
let unityProjectPath: String
42-
let iOSProjectPath: String
45+
let bundleId: String
46+
let projectPath: String
4347

44-
let relativeIOSBuildPath: String
45-
let relativeUnityClassesPath: String
46-
let relativeUnityLibrariesPath: String
47-
let relativeUnityDataPath: String
48-
49-
50-
init?(json: [String : String], currentPath: String) {
51-
guard let projectName = json[Keys.projectName],
52-
let bundleID = json[Keys.bundleID], !bundleID.isEmpty,
53-
let unityPath = json[Config.Keys.unityPath], !unityPath.isEmpty,
54-
let unityVersion = json[Config.Keys.unityVersion], !unityVersion.isEmpty,
55-
let sceneName = json[Config.Keys.unitySceneName] else {
56-
return nil
48+
private enum Keys: String, CodingKey {
49+
case projectName
50+
case bundleId
51+
case projectPath
52+
}
53+
54+
init(from decoder: Decoder) throws {
55+
let container = try decoder.container(keyedBy: Keys.self)
56+
let projectName = try container.decode(String.self, forKey: .projectName)
57+
guard !projectName.isEmpty else {
58+
throw UBKitError.invalidConfigArgument(Keys.projectName.rawValue)
59+
}
60+
61+
let bundleId = try container.decode(String.self, forKey: .bundleId)
62+
guard !bundleId.isEmpty else {
63+
throw UBKitError.invalidConfigArgument(Keys.bundleId.rawValue)
5764
}
5865

59-
if projectName.isEmpty {
60-
guard let folderName = currentPath.components(separatedBy: "/").last else {
61-
return nil
62-
}
63-
self.projectName = folderName
66+
let projectPath: String
67+
if let path = try? container.decode(String.self, forKey: .projectPath), !path.isEmpty {
68+
projectPath = path
6469
} else {
65-
self.projectName = projectName
70+
projectPath = FileManager.default.currentDirectoryPath.appending("/iOS/")
6671
}
6772

68-
if sceneName.isEmpty {
69-
self.unitySceneName = self.projectName
73+
self.projectName = projectName
74+
self.bundleId = bundleId
75+
self.projectPath = projectPath
76+
}
77+
}
78+
79+
struct UnityConfig {
80+
let projectName: String
81+
let applicationPath: String
82+
let version: String
83+
let projectPath: String
84+
let sceneNames: [String]
85+
let relativeIOSBuildPath: String
86+
let relativeClassesPath: String
87+
let relativeLibrariesPath: String
88+
let relativeDataPath: String
89+
90+
private enum Keys: String, CodingKey {
91+
case applicationPath
92+
case version
93+
case projectPath
94+
case projectName
95+
case sceneNames
96+
}
97+
98+
init(from decoder: Decoder) throws {
99+
let container = try decoder.container(keyedBy: Keys.self)
100+
let projectName = try container.decode(String.self, forKey: .projectName)
101+
guard !projectName.isEmpty else {
102+
throw UBKitError.invalidConfigArgument(Keys.projectName.rawValue)
103+
}
104+
105+
let appPath = try container.decode(String.self, forKey: .applicationPath)
106+
guard !appPath.isEmpty else {
107+
throw UBKitError.invalidConfigArgument(Keys.applicationPath.rawValue)
108+
}
109+
110+
let version = try container.decode(String.self, forKey: .version)
111+
guard !version.isEmpty else {
112+
throw UBKitError.invalidConfigArgument(Keys.version.rawValue)
113+
}
114+
115+
let projectPath: String
116+
if let path = try? container.decode(String.self, forKey: .projectPath), !path.isEmpty {
117+
projectPath = path
70118
} else {
71-
self.unitySceneName = sceneName
119+
projectPath = FileManager.default.currentDirectoryPath.appending("/Unity/")
72120
}
73121

74-
self.bundleID = bundleID
75-
self.unityPath = unityPath
76-
self.unityVersion = unityVersion
122+
let sceneNames = try container.decode([String].self, forKey: .sceneNames)
123+
guard sceneNames.count > 0 else {
124+
throw UBKitError.invalidConfigArgument(Keys.sceneNames.rawValue)
125+
}
77126

78-
self.unityProjectPath = currentPath.appending("/Unity/")
79-
self.iOSProjectPath = currentPath.appending("/iOS/")
127+
self.projectName = projectName
128+
self.applicationPath = appPath
129+
self.version = version
130+
self.projectPath = projectPath
131+
self.sceneNames = sceneNames
80132

81-
self.relativeIOSBuildPath = self.projectName.appending("/ios_build/")
82-
self.relativeUnityClassesPath = self.projectName.appending("/ios_build/Classes/")
83-
self.relativeUnityLibrariesPath = self.projectName.appending("/ios_build/Libraries/")
84-
self.relativeUnityDataPath = self.projectName.appending("/ios_build/Data/")
133+
self.relativeIOSBuildPath = projectName.appending("/ios_build/")
134+
self.relativeClassesPath = self.relativeIOSBuildPath.appending("Classes/")
135+
self.relativeLibrariesPath = self.relativeIOSBuildPath.appending("Libraries/")
136+
self.relativeDataPath = self.relativeIOSBuildPath.appending("Data/")
85137
}
86138
}

Sources/UBKit/Models/UBKitError.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ public enum UBKitError: Error, CustomStringConvertible {
3636
case unableToSaveXcodeProject
3737
case waitTimedOut
3838
case shellCommand(String)
39-
case invalidConfigFile
39+
case invalidConfigArgument(String)
40+
case invalidConfigFile(Error)
4041

4142
public var description: String {
4243
switch self {
@@ -64,8 +65,14 @@ public enum UBKitError: Error, CustomStringConvertible {
6465
return "Wait Timed Out"
6566
case .shellCommand(let str):
6667
return "Failed to execute shell command: \(str)"
67-
case .invalidConfigFile:
68-
return "Invalid config file"
68+
case .invalidConfigArgument(let str):
69+
return "Invalid config argument: \(str)"
70+
case .invalidConfigFile(let err):
71+
if let ubError = err as? UBKitError {
72+
return ubError.description
73+
} else {
74+
return "Invalid config file: \(err.localizedDescription)"
75+
}
6976
}
7077
}
7178
}

Sources/UBKit/Models/Unity.swift renamed to Sources/UBKit/Models/UnityCommandLine.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Unity.swift
2+
// UnityCommandLine.swift
33
//
44
// Copyright (c) 2017 Handsome
55
//
@@ -26,7 +26,7 @@ import Foundation
2626
/**
2727
A helper class for interacting with the Unity command line.
2828
*/
29-
struct Unity {
29+
struct UnityCommandLine {
3030
static let buildAction = "iOSBuilder.Perform"
3131
static let refreshAction = "iOSRefresher.Perform"
3232

Sources/UBKit/UBKit.swift

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,19 @@ public final class UBKit {
4343
completion(UBKitError.invalidArguments(arguments[1]))
4444
return
4545
}
46-
46+
4747
let workingPath = fileManager.currentDirectoryPath.appending("/")
4848
if arg != .initialize {
49-
do {
50-
guard let fileData = fileManager.contents(atPath: workingPath.appending("ubconfig.json")) else {
51-
completion(UBKitError.invalidFolder(workingPath.appending("ubconfig.json")))
52-
return
53-
}
54-
if let configJSON = try JSONSerialization.jsonObject(with: fileData, options: .allowFragments) as? [String : String] {
55-
guard let config = Config(json: configJSON, currentPath: fileManager.currentDirectoryPath) else {
56-
completion(UBKitError.invalidConfigFile)
57-
return
58-
}
59-
kitManager = UBKitManager(config: config)
60-
}
49+
guard let fileData = fileManager.contents(atPath: workingPath.appending("ubconfig.json")) else {
50+
completion(UBKitError.invalidFolder(workingPath.appending("ubconfig.json")))
51+
return
52+
}
6153

54+
do {
55+
let config = try JSONDecoder().decode(Config.self, from: fileData)
56+
kitManager = UBKitManager(config: config)
6257
} catch {
63-
completion(error)
58+
completion(UBKitError.invalidConfigFile(error))
6459
return
6560
}
6661
}

Sources/UBKit/UBKitManager.swift

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,22 +128,13 @@ private extension UBKitManager {
128128
let fileCopier = FileCopier(config: config)
129129
return fileCopier.copyFiles(refresh: refresh)
130130
}
131-
132-
func refreshProjects() -> Result {
133-
let refresher = ProjectRefresher(config: config)
134-
return refresher.refresh()
135-
}
136131
}
137132

138133
// MARK: - Refresh
139134
private extension UBKitManager {
140135

141136
func refreshXcodeProject() -> Result {
142-
let refreshResult = refreshProjects()
143-
guard refreshResult == .success else {
144-
return refreshResult
145-
}
146-
147-
return .success
137+
let unityProject = UnityProject(config: config)
138+
return unityProject.refresh()
148139
}
149140
}

Sources/UBKit/Workers/FileCopier.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ class FileCopier {
4848

4949
init(config: Config) {
5050
self.config = config
51-
self.workingPath = config.unityProjectPath
52-
self.xcodeProjectPath = config.iOSProjectPath
53-
self.xcodeProjectFilePath = String(format: "%@%@%@", xcodeProjectPath, config.projectName, ".xcodeproj")
51+
self.workingPath = config.unity.projectPath
52+
self.xcodeProjectPath = config.iOS.projectPath
53+
self.xcodeProjectFilePath = String(format: "%@%@%@", xcodeProjectPath, config.iOS.projectName, ".xcodeproj")
5454
}
5555

5656
func copyFiles(refresh: Bool) -> Result {
@@ -77,7 +77,7 @@ class FileCopier {
7777
}
7878

7979
print("Adding Unity files to Xcode project")
80-
let classesPath = workingPath.appending(config.relativeUnityClassesPath)
80+
let classesPath = workingPath.appending(config.unity.relativeClassesPath)
8181
guard let classesGroup = classesGroup else {
8282
return .failure(UBKitError.invalidUnityProject)
8383
}
@@ -86,7 +86,7 @@ class FileCopier {
8686
return addClassesFilesResult
8787
}
8888

89-
let librariesPath = workingPath.appending(config.relativeUnityLibrariesPath)
89+
let librariesPath = workingPath.appending(config.unity.relativeLibrariesPath)
9090
guard let libsGroup = libsGroup else {
9191
return .failure(UBKitError.invalidUnityProject)
9292
}
@@ -132,8 +132,8 @@ private extension FileCopier {
132132
return .failure(UBKitError.invalidXcodeProject("Missing sources build phase"))
133133
}
134134

135-
guard let targetGroup = project.pbxproj.groups.filter({ $0.path == config.projectName }).first else {
136-
return .failure(UBKitError.missingGroup(config.projectName))
135+
guard let targetGroup = project.pbxproj.groups.filter({ $0.path == config.iOS.projectName }).first else {
136+
return .failure(UBKitError.missingGroup(config.iOS.projectName))
137137
}
138138

139139
do {
@@ -252,14 +252,14 @@ private extension FileCopier {
252252
}
253253

254254
if let classesGroup = generateGroup("Classes", sourceTree: .absolute) {
255-
classesGroup.path = workingPath.appending(config.relativeUnityClassesPath)
255+
classesGroup.path = workingPath.appending(config.unity.relativeClassesPath)
256256
project.pbxproj.addObject(classesGroup)
257257
self.classesGroup = classesGroup
258258
unityGroup.children.append(classesGroup.reference)
259259
}
260260

261261
if let librariesGroup = generateGroup("Libraries", sourceTree: .absolute) {
262-
librariesGroup.path = workingPath.appending(config.relativeUnityLibrariesPath)
262+
librariesGroup.path = workingPath.appending(config.unity.relativeLibrariesPath)
263263
project.pbxproj.addObject(librariesGroup)
264264
self.libsGroup = librariesGroup
265265
unityGroup.children.append(librariesGroup.reference)
@@ -308,7 +308,7 @@ private extension FileCopier {
308308
return .failure(UBKitError.invalidXcodeProject("Missing sources build phase"))
309309
}
310310

311-
guard let mainTarget = project.pbxproj.nativeTargets.filter({ $0.name == config.projectName }).first else {
311+
guard let mainTarget = project.pbxproj.nativeTargets.filter({ $0.name == config.iOS.projectName }).first else {
312312
return .failure(UBKitError.invalidXcodeProject("Missing main target"))
313313
}
314314

@@ -401,7 +401,7 @@ private extension FileCopier {
401401
let fileReference = PBXFileReference(reference: generateUUID(PBXFileReference.self, "data".appending(nameSalt)),
402402
sourceTree: .absolute)
403403
fileReference.name = "Data"
404-
fileReference.path = workingPath.appending(config.relativeUnityDataPath)
404+
fileReference.path = workingPath.appending(config.unity.relativeDataPath)
405405
fileReference.lastKnownFileType = "folder"
406406
unityGroup.children.append(fileReference.reference)
407407
project.pbxproj.addObject(fileReference)
@@ -538,7 +538,7 @@ private extension FileCopier {
538538
}
539539

540540
func generateSourceFile(path: Path, in group: PBXGroup, name: String) -> SourceFile? {
541-
let referencePath = Path(xcodeProjectPath.appending(config.projectName).appending("/").appending(config.projectName))
541+
let referencePath = Path(xcodeProjectPath.appending(config.iOS.projectName).appending("/").appending(config.iOS.projectName))
542542
guard let fileReference = getFileReference(path: path, inPath: referencePath, name: name) else {
543543
return nil
544544
}

0 commit comments

Comments
 (0)