Skip to content

Commit 4597a5f

Browse files
committed
Convert build swiftly release from URL to FilePath
Model locally shell command invocations
1 parent 652207c commit 4597a5f

File tree

4 files changed

+130
-80
lines changed

4 files changed

+130
-80
lines changed

Sources/SwiftlyCore/Commands.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ extension SystemCommand {
922922
case arch(String)
923923
case configuration(String)
924924
case packagePath(FilePath)
925-
case pkgConfigPath(String)
925+
case pkgConfigPath(FilePath)
926926
case product(String)
927927
case swiftSdk(String)
928928
case staticSwiftStdlib

Sources/SwiftlyCore/ModeledCommandLine.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ public struct Configuration: Sendable {
1515
public var arguments: Arguments
1616
/// The environment to use when running the executable.
1717
public var environment: Environment
18+
19+
public init(executable: Executable, arguments: Arguments, environment: Environment) {
20+
self.executable = executable
21+
self.arguments = arguments
22+
self.environment = environment
23+
}
1824
}
1925

2026
public struct Executable: Sendable, Hashable {

Sources/TestSwiftly/TestSwiftly.swift

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,60 @@ let currentPlatform: Platform = MacOS.currentPlatform
1717
#error("Unsupported platform")
1818
#endif
1919

20+
typealias sys = SwiftlyCore.SystemCommand
2021
typealias fs = SwiftlyCore.FileSystem
2122

23+
func sh(executable: Executable = ShCommand.defaultExecutable, _ options: ShCommand.Option...) -> ShCommand {
24+
sh(executable: executable, options)
25+
}
26+
27+
func sh(executable: Executable = ShCommand.defaultExecutable, _ options: [ShCommand.Option]) -> ShCommand {
28+
ShCommand(executable: executable, options)
29+
}
30+
31+
struct ShCommand {
32+
static var defaultExecutable: Executable { .name("sh") }
33+
34+
var executable: Executable
35+
36+
var options: [Option]
37+
38+
enum Option {
39+
case login
40+
case command(String)
41+
42+
func args() -> [String] {
43+
switch self {
44+
case .login:
45+
["-l"]
46+
case let .command(command):
47+
["-c", command]
48+
}
49+
}
50+
}
51+
52+
init(executable: Executable, _ options: [Option]) {
53+
self.executable = executable
54+
self.options = options
55+
}
56+
57+
func config() -> Configuration {
58+
var args: [String] = []
59+
60+
for opt in self.options {
61+
args.append(contentsOf: opt.args())
62+
}
63+
64+
return Configuration(
65+
executable: self.executable,
66+
arguments: Arguments(args),
67+
environment: .inherit
68+
)
69+
}
70+
}
71+
72+
extension ShCommand: Runnable {}
73+
2274
@main
2375
struct TestSwiftly: AsyncParsableCommand {
2476
@Flag(name: [.customShort("y"), .long], help: "Disable confirmation prompts by assuming 'yes'")
@@ -40,11 +92,13 @@ struct TestSwiftly: AsyncParsableCommand {
4092
Foundation.exit(2)
4193
}
4294

95+
guard case let swiftlyArchive = FilePath(swiftlyArchive) else { fatalError("") }
96+
4397
print("Extracting swiftly release")
4498
#if os(Linux)
45-
try currentPlatform.runProgram("tar", "-zxvf", swiftlyArchive, quiet: false)
99+
try await sys.tar().extract(.verbose, .compressed, .file(swiftlyArchive)).run(currentPlatform, quiet: false)
46100
#elseif os(macOS)
47-
try currentPlatform.runProgram("installer", "-pkg", swiftlyArchive, "-target", "CurrentUserHomeDirectory", quiet: false)
101+
try await sys.installer(.verbose, pkg: swiftlyArchive, target: "CurrentUserHomeDirectory").run(currentPlatform, quiet: false)
48102
#endif
49103

50104
#if os(Linux)
@@ -54,7 +108,7 @@ struct TestSwiftly: AsyncParsableCommand {
54108
#endif
55109

56110
var env = ProcessInfo.processInfo.environment
57-
let shell = try await currentPlatform.getShell()
111+
let shell = FilePath(try await currentPlatform.getShell())
58112
var customLoc: FilePath?
59113

60114
if self.customLocation {
@@ -66,37 +120,39 @@ struct TestSwiftly: AsyncParsableCommand {
66120
env["SWIFTLY_TOOLCHAINS_DIR"] = (customLoc! / "toolchains").string
67121

68122
try currentPlatform.runProgram(extractedSwiftly.string, "init", "--assume-yes", "--no-modify-profile", "--skip-install", quiet: false, env: env)
69-
try currentPlatform.runProgram(shell, "-l", "-c", ". \"\(customLoc! / "env.sh")\" && swiftly install --assume-yes latest --post-install-file=./post-install.sh", quiet: false, env: env)
123+
try await sh(executable: .path(shell), .login, .command(". \"\(customLoc! / "env.sh")\" && swiftly install --assume-yes latest --post-install-file=./post-install.sh")).run(currentPlatform, env: env, quiet: false)
70124
} else {
71125
print("Installing swiftly to the default location.")
72126
// Setting this environment helps to ensure that the profile gets sourced with bash, even if it is not in an interactive shell
73-
if shell.hasSuffix("bash") {
127+
if shell.ends(with: "bash") {
74128
env["BASH_ENV"] = (fs.home / ".profile").string
75-
} else if shell.hasSuffix("zsh") {
129+
} else if shell.ends(with: "zsh") {
76130
env["ZDOTDIR"] = fs.home.string
77-
} else if shell.hasSuffix("fish") {
131+
} else if shell.ends(with: "fish") {
78132
env["XDG_CONFIG_HOME"] = (fs.home / ".config").string
79133
}
80134

81135
try currentPlatform.runProgram(extractedSwiftly.string, "init", "--assume-yes", "--skip-install", quiet: false, env: env)
82-
try currentPlatform.runProgram(shell, "-l", "-c", "swiftly install --assume-yes latest --post-install-file=./post-install.sh", quiet: false, env: env)
136+
try await sh(executable: .path(shell), .login, .command("swiftly install --assume-yes latest --post-install-file=./post-install.sh")).run(currentPlatform, env: env, quiet: false)
83137
}
84138

85139
var swiftReady = false
86140

87-
if NSUserName() == "root" && FileManager.default.fileExists(atPath: "./post-install.sh") {
88-
try currentPlatform.runProgram(shell, "./post-install.sh", quiet: false)
141+
if NSUserName() == "root" {
142+
if try await fs.exists(atPath: "./post-install.sh") {
143+
try currentPlatform.runProgram(shell.string, "./post-install.sh", quiet: false)
144+
}
89145
swiftReady = true
90-
} else if FileManager.default.fileExists(atPath: "./post-install.sh") {
146+
} else if try await fs.exists(atPath: "./post-install.sh") {
91147
print("WARNING: not running as root, so skipping the post installation steps and final swift verification.")
92148
} else {
93149
swiftReady = true
94150
}
95151

96152
if let customLoc = customLoc, swiftReady {
97-
try currentPlatform.runProgram(shell, "-l", "-c", ". \"\(customLoc / "env.sh")\" && swift --version", quiet: false, env: env)
153+
try await sh(executable: .path(shell), .login, .command(". \"\(customLoc / "env.sh")\" && swift --version")).run(currentPlatform, env: env, quiet: false)
98154
} else if swiftReady {
99-
try currentPlatform.runProgram(shell, "-l", "-c", "swift --version", quiet: false, env: env)
155+
try await sh(executable: .path(shell), .login, .command("swift --version")).run(currentPlatform, env: env, quiet: false)
100156
}
101157
}
102158
}

0 commit comments

Comments
 (0)