Generate project when editing (#958)
* Pin XcodeProj to a branch until it's merged * Add a way to specify PathRunnable in custom scheme * Make scheme buildable when `tuist edit`-ing * Added changelog entry * Style correct * Update Xcodeproj * Using same path to tuist executable that was used to invoke the edit command * Update documentation * style update
This commit is contained in:
parent
e1c122d2c7
commit
350a53ee08
|
@ -5,6 +5,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
|
|||
## Next
|
||||
|
||||
### Added
|
||||
- When using `tuist edit` it's possible to run `tuist generate` from Xcode by simply running the target https://github.com/tuist/tuist/pull/958 by @vytis
|
||||
|
||||
- Add FAQ section by @mollyIV
|
||||
- Add benchmarking helper tool https://github.com/tuist/tuist/pull/957 by @kwridan.
|
||||
|
|
|
@ -6,15 +6,18 @@ public struct RunAction: Equatable {
|
|||
|
||||
public let configurationName: String
|
||||
public let executable: TargetReference?
|
||||
public let filePath: AbsolutePath?
|
||||
public let arguments: Arguments?
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
public init(configurationName: String,
|
||||
executable: TargetReference? = nil,
|
||||
filePath: AbsolutePath? = nil,
|
||||
arguments: Arguments? = nil) {
|
||||
self.configurationName = configurationName
|
||||
self.executable = executable
|
||||
self.filePath = filePath
|
||||
self.arguments = arguments
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,11 @@ import Foundation
|
|||
public extension RunAction {
|
||||
static func test(configurationName: String = BuildConfiguration.debug.name,
|
||||
executable: TargetReference? = TargetReference(projectPath: "/Project", name: "App"),
|
||||
filePath: AbsolutePath? = nil,
|
||||
arguments: Arguments? = Arguments.test()) -> RunAction {
|
||||
RunAction(configurationName: configurationName,
|
||||
executable: executable,
|
||||
filePath: filePath,
|
||||
arguments: arguments)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class ProjectGroups {
|
|||
frameworks: PBXGroup,
|
||||
playgrounds: PBXGroup?,
|
||||
pbxproj: PBXProj) {
|
||||
self.sortedMain = main
|
||||
sortedMain = main
|
||||
self.projectGroups = Dictionary(uniqueKeysWithValues: projectGroups)
|
||||
self.products = products
|
||||
self.frameworks = frameworks
|
||||
|
|
|
@ -330,19 +330,26 @@ final class SchemesGenerator: SchemesGenerating {
|
|||
target = executable
|
||||
}
|
||||
|
||||
guard let targetNode = try graph.target(path: target.projectPath, name: target.name) else { return nil }
|
||||
guard let buildableReference = try createBuildableReference(targetReference: target,
|
||||
graph: graph,
|
||||
rootPath: rootPath,
|
||||
generatedProjects: generatedProjects) else { return nil }
|
||||
|
||||
var buildableProductRunnable: XCScheme.BuildableProductRunnable?
|
||||
var macroExpansion: XCScheme.BuildableReference?
|
||||
var pathRunnable: XCScheme.PathRunnable?
|
||||
var defaultBuildConfiguration = BuildConfiguration.debug.name
|
||||
|
||||
if targetNode.target.product.runnable {
|
||||
buildableProductRunnable = XCScheme.BuildableProductRunnable(buildableReference: buildableReference, runnableDebuggingMode: "0")
|
||||
if let filePath = scheme.runAction?.filePath {
|
||||
pathRunnable = XCScheme.PathRunnable(filePath: filePath.pathString)
|
||||
} else {
|
||||
macroExpansion = buildableReference
|
||||
guard let targetNode = try graph.target(path: target.projectPath, name: target.name) else { return nil }
|
||||
defaultBuildConfiguration = defaultDebugBuildConfigurationName(in: targetNode.project)
|
||||
guard let buildableReference = try createBuildableReference(targetReference: target,
|
||||
graph: graph,
|
||||
rootPath: rootPath,
|
||||
generatedProjects: generatedProjects) else { return nil }
|
||||
|
||||
if targetNode.target.product.runnable {
|
||||
buildableProductRunnable = XCScheme.BuildableProductRunnable(buildableReference: buildableReference, runnableDebuggingMode: "0")
|
||||
} else {
|
||||
macroExpansion = buildableReference
|
||||
}
|
||||
}
|
||||
|
||||
var commandlineArguments: XCScheme.CommandLineArguments?
|
||||
|
@ -353,10 +360,11 @@ final class SchemesGenerator: SchemesGenerating {
|
|||
environments = environmentVariables(arguments.environment)
|
||||
}
|
||||
|
||||
let buildConfiguration = scheme.runAction?.configurationName ?? defaultDebugBuildConfigurationName(in: targetNode.project)
|
||||
let buildConfiguration = scheme.runAction?.configurationName ?? defaultBuildConfiguration
|
||||
return XCScheme.LaunchAction(runnable: buildableProductRunnable,
|
||||
buildConfiguration: buildConfiguration,
|
||||
macroExpansion: macroExpansion,
|
||||
pathRunnable: pathRunnable,
|
||||
commandlineArguments: commandlineArguments,
|
||||
environmentVariables: environments)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import XcodeProj
|
|||
@propertyWrapper
|
||||
class SortedPBXGroup {
|
||||
var value: PBXGroup
|
||||
|
||||
|
||||
var wrappedValue: PBXGroup {
|
||||
get {
|
||||
value.childGroups.forEach(sort) // We preserve the order of the root level groups and files
|
||||
|
@ -14,11 +14,11 @@ class SortedPBXGroup {
|
|||
value = newValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init(wrappedValue: PBXGroup) {
|
||||
self.value = wrappedValue
|
||||
value = wrappedValue
|
||||
}
|
||||
|
||||
|
||||
// The sorting implementation was taken from https://github.com/yonaskolb/XcodeGen/blob/d64cfff8a1ca01fd8f18cbb41f72230983c4a192/Sources/XcodeGenKit/PBXProjGenerator.swift
|
||||
// We require exactly the same sort which places groups over files while using the PBXGroup from Xcodeproj.
|
||||
private func sort(with group: PBXGroup) {
|
||||
|
@ -52,7 +52,7 @@ private extension PBXFileElement {
|
|||
}
|
||||
|
||||
static func sortByNameThenPath(_ lhs: PBXFileElement, _ rhs: PBXFileElement) -> Bool {
|
||||
return lhs.namePathSortString.localizedStandardCompare(rhs.namePathSortString) == .orderedAscending
|
||||
lhs.namePathSortString.localizedStandardCompare(rhs.namePathSortString) == .orderedAscending
|
||||
}
|
||||
|
||||
var namePathSortString: String {
|
||||
|
|
|
@ -74,7 +74,11 @@ final class ProjectEditor: ProjectEditing {
|
|||
throw ProjectEditorError.noEditableFiles(at)
|
||||
}
|
||||
|
||||
let (project, graph) = projectEditorMapper.map(sourceRootPath: at,
|
||||
// To be sure that we are using the same binary of Tuist that invoked `edit`
|
||||
let tuistPath = AbsolutePath(CommandRegistry.processArguments().first!)
|
||||
|
||||
let (project, graph) = projectEditorMapper.map(tuistPath: tuistPath,
|
||||
sourceRootPath: at,
|
||||
manifests: manifests.map { $0.1 },
|
||||
helpers: helpers,
|
||||
projectDescriptionPath: projectDesciptionPath)
|
||||
|
|
|
@ -4,7 +4,8 @@ import TuistCore
|
|||
import TuistSupport
|
||||
|
||||
protocol ProjectEditorMapping: AnyObject {
|
||||
func map(sourceRootPath: AbsolutePath,
|
||||
func map(tuistPath: AbsolutePath,
|
||||
sourceRootPath: AbsolutePath,
|
||||
manifests: [AbsolutePath],
|
||||
helpers: [AbsolutePath],
|
||||
projectDescriptionPath: AbsolutePath) -> (Project, Graph)
|
||||
|
@ -12,7 +13,8 @@ protocol ProjectEditorMapping: AnyObject {
|
|||
|
||||
final class ProjectEditorMapper: ProjectEditorMapping {
|
||||
// swiftlint:disable:next function_body_length
|
||||
func map(sourceRootPath: AbsolutePath,
|
||||
func map(tuistPath: AbsolutePath,
|
||||
sourceRootPath: AbsolutePath,
|
||||
manifests: [AbsolutePath],
|
||||
helpers: [AbsolutePath],
|
||||
projectDescriptionPath: AbsolutePath) -> (Project, Graph) {
|
||||
|
@ -54,12 +56,20 @@ final class ProjectEditorMapper: ProjectEditorMapping {
|
|||
targets.append(manifestsTarget)
|
||||
if let helpersTarget = helpersTarget { targets.append(helpersTarget) }
|
||||
|
||||
// Run Scheme
|
||||
let buildAction = BuildAction(targets: targets.map { TargetReference(projectPath: sourceRootPath, name: $0.name) })
|
||||
let arguments = Arguments(launch: ["generate --path \(sourceRootPath)": true])
|
||||
|
||||
let runAction = RunAction(configurationName: "Debug", filePath: tuistPath, arguments: arguments)
|
||||
let scheme = Scheme(name: "Manifests", shared: true, buildAction: buildAction, runAction: runAction)
|
||||
|
||||
// Project
|
||||
let project = Project(path: sourceRootPath,
|
||||
name: "Manifests",
|
||||
settings: projectSettings,
|
||||
filesGroup: .group(name: "Manifests"),
|
||||
targets: targets)
|
||||
targets: targets,
|
||||
schemes: [scheme])
|
||||
|
||||
// Graph
|
||||
let cache = GraphLoaderCache()
|
||||
|
|
|
@ -459,6 +459,31 @@ final class SchemesGeneratorTests: XCTestCase {
|
|||
|
||||
let target = Target.test(name: "Library", platform: .iOS, product: .dynamicLibrary)
|
||||
|
||||
let buildAction = BuildAction.test(targets: [TargetReference(projectPath: projectPath, name: "Library")])
|
||||
let launchAction = RunAction.test(configurationName: "Debug", filePath: "/usr/bin/foo")
|
||||
|
||||
let scheme = Scheme.test(name: "Library", buildAction: buildAction, runAction: launchAction)
|
||||
let project = Project.test(path: projectPath, targets: [target])
|
||||
let graph = Graph.create(dependencies: [(project: project, target: target, dependencies: [])])
|
||||
|
||||
// When
|
||||
let got = try subject.schemeLaunchAction(scheme: scheme,
|
||||
graph: graph,
|
||||
rootPath: projectPath,
|
||||
generatedProjects: createGeneratedProjects(projects: [project]))
|
||||
|
||||
// Then
|
||||
let result = try XCTUnwrap(got)
|
||||
XCTAssertNil(result.runnable?.buildableReference)
|
||||
XCTAssertEqual(result.buildConfiguration, "Debug")
|
||||
XCTAssertEqual(result.pathRunnable?.filePath, "/usr/bin/foo")
|
||||
}
|
||||
|
||||
func test_schemeLaunchAction_with_path() throws {
|
||||
let projectPath = AbsolutePath("/somepath/Project")
|
||||
|
||||
let target = Target.test(name: "Library", platform: .iOS, product: .dynamicLibrary)
|
||||
|
||||
let buildAction = BuildAction.test(targets: [TargetReference(projectPath: projectPath, name: "Library")])
|
||||
let testAction = TestAction.test(targets: [TestableTarget(target: TargetReference(projectPath: projectPath, name: "Library"))])
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import XcodeProj
|
||||
|
||||
@testable import TuistSupportTesting
|
||||
@testable import TuistGenerator
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
class SortedPBXGroupTests: TuistTestCase {
|
||||
var subject: SortedPBXGroup!
|
||||
|
@ -159,7 +159,7 @@ class SortedPBXGroupTests: TuistTestCase {
|
|||
file("file2"),
|
||||
file("file3"),
|
||||
file("file4.swift"),
|
||||
])
|
||||
]),
|
||||
]))
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,15 @@ import TuistCore
|
|||
|
||||
final class MockProjectEditorMapper: ProjectEditorMapping {
|
||||
var mapStub: (Project, Graph)?
|
||||
var mapArgs: [(sourceRootPath: AbsolutePath, manifests: [AbsolutePath], helpers: [AbsolutePath], projectDescriptionPath: AbsolutePath)] = []
|
||||
var mapArgs: [(tuistPath: AbsolutePath, sourceRootPath: AbsolutePath, manifests: [AbsolutePath], helpers: [AbsolutePath], projectDescriptionPath: AbsolutePath)] = []
|
||||
|
||||
func map(sourceRootPath: AbsolutePath,
|
||||
func map(tuistPath: AbsolutePath,
|
||||
sourceRootPath: AbsolutePath,
|
||||
manifests: [AbsolutePath],
|
||||
helpers: [AbsolutePath],
|
||||
projectDescriptionPath: AbsolutePath) -> (Project, Graph) {
|
||||
mapArgs.append((sourceRootPath: sourceRootPath,
|
||||
mapArgs.append((tuistPath: tuistPath,
|
||||
sourceRootPath: sourceRootPath,
|
||||
manifests: manifests,
|
||||
helpers: helpers,
|
||||
projectDescriptionPath: projectDescriptionPath))
|
||||
|
|
|
@ -16,8 +16,8 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
|
|||
}
|
||||
|
||||
override func tearDown() {
|
||||
super.tearDown()
|
||||
subject = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_edit_when_there_are_helpers() throws {
|
||||
|
@ -26,48 +26,65 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
|
|||
let manifestPaths = [sourceRootPath].map { $0.appending(component: "Project.swift") }
|
||||
let helperPaths = [sourceRootPath].map { $0.appending(component: "Project+Template.swift") }
|
||||
let projectDescriptionPath = sourceRootPath.appending(component: "ProjectDescription.framework")
|
||||
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
|
||||
|
||||
// When
|
||||
let (project, graph) = subject.map(sourceRootPath: sourceRootPath,
|
||||
let (project, graph) = subject.map(tuistPath: tuistPath,
|
||||
sourceRootPath: sourceRootPath,
|
||||
manifests: manifestPaths,
|
||||
helpers: helperPaths,
|
||||
projectDescriptionPath: projectDescriptionPath)
|
||||
|
||||
// Then
|
||||
let manifestsTarget = project.targets.first
|
||||
let helpersTarget = project.targets.last
|
||||
let expectedManifestsTarget = Target(name: "Manifests",
|
||||
platform: .macOS,
|
||||
product: .staticFramework,
|
||||
productName: "Manifests",
|
||||
bundleId: "io.tuist.${PRODUCT_NAME:rfc1034identifier}",
|
||||
settings: expectedSettings(sourceRootPath: sourceRootPath),
|
||||
sources: manifestPaths.map { (path: $0, compilerFlags: nil) },
|
||||
filesGroup: .group(name: "Manifests"),
|
||||
dependencies: [.target(name: "ProjectDescriptionHelpers")])
|
||||
let expectedHelpersTarget = Target(name: "ProjectDescriptionHelpers",
|
||||
platform: .macOS,
|
||||
product: .staticFramework,
|
||||
productName: "ProjectDescriptionHelpers",
|
||||
bundleId: "io.tuist.${PRODUCT_NAME:rfc1034identifier}",
|
||||
settings: expectedSettings(sourceRootPath: sourceRootPath),
|
||||
sources: helperPaths.map { (path: $0, compilerFlags: nil) },
|
||||
filesGroup: .group(name: "Manifests"),
|
||||
dependencies: [])
|
||||
let expectedProject = Project(path: sourceRootPath,
|
||||
name: "Manifests",
|
||||
settings: Settings(base: [:],
|
||||
configurations: Settings.default.configurations,
|
||||
defaultSettings: .recommended),
|
||||
filesGroup: .group(name: "Manifests"),
|
||||
targets: [expectedManifestsTarget, expectedHelpersTarget])
|
||||
XCTAssertEqual(project, expectedProject)
|
||||
|
||||
let targetNodes = graph.targets.sorted(by: { $0.target.name < $1.target.name })
|
||||
XCTAssertEqual(targetNodes.count, 2)
|
||||
XCTAssertEqual(targetNodes.first?.target, manifestsTarget)
|
||||
XCTAssertEqual(targetNodes.last?.target, helpersTarget)
|
||||
XCTAssertEqual(targetNodes.first?.dependencies, [targetNodes.last!])
|
||||
|
||||
// Generated Manifests target
|
||||
let manifestsTarget = try XCTUnwrap(project.targets.first)
|
||||
XCTAssertEqual(targetNodes.first?.target, manifestsTarget)
|
||||
|
||||
XCTAssertEqual(manifestsTarget.name, "Manifests")
|
||||
XCTAssertEqual(manifestsTarget.platform, .macOS)
|
||||
XCTAssertEqual(manifestsTarget.product, .staticFramework)
|
||||
XCTAssertEqual(manifestsTarget.settings, expectedSettings(sourceRootPath: sourceRootPath))
|
||||
XCTAssertEqual(manifestsTarget.sources.map { $0.path }, manifestPaths)
|
||||
XCTAssertEqual(manifestsTarget.filesGroup, .group(name: "Manifests"))
|
||||
XCTAssertEqual(manifestsTarget.dependencies, [.target(name: "ProjectDescriptionHelpers")])
|
||||
|
||||
// Generated Helpers target
|
||||
let helpersTarget = try XCTUnwrap(project.targets.last)
|
||||
XCTAssertEqual(targetNodes.last?.target, helpersTarget)
|
||||
|
||||
XCTAssertEqual(helpersTarget.name, "ProjectDescriptionHelpers")
|
||||
XCTAssertEqual(helpersTarget.platform, .macOS)
|
||||
XCTAssertEqual(helpersTarget.product, .staticFramework)
|
||||
XCTAssertEqual(helpersTarget.settings, expectedSettings(sourceRootPath: sourceRootPath))
|
||||
XCTAssertEqual(helpersTarget.sources.map { $0.path }, helperPaths)
|
||||
XCTAssertEqual(helpersTarget.filesGroup, .group(name: "Manifests"))
|
||||
XCTAssertEqual(helpersTarget.dependencies, [])
|
||||
|
||||
// Generated Project
|
||||
XCTAssertEqual(project.path, sourceRootPath)
|
||||
XCTAssertEqual(project.name, "Manifests")
|
||||
XCTAssertEqual(project.settings, Settings(base: [:],
|
||||
configurations: Settings.default.configurations,
|
||||
defaultSettings: .recommended))
|
||||
XCTAssertEqual(project.filesGroup, .group(name: "Manifests"))
|
||||
XCTAssertEqual(project.targets, targetNodes.map { $0.target })
|
||||
|
||||
// Generated Scheme
|
||||
XCTAssertEqual(project.schemes.count, 1)
|
||||
let scheme = try XCTUnwrap(project.schemes.first)
|
||||
XCTAssertEqual(scheme.name, "Manifests")
|
||||
|
||||
let buildAction = try XCTUnwrap(scheme.buildAction)
|
||||
XCTAssertEqual(buildAction.targets.map { $0.name }, targetNodes.map { $0.name })
|
||||
|
||||
let runAction = try XCTUnwrap(scheme.runAction)
|
||||
XCTAssertEqual(runAction.filePath, tuistPath)
|
||||
let generateArgument = "generate --path \(sourceRootPath)"
|
||||
XCTAssertEqual(runAction.arguments, Arguments(launch: [generateArgument: true]))
|
||||
}
|
||||
|
||||
func test_edit_when_there_are_no_helpers() throws {
|
||||
|
@ -76,39 +93,53 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
|
|||
let manifestPaths = [sourceRootPath].map { $0.appending(component: "Project.swift") }
|
||||
let helperPaths: [AbsolutePath] = []
|
||||
let projectDescriptionPath = sourceRootPath.appending(component: "ProjectDescription.framework")
|
||||
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
|
||||
|
||||
// When
|
||||
let (project, graph) = subject.map(sourceRootPath: sourceRootPath,
|
||||
let (project, graph) = subject.map(tuistPath: tuistPath,
|
||||
sourceRootPath: sourceRootPath,
|
||||
manifests: manifestPaths,
|
||||
helpers: helperPaths,
|
||||
projectDescriptionPath: projectDescriptionPath)
|
||||
|
||||
// Then
|
||||
let manifestsTarget = project.targets.first
|
||||
XCTAssertEqual(project.targets.count, 1)
|
||||
|
||||
let expectedManifestsTarget = Target(name: "Manifests",
|
||||
platform: .macOS,
|
||||
product: .staticFramework,
|
||||
productName: "Manifests",
|
||||
bundleId: "io.tuist.${PRODUCT_NAME:rfc1034identifier}",
|
||||
settings: expectedSettings(sourceRootPath: sourceRootPath),
|
||||
sources: manifestPaths.map { (path: $0, compilerFlags: nil) },
|
||||
filesGroup: .group(name: "Manifests"),
|
||||
dependencies: [])
|
||||
let expectedProject = Project(path: sourceRootPath,
|
||||
name: "Manifests",
|
||||
settings: Settings(base: [:],
|
||||
configurations: Settings.default.configurations,
|
||||
defaultSettings: .recommended),
|
||||
filesGroup: .group(name: "Manifests"),
|
||||
targets: [expectedManifestsTarget])
|
||||
XCTAssertEqual(project, expectedProject)
|
||||
|
||||
let targetNodes = graph.targets.sorted(by: { $0.target.name < $1.target.name })
|
||||
XCTAssertEqual(targetNodes.count, 1)
|
||||
XCTAssertEqual(targetNodes.first?.target, manifestsTarget)
|
||||
XCTAssertEqual(targetNodes.first?.dependencies, [])
|
||||
|
||||
// Generated Manifests target
|
||||
let manifestsTarget = try XCTUnwrap(project.targets.first)
|
||||
XCTAssertEqual(targetNodes.first?.target, manifestsTarget)
|
||||
|
||||
XCTAssertEqual(manifestsTarget.name, "Manifests")
|
||||
XCTAssertEqual(manifestsTarget.platform, .macOS)
|
||||
XCTAssertEqual(manifestsTarget.product, .staticFramework)
|
||||
XCTAssertEqual(manifestsTarget.settings, expectedSettings(sourceRootPath: sourceRootPath))
|
||||
XCTAssertEqual(manifestsTarget.sources.map { $0.path }, manifestPaths)
|
||||
XCTAssertEqual(manifestsTarget.filesGroup, .group(name: "Manifests"))
|
||||
XCTAssertEqual(manifestsTarget.dependencies, [])
|
||||
|
||||
// Generated Project
|
||||
XCTAssertEqual(project.path, sourceRootPath)
|
||||
XCTAssertEqual(project.name, "Manifests")
|
||||
XCTAssertEqual(project.settings, Settings(base: [:],
|
||||
configurations: Settings.default.configurations,
|
||||
defaultSettings: .recommended))
|
||||
XCTAssertEqual(project.filesGroup, .group(name: "Manifests"))
|
||||
XCTAssertEqual(project.targets, targetNodes.map { $0.target })
|
||||
|
||||
// Generated Scheme
|
||||
XCTAssertEqual(project.schemes.count, 1)
|
||||
let scheme = try XCTUnwrap(project.schemes.first)
|
||||
XCTAssertEqual(scheme.name, "Manifests")
|
||||
|
||||
let buildAction = try XCTUnwrap(scheme.buildAction)
|
||||
XCTAssertEqual(buildAction.targets.map { $0.name }, targetNodes.map { $0.name })
|
||||
|
||||
let runAction = try XCTUnwrap(scheme.runAction)
|
||||
XCTAssertEqual(runAction.filePath, tuistPath)
|
||||
let generateArgument = "generate --path \(sourceRootPath)"
|
||||
XCTAssertEqual(runAction.arguments, Arguments(launch: [generateArgument: true]))
|
||||
}
|
||||
|
||||
fileprivate func expectedSettings(sourceRootPath: AbsolutePath) -> Settings {
|
||||
|
|
|
@ -62,6 +62,7 @@ final class ProjectEditorTests: TuistUnitTestCase {
|
|||
let helpers = ["A.swift", "B.swift"].map { helpersDirectory.appending(component: $0) }
|
||||
try helpers.forEach { try FileHandler.shared.touch($0) }
|
||||
let manifests: [(Manifest, AbsolutePath)] = [(.project, directory.appending(component: "Project.swift"))]
|
||||
let tuistPath = AbsolutePath(ProcessInfo.processInfo.arguments.first!)
|
||||
|
||||
resourceLocator.projectDescriptionStub = { projectDescriptionPath }
|
||||
manifestFilesLocator.locateStub = manifests
|
||||
|
@ -79,6 +80,7 @@ final class ProjectEditorTests: TuistUnitTestCase {
|
|||
// Then
|
||||
XCTAssertEqual(projectEditorMapper.mapArgs.count, 1)
|
||||
let mapArgs = projectEditorMapper.mapArgs.first
|
||||
XCTAssertEqual(mapArgs?.tuistPath, tuistPath)
|
||||
XCTAssertEqual(mapArgs?.helpers, helpers)
|
||||
XCTAssertEqual(mapArgs?.sourceRootPath, directory)
|
||||
XCTAssertEqual(mapArgs?.projectDescriptionPath, projectDescriptionPath)
|
||||
|
|
|
@ -14,7 +14,7 @@ Editing your projects is easy; position yourself in a directory where there's a
|
|||
tuist edit
|
||||
```
|
||||
|
||||
It'll generate a temporary Xcode project with the manfiests and the project description helpers. Please note that the project doesn't get generated as the files are edited. Once you are done with editing, you can close the project and run `tuist generate`.
|
||||
It will open a temporary Xcode project with the manifests and the project description helpers. After making changes you can run the target from Xcode and it will call `tuist generate` for you.
|
||||
|
||||
The project is deleted automatically once you are done with editing. If you wish to generate and keep the project in the current directory, you can run the command passing the `--permanent` argument:
|
||||
|
||||
|
|
Loading…
Reference in New Issue