Add dump command (#710)

Add dump command
This commit is contained in:
Yonas Kolb
2019-11-10 11:47:43 +11:00
committed by GitHub
9 changed files with 147 additions and 47 deletions
+1
View File
@@ -4,6 +4,7 @@
#### Added
- Add Carthage static framework dependencies support. [#688](https://github.com/yonaskolb/XcodeGen/pull/688) @giginet
- Added `xcodegen dump` command [#710](https://github.com/yonaskolb/XcodeGen/pull/710) @yonaskolb
- Added `--no-env` option to disable environment variables expansion [#704](https://github.com/yonaskolb/XcodeGen/pull/704) @rcari
#### Fixed
+1 -1
View File
@@ -130,7 +130,7 @@ Options:
- **--use-cache**: Used to prevent unnecessarily generating the project. If this is set, then a cache file will be written to when a project is generated. If `xcodegen` is later run but the spec and all the files it contains are the same, the project won't be generated.
- **--cache-path**: A custom path to use for your cache file. This defaults to `~/.xcodegen/cache/{PROJECT_SPEC_PATH_HASH}`
Use `xcodegen help` to see more detailed usage information.
There are other commands as well. Use `xcodegen help` to see more detailed usage information.
## Editing
```shell
+2 -3
View File
@@ -144,7 +144,7 @@ extension Dictionary where Key == String, Value: Any {
return merged
}
func expand(variables: [String:String]) -> JSONDictionary {
func expand(variables: [String: String]) -> JSONDictionary {
var expanded: JSONDictionary = self
if !variables.isEmpty {
@@ -189,8 +189,7 @@ extension Dictionary where Key == String, Value: Any {
index = result.endIndex
} else if substring[index] == "$"
&& substring[substring.index(index, offsetBy: 1)] == "{"
&& substring[substring.index(index, offsetBy: 2)] != "}"
{
&& substring[substring.index(index, offsetBy: 2)] != "}" {
// This is the start of a variable expansion...
let variableStart = index
if let variableEnd = substring.firstIndex(of: "}") {
+1 -1
View File
@@ -7,7 +7,7 @@ import Yams
public class SpecLoader {
var project: Project!
private var projectDictionary: [String: Any]?
public private(set) var projectDictionary: [String: Any]?
let version: Version
public init(version: Version) {
@@ -0,0 +1,71 @@
import Foundation
import SwiftCLI
import PathKit
import ProjectSpec
import Yams
class DumpCommand: ProjectCommand {
private let dumpType = Key<DumpType>(
"--type",
"-t",
description: """
The type of dump to output. Either \(DumpType.allCases.map { "\"\($0.rawValue)\"" }.joined(separator: ", ")). Defaults to \(DumpType.defaultValue.rawValue). The "parsed" types parse the project into swift and then back again.
"""
)
private let file = Key<Path>(
"--file",
"-f",
description: "The path of a file to write to. If not supplied will output to stdout"
)
init(version: Version) {
super.init(version: version,
name: "dump",
shortDescription: "Dumps the resolved project spec to stdout or a file"
)
}
override func execute(specLoader: SpecLoader, projectSpecPath: Path, project: Project) throws {
let type = dumpType.value ?? .defaultValue
let output: String
switch type {
case .swiftDump:
var string = ""
dump(project, to: &string)
output = string
case .json:
let data = try JSONSerialization.data(withJSONObject: specLoader.projectDictionary!, options: .prettyPrinted)
output = String(data: data, encoding: .utf8)!
case .yaml:
output = try Yams.dump(object: specLoader.projectDictionary!)
case .parsedJSON:
let data = try JSONSerialization.data(withJSONObject: project.toJSONDictionary(), options: .prettyPrinted)
output = String(data: data, encoding: .utf8)!
case .parsedYaml:
output = try Yams.dump(object: project.toJSONDictionary())
case .summary:
output = project.debugDescription
}
if let file = file.value {
try file.parent().mkpath()
try file.write(output)
} else {
stdout.print(output)
}
}
}
private enum DumpType: String, ConvertibleFromString, CaseIterable {
case swiftDump = "swift-dump"
case json
case yaml
case parsedJSON = "parsed-json"
case parsedYaml = "parsed-yaml"
case summary
static var defaultValue: DumpType { .yaml }
}
@@ -5,10 +5,7 @@ import SwiftCLI
import XcodeGenKit
import XcodeProj
class GenerateCommand: Command {
let name: String = "generate"
let shortDescription: String = "Generate an Xcode project from a spec"
class GenerateCommand: ProjectCommand {
let quiet = Flag(
"-q",
@@ -17,13 +14,6 @@ class GenerateCommand: Command {
defaultValue: false
)
let disableEnvExpansion = Flag(
"-n",
"--no-env",
description: "Disable environment variables expansions",
defaultValue: false
)
let useCache = Flag(
"-c",
"--use-cache",
@@ -36,43 +26,23 @@ class GenerateCommand: Command {
description: "Where the cache file will be loaded from and save to. Defaults to ~/.xcodegen/cache/{SPEC_PATH_HASH}"
)
let spec = Key<Path>(
"-s",
"--spec",
description: "The path to the project spec file. Defaults to project.yml"
let projectDirectory = Key<Path>(
"-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"
)
let projectDirectory = Key<Path>("-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")
let version: Version
init(version: Version) {
self.version = version
super.init(version: version,
name: "generate",
shortDescription: "Generate an Xcode project from a spec"
)
}
func execute() throws {
let projectSpecPath = (spec.value ?? "project.yml").absolute()
override func execute(specLoader: SpecLoader, projectSpecPath: Path, project: Project) throws {
let projectDirectory = self.projectDirectory.value?.absolute() ?? projectSpecPath.parent()
if !projectSpecPath.exists {
throw GenerationError.missingProjectSpec(projectSpecPath)
}
let specLoader = SpecLoader(version: version)
let project: Project
let variables: [String: String] = disableEnvExpansion.value ? [:] : ProcessInfo.processInfo.environment
// load project spec
do {
project = try specLoader.loadProject(path: projectSpecPath, variables: variables)
info("Loaded project:\n \(project.debugDescription.replacingOccurrences(of: "\n", with: "\n "))")
} catch {
throw GenerationError.projectSpecParsingError(error)
}
// validate project dictionary
do {
try specLoader.validateProjectDictionaryWarnings()
@@ -0,0 +1,56 @@
import Foundation
import SwiftCLI
import ProjectSpec
import XcodeGenKit
import PathKit
import Core
class ProjectCommand: Command {
let version: Version
let name: String
let shortDescription: String
let spec = Key<Path>(
"-s",
"--spec",
description: "The path to the project spec file. Defaults to project.yml"
)
let disableEnvExpansion = Flag(
"-n",
"--no-env",
description: "Disable environment variable expansions",
defaultValue: false
)
init(version: Version, name: String, shortDescription: String) {
self.version = version
self.name = name
self.shortDescription = shortDescription
}
func execute() throws {
let projectSpecPath = (spec.value ?? "project.yml").absolute()
if !projectSpecPath.exists {
throw GenerationError.missingProjectSpec(projectSpecPath)
}
let specLoader = SpecLoader(version: version)
let project: Project
let variables: [String: String] = disableEnvExpansion.value ? [:] : ProcessInfo.processInfo.environment
do {
project = try specLoader.loadProject(path: projectSpecPath, variables: variables)
} catch {
throw GenerationError.projectSpecParsingError(error)
}
try execute(specLoader: specLoader, projectSpecPath: projectSpecPath, project: project)
}
func execute(specLoader: SpecLoader, projectSpecPath: Path, project: Project) throws {}
}
+4 -1
View File
@@ -12,7 +12,10 @@ public class XcodeGenCLI {
name: "xcodegen",
version: version.string,
description: "Generates Xcode projects",
commands: [generateCommand]
commands: [
generateCommand,
DumpCommand(version: version),
]
)
cli.parser.routeBehavior = .searchWithFallback(generateCommand)
}
+1 -1
View File
@@ -479,7 +479,7 @@ public class PBXProjGenerator {
let dependecyLinkage = dependencyTarget.defaultLinkage
let link = dependency.link ??
((dependecyLinkage == .dynamic && target.type != .staticLibrary) ||
(dependecyLinkage == .static && target.type.isExecutable))
(dependecyLinkage == .static && target.type.isExecutable))
if link {
let dependencyFile = targetFileReferences[dependencyTarget.name]!