Skip to content

Generate command models from argument parser info JSON files #345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft
10 changes: 10 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ let package = Package(
],
path: "Tools/generate-docs-reference"
),
.executableTarget(
name: "generate-command-models",
dependencies: [
.target(name: "SwiftlyCore"),
.target(name: "LinuxPlatform", condition: .when(platforms: [.linux])),
.target(name: "MacOSPlatform", condition: .when(platforms: [.macOS])),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
],
path: "Tools/generate-command-models"
),
.executableTarget(
name: "build-swiftly-release",
dependencies: [
Expand Down
14 changes: 7 additions & 7 deletions Sources/LinuxPlatform/Linux.swift
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,9 @@ public struct Linux: Platform {
if let mockedHomeDir = ctx.mockedHomeDir {
var env = ProcessInfo.processInfo.environment
env["GNUPGHOME"] = (mockedHomeDir / ".gnupg").string
try await sys.gpg()._import(keys: tmpFile).run(self, env: env, quiet: true)
try await sys.gpg()._import(key: tmpFile).run(self, env: env, quiet: true)
} else {
try await sys.gpg()._import(keys: tmpFile).run(self, quiet: true)
try await sys.gpg()._import(key: tmpFile).run(self, quiet: true)
}
}
}
Expand Down Expand Up @@ -418,9 +418,9 @@ public struct Linux: Platform {
if let mockedHomeDir = ctx.mockedHomeDir {
var env = ProcessInfo.processInfo.environment
env["GNUPGHOME"] = (mockedHomeDir / ".gnupg").string
try await sys.gpg().verify(detachedSignature: sigFile, signedData: archive).run(self, env: env, quiet: false)
try await sys.gpg().verify(detached_signature: sigFile, signed_data: archive).run(self, env: env, quiet: false)
} else {
try await sys.gpg().verify(detachedSignature: sigFile, signedData: archive).run(self, quiet: !verbose)
try await sys.gpg().verify(detached_signature: sigFile, signed_data: archive).run(self, quiet: !verbose)
}
} catch {
throw SwiftlyError(message: "Signature verification failed: \(error).")
Expand All @@ -447,9 +447,9 @@ public struct Linux: Platform {
if let mockedHomeDir = ctx.mockedHomeDir {
var env = ProcessInfo.processInfo.environment
env["GNUPGHOME"] = (mockedHomeDir / ".gnupg").string
try await sys.gpg().verify(detachedSignature: sigFile, signedData: archive).run(self, env: env, quiet: false)
try await sys.gpg().verify(detached_signature: sigFile, signed_data: archive).run(self, env: env, quiet: false)
} else {
try await sys.gpg().verify(detachedSignature: sigFile, signedData: archive).run(self, quiet: !verbose)
try await sys.gpg().verify(detached_signature: sigFile, signed_data: archive).run(self, quiet: !verbose)
}
} catch {
throw SwiftlyError(message: "Signature verification failed: \(error).")
Expand Down Expand Up @@ -603,7 +603,7 @@ public struct Linux: Platform {

public func getShell() async throws -> String {
let userName = ProcessInfo.processInfo.userName
if let entry = try await sys.getent(database: "passwd", keys: userName).entries(self).first {
if let entry = try await sys.getent(database: "passwd", key: userName).entries(self).first {
if let shell = entry.last { return shell }
}

Expand Down
18 changes: 9 additions & 9 deletions Sources/MacOSPlatform/MacOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public struct MacOS: Platform {
// If the toolchains go into the default user location then we use the installer to install them
await ctx.print("Installing package in user home directory...")

try await sys.installer(.verbose, pkg: tmpFile, target: "CurrentUserHomeDirectory").run(self, quiet: !verbose)
try await sys.installer(.verbose, .pkg(tmpFile), .target("CurrentUserHomeDirectory")).run(self, quiet: !verbose)
} else {
// Otherwise, we extract the pkg into the requested toolchains directory.
await ctx.print("Expanding pkg...")
Expand All @@ -84,7 +84,7 @@ public struct MacOS: Platform {

await ctx.print("Checking package signature...")
do {
try await sys.pkgutil().checkSignature(pkgPath: tmpFile).run(self, quiet: !verbose)
try await sys.pkgutil().checksignature(pkg_path: tmpFile).run(self, quiet: !verbose)
} catch {
// If this is not a test that uses mocked toolchains then we must throw this error and abort installation
guard ctx.mockedHomeDir != nil else {
Expand All @@ -94,7 +94,7 @@ public struct MacOS: Platform {
// We permit the signature verification to fail during testing
await ctx.print("Signature verification failed, which is allowable during testing with mocked toolchains")
}
try await sys.pkgutil(.verbose).expand(pkgPath: tmpFile, dirPath: tmpDir).run(self, quiet: !verbose)
try await sys.pkgutil(.verbose).expand(pkg_path: tmpFile, dir_path: tmpDir).run(self, quiet: !verbose)

// There's a slight difference in the location of the special Payload file between official swift packages
// and the ones that are mocked here in the test framework.
Expand All @@ -118,18 +118,18 @@ public struct MacOS: Platform {
if ctx.mockedHomeDir == nil {
await ctx.print("Extracting the swiftly package...")
try await sys.installer(
pkg: archive,
target: "CurrentUserHomeDirectory"
.pkg(archive),
.target("CurrentUserHomeDirectory")
)
try? await sys.pkgutil(.volume(userHomeDir)).forget(packageId: "org.swift.swiftly").run(self)
try? await sys.pkgutil(.volume(userHomeDir)).forget(pkg_id: "org.swift.swiftly").run(self)
} else {
let installDir = userHomeDir / ".swiftly"
try await fs.mkdir(.parents, atPath: installDir)

// In the case of a mock for testing purposes we won't use the installer, perferring a manual process because
// the installer will not install to an arbitrary path, only a volume or user home directory.
let tmpDir = fs.mktemp()
try await sys.pkgutil().expand(pkgPath: archive, dirPath: tmpDir).run(self)
try await sys.pkgutil().expand(pkg_path: archive, dir_path: tmpDir).run(self)

// There's a slight difference in the location of the special Payload file between official swift packages
// and the ones that are mocked here in the test framework.
Expand Down Expand Up @@ -162,7 +162,7 @@ public struct MacOS: Platform {

try await fs.remove(atPath: toolchainDir)

try? await sys.pkgutil(.volume(fs.home)).forget(packageId: pkgInfo.CFBundleIdentifier).run(self, quiet: !verbose)
try? await sys.pkgutil(.volume(fs.home)).forget(pkg_id: pkgInfo.CFBundleIdentifier).run(self, quiet: !verbose)
}

public func getExecutableName() -> String {
Expand Down Expand Up @@ -191,7 +191,7 @@ public struct MacOS: Platform {
}

public func getShell() async throws -> String {
for (key, value) in try await sys.dscl(datasource: ".").read(path: fs.home, keys: "UserShell").properties(self) {
for (key, value) in try await sys.dscl(datasource: ".").read(path: fs.home, key: ["UserShell"]).properties(self) {
return value
}

Expand Down
67 changes: 67 additions & 0 deletions Sources/SwiftlyCore/Commands+Runnable+Output.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Foundation
import SystemPackage

extension SystemCommand.dsclCommand.readCommand: Output {
public func properties(_ p: Platform) async throws -> [(key: String, value: String)] {
let output = try await self.output(p)
guard let output else { return [] }

var props: [(key: String, value: String)] = []
for line in output.components(separatedBy: "\n") {
if case let comps = line.components(separatedBy: ": "), comps.count == 2 {
props.append((key: comps[0], value: comps[1]))
}
}
return props
}
}

extension SystemCommand.lipoCommand.createCommand: Runnable {}

extension SystemCommand.pkgbuildCommand: Runnable {}

extension SystemCommand.getentCommand: Output {
public func entries(_ platform: Platform) async throws -> [[String]] {
let output = try await output(platform)
guard let output else { return [] }

var entries: [[String]] = []
for line in output.components(separatedBy: "\n") {
entries.append(line.components(separatedBy: ":"))
}
return entries
}
}

extension SystemCommand.gitCommand.logCommand: Output {}
extension SystemCommand.gitCommand.diffindexCommand: Runnable {}
extension SystemCommand.gitCommand.initCommand: Runnable {}
extension SystemCommand.gitCommand.commitCommand: Runnable {}

extension SystemCommand.tarCommand.createCommand: Runnable {}
extension SystemCommand.tarCommand.extractCommand: Runnable {}

extension SystemCommand.swiftCommand.packageCommand.resetCommand: Runnable {}
extension SystemCommand.swiftCommand.packageCommand.cleanCommand: Runnable {}
extension SystemCommand.swiftCommand.packageCommand.initCommand: Runnable {}
extension SystemCommand.swiftCommand.sdkCommand.installCommand: Runnable {}
extension SystemCommand.swiftCommand.sdkCommand.removeCommand: Runnable {}
extension SystemCommand.swiftCommand.buildCommand: Runnable {}

extension SystemCommand.makeCommand: Runnable {}
extension SystemCommand.makeCommand.installCommand: Runnable {}

extension SystemCommand.stripCommand: Runnable {}

extension SystemCommand.sha256sumCommand: Output {}

extension SystemCommand.productbuildCommand: Runnable {}

extension SystemCommand.gpgCommand.importCommand: Runnable {}
extension SystemCommand.gpgCommand.verifyCommand: Runnable {}

extension SystemCommand.pkgutilCommand.checksignatureCommand: Runnable {}
extension SystemCommand.pkgutilCommand.expandCommand: Runnable {}
extension SystemCommand.pkgutilCommand.forgetCommand: Runnable {}

extension SystemCommand.installerCommand: Runnable {}
Loading