mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2026-03-18 20:02:25 +00:00
126339f1c8
The preGenCommand may generate files, change paths, etc. If we run this after checking the cache, it never gets the chance to run if the cache hasn't changed. Running it before checking the cache lets us make these changes and _then_ we can check the cache to see if we need to regenerate or not. Co-authored-by: Dale Myers <dalemyers@microsoft.com>
139 lines
4.6 KiB
Swift
139 lines
4.6 KiB
Swift
import Foundation
|
|
import PathKit
|
|
import ProjectSpec
|
|
import SwiftCLI
|
|
import XcodeGenKit
|
|
import XcodeProj
|
|
import Version
|
|
|
|
class GenerateCommand: ProjectCommand {
|
|
|
|
@Flag("-c", "--use-cache", description: "Use a cache for the xcodegen spec. This will prevent unnecessarily generating the project if nothing has changed")
|
|
var useCache: Bool
|
|
|
|
@Key("--cache-path", description: "Where the cache file will be loaded from and save to. Defaults to ~/.xcodegen/cache/{SPEC_PATH_HASH}")
|
|
var cacheFilePath: Path?
|
|
|
|
@Key("-p", "--project", description: "The path to the directory where the project should be generated. Defaults to the directory the spec is in. The filename is defined in the project spec")
|
|
var projectDirectory: Path?
|
|
|
|
@Flag("--only-plists", description: "Generate only plist files")
|
|
var onlyPlists: Bool
|
|
|
|
init(version: Version) {
|
|
super.init(version: version,
|
|
name: "generate",
|
|
shortDescription: "Generate an Xcode project from a spec")
|
|
}
|
|
|
|
override func execute(specLoader: SpecLoader, projectSpecPath: Path, project: Project) throws {
|
|
|
|
let projectDirectory = self.projectDirectory?.absolute() ?? projectSpecPath.parent()
|
|
|
|
// validate project dictionary
|
|
do {
|
|
try specLoader.validateProjectDictionaryWarnings()
|
|
} catch {
|
|
warning("\(error)")
|
|
}
|
|
|
|
let projectPath = projectDirectory + "\(project.name).xcodeproj"
|
|
|
|
// run pre gen command before we use the cache as the scripts may change it
|
|
if let command = project.options.preGenCommand {
|
|
try Task.run(bash: command, directory: projectDirectory.absolute().string)
|
|
}
|
|
|
|
let cacheFilePath = self.cacheFilePath ??
|
|
Path("~/.xcodegen/cache/\(projectSpecPath.absolute().string.md5)").absolute()
|
|
var cacheFile: CacheFile?
|
|
|
|
// generate cache
|
|
if useCache || self.cacheFilePath != nil {
|
|
do {
|
|
cacheFile = try specLoader.generateCacheFile()
|
|
} catch {
|
|
throw GenerationError.projectSpecParsingError(error)
|
|
}
|
|
}
|
|
|
|
let projectExists = XcodeProj.pbxprojPath(projectPath).exists
|
|
|
|
// check cache
|
|
if let cacheFile = cacheFile,
|
|
projectExists,
|
|
cacheFilePath.exists {
|
|
do {
|
|
let existingCacheFile: String = try cacheFilePath.read()
|
|
if cacheFile.string == existingCacheFile {
|
|
info("Project \(project.name) has not changed since cache was written")
|
|
return
|
|
}
|
|
} catch {
|
|
info("Couldn't load cache at \(cacheFile)")
|
|
}
|
|
}
|
|
|
|
// validate project
|
|
do {
|
|
try project.validateMinimumXcodeGenVersion(version)
|
|
try project.validate()
|
|
} catch let error as SpecValidationError {
|
|
throw GenerationError.validationError(error)
|
|
}
|
|
|
|
// generate plists
|
|
info("⚙️ Generating plists...")
|
|
let fileWriter = FileWriter(project: project)
|
|
do {
|
|
try fileWriter.writePlists()
|
|
if onlyPlists {
|
|
return
|
|
}
|
|
} catch {
|
|
throw GenerationError.writingError(error)
|
|
}
|
|
|
|
// generate project
|
|
info("⚙️ Generating project...")
|
|
let xcodeProject: XcodeProj
|
|
do {
|
|
let projectGenerator = ProjectGenerator(project: project)
|
|
|
|
guard let userName = ProcessInfo.processInfo.environment["LOGNAME"] else {
|
|
throw GenerationError.missingUsername
|
|
}
|
|
|
|
xcodeProject = try projectGenerator.generateXcodeProject(in: projectDirectory, userName: userName)
|
|
|
|
} catch {
|
|
throw GenerationError.generationError(error)
|
|
}
|
|
|
|
// write project
|
|
info("⚙️ Writing project...")
|
|
do {
|
|
try fileWriter.writeXcodeProject(xcodeProject, to: projectPath)
|
|
|
|
success("Created project at \(projectPath)")
|
|
} catch {
|
|
throw GenerationError.writingError(error)
|
|
}
|
|
|
|
// write cache
|
|
if let cacheFile = cacheFile {
|
|
do {
|
|
try cacheFilePath.parent().mkpath()
|
|
try cacheFilePath.write(cacheFile.string)
|
|
} catch {
|
|
info("Failed to write cache: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
// run post gen command
|
|
if let command = project.options.postGenCommand {
|
|
try Task.run(bash: command, directory: projectDirectory.absolute().string)
|
|
}
|
|
}
|
|
}
|