Skip to content

Commit

Permalink
refactor file writing
Browse files Browse the repository at this point in the history
  • Loading branch information
yonaskolb committed Oct 29, 2018
1 parent 228ab66 commit 26106a0
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 69 deletions.
18 changes: 4 additions & 14 deletions Sources/XcodeGen/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,11 @@ func generate(spec: String, project: String, isQuiet: Bool, justVersion: Bool) {
let xcodeProject = try projectGenerator.generateXcodeProject()

logger.info("⚙️ Writing project...")
let projectWriter = ProjectWriter(project: project)
try projectWriter.writeXcodeProject(xcodeProject)
try projectWriter.writePlists()

try projectGenerator.generateFiles()

let projectFile = projectPath + "\(project.name).xcodeproj"
let tempPath = Path.temporary + "XcodeGen_\(Int(NSTimeIntervalSince1970))"
try? tempPath.delete()
if projectFile.exists {
try projectFile.copy(tempPath)
}
try xcodeProject.write(path: tempPath, override: true)
try? projectFile.delete()
try tempPath.copy(projectFile)
try? tempPath.delete()

logger.success("💾 Saved project to \(projectFile.string)")
logger.success("💾 Saved project to \(project.projectPath.string)")
} catch let error as SpecValidationError {
fatalError(error.description)
} catch {
Expand Down
42 changes: 42 additions & 0 deletions Sources/XcodeGenKit/InfoPlistGenerator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Foundation
import ProjectSpec
import PathKit

public class InfoPlistGenerator {

/**
Default info plist attributes taken from:
/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/Project Templates/Base/Base_DefinitionsInfoPlist.xctemplate/TemplateInfo.plist
*/
var defaultInfoPlist: [String: Any] = {
var dictionary: [String: Any] = [:]
dictionary["CFBundleIdentifier"] = "$(PRODUCT_BUNDLE_IDENTIFIER)"
dictionary["CFBundleInfoDictionaryVersion"] = "6.0"
dictionary["CFBundleExecutable"] = "$(EXECUTABLE_NAME)"
dictionary["CFBundleName"] = "$(PRODUCT_NAME)"
dictionary["CFBundleDevelopmentRegion"] = "$(DEVELOPMENT_LANGUAGE)"
dictionary["CFBundleShortVersionString"] = "1.0"
dictionary["CFBundleVersion"] = "1"
return dictionary
}()

public func generateAttributes(target: Target) -> [String: Any] {
var targetInfoPlist = defaultInfoPlist
switch target.type {
case .uiTestBundle,
.unitTestBundle:
targetInfoPlist["CFBundlePackageType"] = "BNDL"
case .application,
.watch2App:
targetInfoPlist["CFBundlePackageType"] = "APPL"
case .framework:
targetInfoPlist["CFBundlePackageType"] = "FMWK"
case .bundle:
targetInfoPlist["CFBundlePackageType"] = "BNDL"
case .xpcService:
targetInfoPlist["CFBundlePackageType"] = "XPC"
default: break
}
return targetInfoPlist
}
}
51 changes: 0 additions & 51 deletions Sources/XcodeGenKit/ProjectGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,57 +33,6 @@ public class ProjectGenerator {
return XcodeProj(workspace: workspace, pbxproj: pbxProj, sharedData: sharedData)
}

public func generateFiles() throws {

/*
Default info plist attributes taken from:
/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/Project Templates/Base/Base_DefinitionsInfoPlist.xctemplate/TemplateInfo.plist
*/
var defaultInfoPlist: [String: Any] = [:]
defaultInfoPlist["CFBundleIdentifier"] = "$(PRODUCT_BUNDLE_IDENTIFIER)"
defaultInfoPlist["CFBundleInfoDictionaryVersion"] = "6.0"
defaultInfoPlist["CFBundleExecutable"] = "$(EXECUTABLE_NAME)"
defaultInfoPlist["CFBundleName"] = "$(PRODUCT_NAME)"
defaultInfoPlist["CFBundleDevelopmentRegion"] = "$(DEVELOPMENT_LANGUAGE)"
defaultInfoPlist["CFBundleShortVersionString"] = "1.0"
defaultInfoPlist["CFBundleVersion"] = "1"

for target in project.targets {
if let plist = target.info {
var targetInfoPlist = defaultInfoPlist
switch target.type {
case .uiTestBundle,
.unitTestBundle:
targetInfoPlist["CFBundlePackageType"] = "BNDL"
case .application,
.watch2App:
targetInfoPlist["CFBundlePackageType"] = "APPL"
case .framework:
targetInfoPlist["CFBundlePackageType"] = "FMWK"
case .bundle:
targetInfoPlist["CFBundlePackageType"] = "BNDL"
case .xpcService:
targetInfoPlist["CFBundlePackageType"] = "XPC"
default: break
}
let path = project.basePath + plist.path
let attributes = targetInfoPlist.merged(plist.attributes)
let data = try PropertyListSerialization.data(fromPropertyList: attributes, format: .xml, options: 0)
try? path.delete()
try path.parent().mkpath()
try path.write(data)
}

if let plist = target.entitlements {
let path = project.basePath + plist.path
let data = try PropertyListSerialization.data(fromPropertyList: plist.attributes, format: .xml, options: 0)
try? path.delete()
try path.parent().mkpath()
try path.write(data)
}
}
}

func generateWorkspace() throws -> XCWorkspace {
let dataElement: XCWorkspaceDataElement = .file(XCWorkspaceDataFileRef(location: .self("")))
let workspaceData = XCWorkspaceData(children: [dataElement])
Expand Down
51 changes: 51 additions & 0 deletions Sources/XcodeGenKit/ProjectWriter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Foundation
import ProjectSpec
import xcodeproj
import PathKit

public class ProjectWriter {

let project: Project

public init(project: Project) {
self.project = project
}

public func writeXcodeProject(_ xcodeProject: XcodeProj) throws {
let projectPath = project.projectPath
let tempPath = Path.temporary + "XcodeGen_\(Int(NSTimeIntervalSince1970))"
try? tempPath.delete()
if projectPath.exists {
try projectPath.copy(tempPath)
}
try xcodeProject.write(path: tempPath, override: true)
try? projectPath.delete()
try tempPath.copy(projectPath)
try? tempPath.delete()
}

public func writePlists() throws {

let infoPlistGenerator = InfoPlistGenerator()
for target in project.targets {
// write Info.plist
if let plist = target.info {
let path = project.basePath + plist.path
let attributes = infoPlistGenerator.generateAttributes(target: target).merged(plist.attributes)
let data = try PropertyListSerialization.data(fromPropertyList: attributes, format: .xml, options: 0)
try? path.delete()
try path.parent().mkpath()
try path.write(data)
}

// write entitlements
if let plist = target.entitlements {
let path = project.basePath + plist.path
let data = try PropertyListSerialization.data(fromPropertyList: plist.attributes, format: .xml, options: 0)
try? path.delete()
try path.parent().mkpath()
try path.write(data)
}
}
}
}
5 changes: 3 additions & 2 deletions Tests/XcodeGenKitTests/ProjectFixtureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ fileprivate func generateXcodeProject(specPath: Path, file: String = #file, line
let project = try Project(path: specPath)
let generator = ProjectGenerator(project: project)
let xcodeProject = try generator.generateXcodeProject()
try generator.generateFiles()
try xcodeProject.write(path: project.projectPath, override: true)
let writer = ProjectWriter(project: project)
try writer.writePlists()
try writer.writeXcodeProject(xcodeProject)

return xcodeProject
}
4 changes: 2 additions & 2 deletions Tests/XcodeGenKitTests/ProjectGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -836,8 +836,8 @@ class ProjectGeneratorTests: XCTestCase {
let tempPath = Path.temporary + "info"
let project = Project(basePath: tempPath, name: "", targets: [Target(name: "", type: .application, platform: .iOS, info: plist)])
let pbxProject = try project.generatePbxProj()
let generator = ProjectGenerator(project: project)
try generator.generateFiles()
let writer = ProjectWriter(project: project)
try writer.writePlists()

guard let targetConfig = pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first else {
throw failure("Couldn't find Target config")
Expand Down

0 comments on commit 26106a0

Please sign in to comment.