Skip to content

Commit

Permalink
Add tuist graph support for non-generated Xcode projects (tuist#7322)
Browse files Browse the repository at this point in the history
  • Loading branch information
fortmarek authored Feb 18, 2025
1 parent 3850408 commit 1134fc4
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 16 deletions.
17 changes: 15 additions & 2 deletions Sources/TuistKit/Services/GraphService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import TuistLoader
import TuistPlugin
import TuistSupport
import XcodeGraph
import XcodeGraphMapper

final class GraphService {
private let graphVizMapper: GraphToGraphVizMapping
private let manifestGraphLoader: ManifestGraphLoading
private let fileSystem: FileSystem
private let manifestLoader: ManifestLoading
private let xcodeGraphMapper: XcodeGraphMapping

convenience init() {
let manifestLoader = ManifestLoaderFactory()
Expand All @@ -29,17 +32,22 @@ final class GraphService {
let graphVizMapper = GraphToGraphVizMapper()
self.init(
graphVizGenerator: graphVizMapper,
manifestGraphLoader: manifestGraphLoader
manifestGraphLoader: manifestGraphLoader,
manifestLoader: manifestLoader
)
}

init(
graphVizGenerator: GraphToGraphVizMapping,
manifestGraphLoader: ManifestGraphLoading,
manifestLoader: ManifestLoading,
xcodeGraphMapper: XcodeGraphMapping = XcodeGraphMapper(),
fileSystem: FileSystem = FileSystem()
) {
graphVizMapper = graphVizGenerator
self.manifestGraphLoader = manifestGraphLoader
self.manifestLoader = manifestLoader
self.xcodeGraphMapper = xcodeGraphMapper
self.fileSystem = fileSystem
}

Expand All @@ -54,7 +62,12 @@ final class GraphService {
path: AbsolutePath,
outputPath: AbsolutePath
) async throws {
let (graph, _, _, _) = try await manifestGraphLoader.load(path: path)
let graph: XcodeGraph.Graph
if try await manifestLoader.hasRootManifest(at: path) {
(graph, _, _, _) = try await manifestGraphLoader.load(path: path)
} else {
graph = try await xcodeGraphMapper.map(at: path)
}

let fileExtension = switch format {
case .legacyJSON:
Expand Down
89 changes: 75 additions & 14 deletions Tests/TuistKitTests/Services/GraphServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,45 @@ import Mockable
import ProjectAutomation
import ServiceContextModule
import TuistCore
import TuistCoreTesting
import TuistLoader
import TuistLoaderTesting
import TuistPlugin
import TuistSupport
import TuistSupportTesting
import XcodeGraph
import XcodeProj
import XCTest

@testable import TuistCoreTesting
@testable import TuistKit
@testable import TuistLoaderTesting
@testable import TuistSupportTesting

final class GraphServiceTests: TuistUnitTestCase {
var manifestGraphLoader: MockManifestGraphLoading!
var graphVizMapper: MockGraphToGraphVizMapper!
var subject: GraphService!
private var manifestGraphLoader: MockManifestGraphLoading!
private var manifestLoader: MockManifestLoading!
private var graphVizMapper: MockGraphToGraphVizMapper!
private var xcodeGraphMapper: MockXcodeGraphMapping!
private var subject: GraphService!

override func setUp() {
super.setUp()
graphVizMapper = MockGraphToGraphVizMapper()
manifestGraphLoader = .init()
manifestGraphLoader = MockManifestGraphLoading()
manifestLoader = MockManifestLoading()
xcodeGraphMapper = MockXcodeGraphMapping()

subject = GraphService(
graphVizGenerator: graphVizMapper,
manifestGraphLoader: manifestGraphLoader
manifestGraphLoader: manifestGraphLoader,
manifestLoader: manifestLoader,
xcodeGraphMapper: xcodeGraphMapper
)
}

override func tearDown() {
graphVizMapper = nil
manifestGraphLoader = nil
manifestLoader = nil
xcodeGraphMapper = nil
subject = nil
super.tearDown()
}
Expand All @@ -46,8 +55,12 @@ final class GraphServiceTests: TuistUnitTestCase {
let graphPath = temporaryPath.appending(component: "graph.dot")
let projectManifestPath = temporaryPath.appending(component: "Project.swift")

try FileHandler.shared.touch(graphPath)
try FileHandler.shared.touch(projectManifestPath)
given(manifestLoader)
.hasRootManifest(at: .any)
.willReturn(true)

try await fileSystem.touch(graphPath)
try await fileSystem.touch(projectManifestPath)
graphVizMapper.stubMap = Graph()

given(manifestGraphLoader)
Expand All @@ -66,7 +79,7 @@ final class GraphServiceTests: TuistUnitTestCase {
path: temporaryPath,
outputPath: temporaryPath
)
let got = try FileHandler.shared.readTextFile(graphPath)
let got = try await fileSystem.readTextFile(at: graphPath)
let expected = "graph { }"
// Then
XCTAssertEqual(got, expected)
Expand All @@ -84,8 +97,12 @@ final class GraphServiceTests: TuistUnitTestCase {
let graphPath = temporaryPath.appending(component: "graph.json")
let projectManifestPath = temporaryPath.appending(component: "Project.swift")

try FileHandler.shared.touch(graphPath)
try FileHandler.shared.touch(projectManifestPath)
given(manifestLoader)
.hasRootManifest(at: .any)
.willReturn(true)

try await fileSystem.touch(graphPath)
try await fileSystem.touch(projectManifestPath)

given(manifestGraphLoader)
.load(path: .any)
Expand All @@ -103,7 +120,7 @@ final class GraphServiceTests: TuistUnitTestCase {
path: temporaryPath,
outputPath: temporaryPath
)
let got = try FileHandler.shared.readTextFile(graphPath)
let got = try await fileSystem.readTextFile(at: graphPath)

let result = try JSONDecoder().decode(ProjectAutomation.Graph.self, from: got.data(using: .utf8)!)
// Then
Expand All @@ -125,6 +142,10 @@ final class GraphServiceTests: TuistUnitTestCase {
try await fileSystem.touch(graphPath)
try await fileSystem.touch(projectManifestPath)

given(manifestLoader)
.hasRootManifest(at: .any)
.willReturn(true)

given(manifestGraphLoader)
.load(path: .any)
.willReturn((.test(), [], MapperEnvironment(), []))
Expand Down Expand Up @@ -152,4 +173,44 @@ final class GraphServiceTests: TuistUnitTestCase {
""")
}
}

func test_run_when_json_and_has_no_root_manifest() async throws {
try await ServiceContext.withTestingDependencies {
// Given
let temporaryPath = try temporaryPath()
let graphPath = temporaryPath.appending(component: "graph.json")

try await fileSystem.touch(graphPath)

given(manifestLoader)
.hasRootManifest(at: .any)
.willReturn(false)

given(xcodeGraphMapper)
.map(at: .any)
.willReturn(.test())

// When
try await subject.run(
format: .json,
layoutAlgorithm: .dot,
skipTestTargets: false,
skipExternalDependencies: false,
open: false,
platformToFilter: nil,
targetsToFilter: [],
path: temporaryPath,
outputPath: temporaryPath
)
let got = try await fileSystem.readTextFile(at: graphPath)

let result = try JSONDecoder().decode(XcodeGraph.Graph.self, from: got.data(using: .utf8)!)
// Then
XCTAssertEqual(result, .test())
XCTAssertPrinterOutputContains("""
Deleting existing graph at \(graphPath.pathString)
Graph exported to \(graphPath.pathString)
""")
}
}
}

0 comments on commit 1134fc4

Please sign in to comment.