Generate tuist generated file into workspace to solve ambiguity. (#1427)

* Generate tuist generated file into workspace to solve ambiguity.

* Edit changelog.

* Move generating tuist-generated file to TuistKit.

* Fix BuildGraphInspector tests.

* Add test for no tuist workspace present.

* Add loadProjectWorkspace method to add tuist-generated to project workspace.

* Run swiftformat.
This commit is contained in:
Marek Fořt 2020-06-11 20:32:32 +02:00 committed by GitHub
parent 168c32ba96
commit 036fa7559b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 83 additions and 15 deletions

View File

@ -12,6 +12,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
### Fixed
- Fix `tuist build` building a wrong workspace [#1427](https://github.com/tuist/tuist/pull/1427) by [@fortmarek](https://github.com/fortmarek)
- `tuist edit` always creates a project in a new temp dir [#1424](https://github.com/tuist/tuist/pull/1424) by [@fortmarek](https://github.com/fortmarek)
- Fix `tuist init` and `tuist scaffold` with new ArgumentParser version [#1425](https://github.com/tuist/tuist/pull/1425) by [@fortmarek](https://github.com/fortmarek)
- `--clean` argument ot the build command [#1421](https://github.com/tuist/tuist/pull/1421) by [@pepibumur](https://github.com/pepibumur)

View File

@ -1,6 +1,7 @@
import Foundation
import TSCBasic
import TuistCore
import TuistSupport
public protocol BuildGraphInspecting {
/// Returns the build arguments to be used with the given target.
@ -10,7 +11,7 @@ public protocol BuildGraphInspecting {
/// Given a directory, it returns the first .xcworkspace found.
/// - Parameter path: Found .xcworkspace.
func workspacePath(directory: AbsolutePath) -> AbsolutePath?
func workspacePath(directory: AbsolutePath) throws -> AbsolutePath?
/// From the list of buildable targets of the given scheme, it returns the first one.
/// - Parameters:
@ -62,7 +63,13 @@ public class BuildGraphInspector: BuildGraphInspecting {
.sorted(by: { $0.name < $1.name })
}
public func workspacePath(directory: AbsolutePath) -> AbsolutePath? {
directory.glob("**/*.xcworkspace").first
public func workspacePath(directory: AbsolutePath) throws -> AbsolutePath? {
try directory.glob("**/*.xcworkspace")
.filter {
try FileHandler.shared.contentsOfDirectory($0)
.map(\.basename)
.contains(Constants.tuistGeneratedFileName)
}
.first
}
}

View File

@ -123,12 +123,14 @@ final class WorkspaceGenerator: WorkspaceGenerating {
generatedProjects: generatedProjects,
graph: graph)
return WorkspaceDescriptor(path: path,
xcworkspacePath: workspacePath,
xcworkspace: xcWorkspace,
projectDescriptors: projects,
schemeDescriptors: schemes,
sideEffectDescriptors: [])
return WorkspaceDescriptor(
path: path,
xcworkspacePath: workspacePath,
xcworkspace: xcWorkspace,
projectDescriptors: projects,
schemeDescriptors: schemes,
sideEffectDescriptors: []
)
}
/// Create a XCWorkspaceDataElement.file from a path string.

View File

@ -124,7 +124,7 @@ class ProjectGenerator: ProjectGenerating {
private func generateProjectWorkspace(path: AbsolutePath) throws -> (AbsolutePath, Graph) {
// Load
let (project, graph, sideEffects) = try loadProject(path: path)
let (project, graph, sideEffects) = try loadProjectWorkspace(path: path)
// Lint
try lint(graph: graph)
@ -191,6 +191,23 @@ class ProjectGenerator: ProjectGenerating {
return (project, updatedGraph, modelMapperSideEffects + graphMapperSideEffects)
}
private func loadProjectWorkspace(path: AbsolutePath) throws -> (Project, Graph, [SideEffectDescriptor]) {
// Load project
let (project, graph, sideEffects) = try loadProject(path: path)
/// Used to disambiguate which workspaces are generated by tuist and which are not
let tuistGeneratedFileDescriptor = FileDescriptor(
path: project.path.appending(components: "\(project.name).xcworkspace", Constants.tuistGeneratedFileName)
)
/// Additional side effects
let additionalSideEffects: [SideEffectDescriptor] = [
.file(tuistGeneratedFileDescriptor),
]
return (project, graph, sideEffects + additionalSideEffects)
}
private func loadWorkspace(path: AbsolutePath) throws -> (Workspace, Graph, [SideEffectDescriptor]) {
// Load all manifests
let manifests = try recursiveManifestLoader.loadWorkspace(at: path)
@ -220,7 +237,17 @@ class ProjectGenerator: ProjectGenerating {
// Apply graph mappers
let (updatedGraph, graphMapperSideEffects) = try graphMapperProvider.mapper(config: config).map(graph: graph)
return (workspace, updatedGraph, modelMapperSideEffects + graphMapperSideEffects)
/// Used to disambiguate which workspaces are generated by tuist and which are not
let tuistGeneratedFileDescriptor = FileDescriptor(
path: workspace.path.appending(components: "\(workspace.name).xcworkspace", Constants.tuistGeneratedFileName)
)
/// Additional side effects
let additionalSideEffects: [SideEffectDescriptor] = [
.file(tuistGeneratedFileDescriptor),
]
return (workspace, updatedGraph, modelMapperSideEffects + graphMapperSideEffects + additionalSideEffects)
}
private func convert(manifests: LoadedProjects,

View File

@ -50,7 +50,7 @@ final class BuildService {
func run(schemeName: String?, generate: Bool, clean: Bool, configuration: String?, path: AbsolutePath) throws {
let graph: Graph
if generate || buildGraphInspector.workspacePath(directory: path) == nil {
if try (generate || buildGraphInspector.workspacePath(directory: path) == nil) {
graph = try projectGenerator.generateWithGraph(path: path, projectOnly: false).1
} else {
graph = try projectGenerator.load(path: path)
@ -82,7 +82,7 @@ final class BuildService {
guard let buildableTarget = buildGraphInspector.buildableTarget(scheme: scheme, graph: graph) else {
throw BuildServiceError.schemeWithoutBuildableTargets(scheme: scheme.name)
}
let workspacePath = buildGraphInspector.workspacePath(directory: path)!
let workspacePath = try buildGraphInspector.workspacePath(directory: path)!
_ = try xcodebuildController.build(.workspace(workspacePath),
scheme: scheme.name,
clean: clean,

View File

@ -15,6 +15,7 @@ public struct Constants {
public static let templatesDirectoryName: String = "Templates"
public static let twitterHandle: String = "tuistio"
public static let joinSlackURL: String = "https://slack.tuist.io/"
public static let tuistGeneratedFileName = ".tuist-generated"
public struct EnvironmentVariables {
public static let colouredOutput = "TUIST_COLOURED_OUTPUT"

View File

@ -166,10 +166,40 @@ final class BuildGraphInspectorTests: TuistUnitTestCase {
// Given
let path = try temporaryPath()
let workspacePath = path.appending(component: "App.xcworkspace")
try FileHandler.shared.touch(workspacePath)
try FileHandler.shared.createFolder(workspacePath)
try FileHandler.shared.touch(workspacePath.appending(component: Constants.tuistGeneratedFileName))
// When
let got = subject.workspacePath(directory: path)
let got = try subject.workspacePath(directory: path)
// Then
XCTAssertEqual(got, workspacePath)
}
func test_workspacePath_when_no_tuist_workspace_is_present() throws {
// Given
let path = try temporaryPath()
let workspacePath = path.appending(component: "App.xcworkspace")
try FileHandler.shared.createFolder(workspacePath)
// When
let got = try subject.workspacePath(directory: path)
// Then
XCTAssertNil(got)
}
func test_workspacePath_when_multiple_workspaces_are_present() throws {
// Given
let path = try temporaryPath()
let nonTuistWorkspacePath = path.appending(components: "SPM.xcworkspace")
try FileHandler.shared.createFolder(nonTuistWorkspacePath)
let workspacePath = path.appending(component: "TuistApp.xcworkspace")
try FileHandler.shared.createFolder(workspacePath)
try FileHandler.shared.touch(workspacePath.appending(component: Constants.tuistGeneratedFileName))
// When
let got = try subject.workspacePath(directory: path)
// Then
XCTAssertEqual(got, workspacePath)