From fd8367df2a75668032e788d0ed262c02daa1082b Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 15 May 2024 10:37:44 +0100 Subject: [PATCH] Update the tools to use swift-command-line-tools. --- Package.resolved | 8 ++++++ Package.swift | 5 +++- Tools/Sources/BuildSDK.swift | 17 ++++++------ Tools/Sources/DownloadStrings.swift | 5 ++-- Tools/Sources/GenerateSAS.swift | 3 +-- Tools/Sources/GenerateSDKMocks.swift | 5 ++-- Tools/Sources/Locheck.swift | 7 ++--- Tools/Sources/OutdatedPackages.swift | 7 ++--- Tools/Sources/SetupProject.swift | 9 ++++--- Tools/Sources/URL.swift | 8 ++++++ Tools/Sources/Utilities.swift | 39 ---------------------------- 11 files changed, 49 insertions(+), 64 deletions(-) create mode 100644 Tools/Sources/URL.swift delete mode 100644 Tools/Sources/Utilities.swift diff --git a/Package.resolved b/Package.resolved index 627f170ab..6eadbc25a 100644 --- a/Package.resolved +++ b/Package.resolved @@ -9,6 +9,14 @@ "version" : "1.2.2" } }, + { + "identity" : "swift-command-line-tools", + "kind" : "remoteSourceControl", + "location" : "https://github.com/element-hq/swift-command-line-tools.git", + "state" : { + "revision" : "a6ad90808f4f6cac615ab8496c6ff1bc5f9fa192" + } + }, { "identity" : "yams", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index c1167fbc8..5752c0ade 100644 --- a/Package.swift +++ b/Package.swift @@ -6,19 +6,22 @@ import PackageDescription let package = Package( name: "Element Swift", platforms: [ - .macOS(.v12) + .macOS(.v13) ], products: [ .executable(name: "tools", targets: ["Tools"]) ], dependencies: [ .package(url: "https://github.com/apple/swift-argument-parser", .upToNextMinor(from: "1.2.0")), + .package(url: "https://github.com/element-hq/swift-command-line-tools.git", revision: "a6ad90808f4f6cac615ab8496c6ff1bc5f9fa192"), + // .package(path: "../../../swift-command-line-tools"), .package(url: "https://github.com/jpsim/Yams", .upToNextMinor(from: "5.0.0")) ], targets: [ .executableTarget(name: "Tools", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "CommandLineTools", package: "swift-command-line-tools"), .product(name: "Yams", package: "Yams") ], path: "Tools/Sources") diff --git a/Tools/Sources/BuildSDK.swift b/Tools/Sources/BuildSDK.swift index a48baf7a5..1fc35a67d 100644 --- a/Tools/Sources/BuildSDK.swift +++ b/Tools/Sources/BuildSDK.swift @@ -1,4 +1,5 @@ import ArgumentParser +import CommandLineTools import Foundation import Yams @@ -67,7 +68,7 @@ struct BuildSDK: ParsableCommand { /// but only when the ``target`` option hasn't been supplied. func checkRustupTargets() throws { guard target.isEmpty, device == 0, simulator == 0 else { return } - guard let output = try Utilities.zsh("rustup show") else { throw Error.rustupOutputFailure } + guard let output = try Zsh.run(command: "rustup show") else { throw Error.rustupOutputFailure } var requiredTargets = Target.allCases.reduce(into: [String: Bool]()) { partialResult, target in partialResult[target.rawValue] = false @@ -85,14 +86,14 @@ struct BuildSDK: ParsableCommand { /// Clones the Rust SDK if a copy isn't found in the parent directory. func cloneSDKIfNeeded() throws { - guard !FileManager.default.fileExists(atPath: Utilities.sdkDirectoryURL.path) else { return } - try Utilities.zsh("git clone https://github.com/matrix-org/matrix-rust-sdk", workingDirectoryURL: Utilities.parentDirectoryURL) + guard !FileManager.default.fileExists(atPath: URL.sdkDirectory.path) else { return } + try Zsh.run(command: "git clone https://github.com/matrix-org/matrix-rust-sdk", directory: .parentDirectory) } /// Checkout the specified branch of the SDK if supplied. func checkoutBranchIfSupplied() throws { guard let branch else { return } - try Utilities.zsh("git checkout \(branch)", workingDirectoryURL: Utilities.sdkDirectoryURL) + try Zsh.run(command: "git checkout \(branch)", directory: .sdkDirectory) } /// Build the Rust SDK as an XCFramework with the debug profile. @@ -103,7 +104,7 @@ struct BuildSDK: ParsableCommand { if device > 0 { buildCommand.append(" --target \(Target.iOS.rawValue)") } else if simulator > 0 { - let hostArchitecture = try Utilities.zsh("arch") + let hostArchitecture = try Zsh.run(command: "arch") if hostArchitecture?.trimmingCharacters(in: .whitespacesAndNewlines) == "arm64" { buildCommand.append(" --target \(Target.simulatorARM64.rawValue)") } else { @@ -112,18 +113,18 @@ struct BuildSDK: ParsableCommand { } else if !target.isEmpty { target.forEach { buildCommand.append(" --target \($0.rawValue)") } } - try Utilities.zsh(buildCommand, workingDirectoryURL: Utilities.sdkDirectoryURL) + try Zsh.run(command: buildCommand, directory: .sdkDirectory) } /// Update the Xcode project to use the build of the SDK. func updateXcodeProject() throws { try updateProjectYAML() - try Utilities.zsh("xcodegen") + try Zsh.run(command: "xcodegen") } /// Update project.yml with the local path of the SDK. func updateProjectYAML() throws { - let yamlURL = Utilities.projectDirectoryURL.appendingPathComponent("project.yml") + let yamlURL = URL.projectDirectory.appendingPathComponent("project.yml") let yamlString = try String(contentsOf: yamlURL) guard var projectConfig = try Yams.compose(yaml: yamlString) else { throw Error.failureParsingProjectYAML } diff --git a/Tools/Sources/DownloadStrings.swift b/Tools/Sources/DownloadStrings.swift index b1f457624..c3862a817 100644 --- a/Tools/Sources/DownloadStrings.swift +++ b/Tools/Sources/DownloadStrings.swift @@ -1,4 +1,5 @@ import ArgumentParser +import CommandLineTools import Foundation struct DownloadStrings: ParsableCommand { @@ -14,10 +15,10 @@ struct DownloadStrings: ParsableCommand { private func localazyDownload() throws { let arguments = allLanguages ? " all" : "" - try Utilities.zsh("localazy download\(arguments)") + try Zsh.run(command: "localazy download\(arguments)") } private func swiftgen() throws { - try Utilities.zsh("swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml") + try Zsh.run(command: "swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml") } } diff --git a/Tools/Sources/GenerateSAS.swift b/Tools/Sources/GenerateSAS.swift index 7d6aab276..9a91c9f26 100644 --- a/Tools/Sources/GenerateSAS.swift +++ b/Tools/Sources/GenerateSAS.swift @@ -65,8 +65,7 @@ struct GenerateSAS: ParsableCommand { } private func writeToFile(file: String, dict: [String: String], subdirectory: String) { - let projectDirectory = Utilities.projectDirectoryURL - let fileDirectory = projectDirectory.appendingPathComponent("ElementX/Resources/Localizations").appendingPathComponent(subdirectory) + let fileDirectory = URL.projectDirectory.appendingPathComponent("ElementX/Resources/Localizations").appendingPathComponent(subdirectory) let filePath = fileDirectory.appendingPathComponent(file) diff --git a/Tools/Sources/GenerateSDKMocks.swift b/Tools/Sources/GenerateSDKMocks.swift index 69ce88e74..064eae6cc 100644 --- a/Tools/Sources/GenerateSDKMocks.swift +++ b/Tools/Sources/GenerateSDKMocks.swift @@ -1,4 +1,5 @@ import ArgumentParser +import CommandLineTools import Foundation struct GenerateSDKMocks: ParsableCommand { @@ -15,7 +16,7 @@ struct GenerateSDKMocks: ParsableCommand { func run() throws { if version == "local" { - try generateSDKMocks(ffiPath: "\(Utilities.sdkDirectoryURL.path)/bindings/apple/generated/swift") + try generateSDKMocks(ffiPath: "\(URL.sdkDirectory.path)/bindings/apple/generated/swift") } else { try downloadSDK(version: version) { path in try generateSDKMocks(ffiPath: path) @@ -26,7 +27,7 @@ struct GenerateSDKMocks: ParsableCommand { /// Generates the SDK mocks using Sourcery. func generateSDKMocks(ffiPath: String) throws { - try Utilities.zsh("sourcery --sources \(ffiPath) --sources ElementX/Sources/Mocks/SDK --templates Tools/Sourcery --output ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift --args autoMockableImports=\"Foundation\",autoMockableImports=\"MatrixRustSDK\"") + try Zsh.run(command: "sourcery --sources \(ffiPath) --sources ElementX/Sources/Mocks/SDK --templates Tools/Sourcery --output ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift --args autoMockableImports=\"Foundation\",autoMockableImports=\"MatrixRustSDK\"") } /// Downloads the specified version of the `matrix_sdk_ffi.swift` file and returns the path to the downloaded file. diff --git a/Tools/Sources/Locheck.swift b/Tools/Sources/Locheck.swift index 82c887189..cf5d36022 100644 --- a/Tools/Sources/Locheck.swift +++ b/Tools/Sources/Locheck.swift @@ -1,4 +1,5 @@ import ArgumentParser +import CommandLineTools import Foundation struct Locheck: ParsableCommand { @@ -19,7 +20,7 @@ struct Locheck: ParsableCommand { static var configuration = CommandConfiguration(abstract: "A tool that verifies bad strings contained in localization files") private var stringsDirectoryURL: URL { - Utilities.projectDirectoryURL.appendingPathComponent("ElementX/Resources/Localizations") + .projectDirectory.appendingPathComponent("ElementX/Resources/Localizations") } func run() throws { @@ -28,14 +29,14 @@ struct Locheck: ParsableCommand { } func checkStrings() throws { - guard let output = try Utilities.zsh("mint run locheck discoverlproj --ignore-missing --ignore lproj_file_missing_from_translation --treat-warnings-as-errors \(stringsDirectoryURL.path)") else { + guard let output = try Zsh.run(command: "mint run locheck discoverlproj --ignore-missing --ignore lproj_file_missing_from_translation --treat-warnings-as-errors \(stringsDirectoryURL.path)") else { throw LocheckError.missingMint } print(output) } private func checkMint() throws { - let result = try Utilities.zsh("which mint") + let result = try Zsh.run(command: "which mint") if result?.contains("not found") == true { throw LocheckError.missingMint diff --git a/Tools/Sources/OutdatedPackages.swift b/Tools/Sources/OutdatedPackages.swift index 0e9d647cc..941eeece8 100644 --- a/Tools/Sources/OutdatedPackages.swift +++ b/Tools/Sources/OutdatedPackages.swift @@ -1,10 +1,11 @@ import ArgumentParser +import CommandLineTools import Foundation struct OutdatedPackages: ParsableCommand { static var configuration = CommandConfiguration(abstract: "A tool to check outdated package dependencies. Please make sure you have already run setup-project before using this tool.") - private var projectSwiftPMDirectoryURL: URL { Utilities.projectDirectoryURL.appendingPathComponent("ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm") } + private var projectSwiftPMDirectoryURL: URL { .projectDirectory.appendingPathComponent("ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm") } func run() throws { try checkToolsDependencies() @@ -12,12 +13,12 @@ struct OutdatedPackages: ParsableCommand { } func checkToolsDependencies() throws { - guard let output = try Utilities.zsh("swift outdated"), !output.isEmpty else { return } + guard let output = try Zsh.run(command: "swift outdated"), !output.isEmpty else { return } print("outdated tools Swift packages:\n\(output)") } func checkProjectDependencies() throws { - guard let output = try Utilities.zsh("swift outdated", workingDirectoryURL: projectSwiftPMDirectoryURL), !output.isEmpty else { return } + guard let output = try Zsh.run(command: "swift outdated", directory: projectSwiftPMDirectoryURL), !output.isEmpty else { return } print("outdated project Swift packages:\n\(output)") } } diff --git a/Tools/Sources/SetupProject.swift b/Tools/Sources/SetupProject.swift index bb977c9ac..28363b63f 100644 --- a/Tools/Sources/SetupProject.swift +++ b/Tools/Sources/SetupProject.swift @@ -1,4 +1,5 @@ import ArgumentParser +import CommandLineTools import Foundation struct SetupProject: ParsableCommand { @@ -12,18 +13,18 @@ struct SetupProject: ParsableCommand { } func setupGitHooks() throws { - try Utilities.zsh("git config core.hooksPath .githooks") + try Zsh.run(command: "git config core.hooksPath .githooks") } func brewBundleInstall() throws { - try Utilities.zsh("brew install xcodegen swiftgen swiftformat git-lfs sourcery mint kiliankoe/formulae/swift-outdated localazy/tools/localazy peripheryapp/periphery/periphery") + try Zsh.run(command: "brew install xcodegen swiftgen swiftformat git-lfs sourcery mint kiliankoe/formulae/swift-outdated localazy/tools/localazy peripheryapp/periphery/periphery") } func mintPackagesInstall() throws { - try Utilities.zsh("mint install Asana/locheck") + try Zsh.run(command: "mint install Asana/locheck") } func xcodegen() throws { - try Utilities.zsh("xcodegen") + try Zsh.run(command: "xcodegen") } } diff --git a/Tools/Sources/URL.swift b/Tools/Sources/URL.swift new file mode 100644 index 000000000..f2c5bec4c --- /dev/null +++ b/Tools/Sources/URL.swift @@ -0,0 +1,8 @@ +import ArgumentParser +import Foundation + +extension URL { + static var projectDirectory: URL { URL(fileURLWithPath: FileManager.default.currentDirectoryPath) } + static var parentDirectory: URL { .projectDirectory.deletingLastPathComponent() } + static var sdkDirectory: URL { .parentDirectory.appendingPathComponent("matrix-rust-sdk") } +} diff --git a/Tools/Sources/Utilities.swift b/Tools/Sources/Utilities.swift deleted file mode 100644 index d0d9669db..000000000 --- a/Tools/Sources/Utilities.swift +++ /dev/null @@ -1,39 +0,0 @@ -import ArgumentParser -import Foundation - -enum Utilities { - enum Error: LocalizedError { - case scriptFailed(command: String, path: String) - - var errorDescription: String? { - switch self { - case let .scriptFailed(command, path): - return "command \(command) failed in path: \(path)" - } - } - } - - static var projectDirectoryURL: URL { URL(fileURLWithPath: FileManager.default.currentDirectoryPath) } - static var parentDirectoryURL: URL { Utilities.projectDirectoryURL.deletingLastPathComponent() } - static var sdkDirectoryURL: URL { parentDirectoryURL.appendingPathComponent("matrix-rust-sdk") } - - /// Runs a command in zsh. - @discardableResult - static func zsh(_ command: String, workingDirectoryURL: URL = projectDirectoryURL) throws -> String? { - let process = Process() - process.executableURL = URL(fileURLWithPath: "/bin/zsh") - process.arguments = ["-cu", command] - process.currentDirectoryURL = workingDirectoryURL - - let outputPipe = Pipe() - process.standardOutput = outputPipe - - try process.run() - process.waitUntilExit() - - guard process.terminationReason == .exit, process.terminationStatus == 0 else { throw Error.scriptFailed(command: command, path: workingDirectoryURL.absoluteString) } - - guard let outputData = try outputPipe.fileHandleForReading.readToEnd() else { return nil } - return String(data: outputData, encoding: .utf8) - } -}