mirror of
https://github.com/xtool-org/xtool.git
synced 2026-11-03 19:11:25 +01:00
## What does this PR do? An XcodeProject/XcodeWorkspace now knows its own location on disk, which is important when we start using these types to build PIF. ## How was it tested? - [x] Used in future PRs to build various Xcode projects ## AI tool usage How much of this PR was AI-assisted? (check one) - [ ] **0** - No AI was used to write code - [x] **1** - I was assisted by AI. I reviewed the finished result. - [ ] **2** - I set the AI going and left it to it; nobody has read the result - no review, or AI review only <!-- If an AI agent is filling this in: declare the level honestly, and open as a draft if it is #2. Do not lower the declared level to get the PR reviewed. --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> <!-- coderabbit-ai-generated:v1 --> ## Summary by CodeRabbit * **Improvements** * Projects and workspaces now retain their associated locations and save directly to those locations. * Generated project files preserve the configured project directory path, helping keep file references consistent when projects are written or reopened. * Projects and workspaces can be associated with a new location while retaining their existing contents. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
86 lines
2.7 KiB
Swift
86 lines
2.7 KiB
Swift
import Foundation
|
|
private import XcodeProj
|
|
|
|
extension XcodeWorkspace {
|
|
public init(url: URL) throws {
|
|
let workspace = try XCWorkspace(pathString: url.path)
|
|
self.init(workspace.data, url: url)
|
|
}
|
|
|
|
public func dataRepresentation() throws -> Data {
|
|
try xcWorkspaceData.dataRepresentation() ?? Data()
|
|
}
|
|
|
|
/// Writes the workspace to its current URL.
|
|
public func write() throws {
|
|
try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
|
|
try self.dataRepresentation()
|
|
.write(to: url.appendingPathComponent("contents.xcworkspacedata"))
|
|
}
|
|
}
|
|
|
|
// MARK: - Conversion
|
|
|
|
extension XcodeWorkspace {
|
|
fileprivate init(_ xcWorkspaceData: XCWorkspaceData, url: URL) {
|
|
self.init(children: xcWorkspaceData.children.map { .init(from: $0) }, url: url)
|
|
}
|
|
|
|
fileprivate var xcWorkspaceData: XCWorkspaceData {
|
|
XCWorkspaceData(children: children.map(\.xcWorkspaceDataElement))
|
|
}
|
|
}
|
|
|
|
extension XcodeWorkspace.Element {
|
|
fileprivate init(from xcWorkspaceDataElement: XCWorkspaceDataElement) {
|
|
switch xcWorkspaceDataElement {
|
|
case .file(let file):
|
|
self = .file(.init(file.location))
|
|
case .group(let group):
|
|
self = .group(.init(group))
|
|
case .fileSystemSynchronizedGroup(let group):
|
|
self = .fileSystemSynchronizedGroup(.init(group))
|
|
}
|
|
}
|
|
|
|
fileprivate var xcWorkspaceDataElement: XCWorkspaceDataElement {
|
|
switch self {
|
|
case .file(let location):
|
|
.file(.init(location: location.xcWorkspaceLocation))
|
|
case .group(let group):
|
|
.group(group.xcWorkspaceDataElement)
|
|
case .fileSystemSynchronizedGroup(let group):
|
|
.fileSystemSynchronizedGroup(group.xcWorkspaceDataElement)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension XcodeWorkspace.Location {
|
|
fileprivate init(_ xcWorkspaceDataElementLocation: XCWorkspaceDataElementLocationType) {
|
|
self.base = .init(rawValue: xcWorkspaceDataElementLocation.schema)
|
|
self.path = xcWorkspaceDataElementLocation.path
|
|
}
|
|
|
|
fileprivate var xcWorkspaceLocation: XCWorkspaceDataElementLocationType {
|
|
.other(base.rawValue, path)
|
|
}
|
|
}
|
|
|
|
extension XcodeWorkspace.Group {
|
|
fileprivate init(_ xcWorkspaceDataGroup: XCWorkspaceDataGroup) {
|
|
self.init(
|
|
location: .init(xcWorkspaceDataGroup.location),
|
|
name: xcWorkspaceDataGroup.name,
|
|
children: xcWorkspaceDataGroup.children.map { .init(from: $0) }
|
|
)
|
|
}
|
|
|
|
fileprivate var xcWorkspaceDataElement: XCWorkspaceDataGroup {
|
|
.init(
|
|
location: self.location.xcWorkspaceLocation,
|
|
name: name,
|
|
children: children.map(\.xcWorkspaceDataElement)
|
|
)
|
|
}
|
|
}
|