Skip to content

Commit d732a84

Browse files
committed
Fixes for the system managed detection and installation logic
1 parent 35a05d0 commit d732a84

File tree

3 files changed

+53
-45
lines changed

3 files changed

+53
-45
lines changed

Sources/Swiftly/Init.swift

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -138,26 +138,8 @@ internal struct Init: SwiftlyCommand {
138138

139139
guard var config else { throw Error(message: "Configuration could not be set") }
140140

141-
let swiftlyBin = Swiftly.currentPlatform.swiftlyBinDir.appendingPathComponent("swiftly", isDirectory: false)
142-
143-
let cmd = URL(fileURLWithPath: CommandLine.arguments[0])
144-
let systemManagedSwiftlyBin = try Swiftly.currentPlatform.systemManagedBinary(CommandLine.arguments[0])
145-
146-
// Don't move the binary if it's already in the right place, this is being invoked inside an xctest, or it is a system managed binary
147-
if cmd != swiftlyBin && !cmd.path.hasSuffix("xctest") && systemManagedSwiftlyBin == nil {
148-
SwiftlyCore.print("Moving swiftly into the installation directory...")
149-
150-
if swiftlyBin.fileExists() {
151-
try FileManager.default.removeItem(at: swiftlyBin)
152-
}
153-
154-
do {
155-
try FileManager.default.moveItem(at: cmd, to: swiftlyBin)
156-
} catch {
157-
try FileManager.default.copyItem(at: cmd, to: swiftlyBin)
158-
SwiftlyCore.print("Swiftly has been copied into the installation directory. You can remove '\(cmd.path)'. It is no longer needed.")
159-
}
160-
}
141+
// Move our executable over to the correct place
142+
let _ = try Swiftly.currentPlatform.findSwiftlyBin(installSwiftly: true)
161143

162144
if overwrite || !FileManager.default.fileExists(atPath: envFile.path) {
163145
SwiftlyCore.print("Creating shell environment file for the user...")

Sources/Swiftly/Install.swift

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,22 +243,14 @@ struct Install: SwiftlyCommand {
243243

244244
var pathChanged = false
245245

246-
// Don't create the proxies in the tests
247-
if CommandLine.arguments.count > 0 && !CommandLine.arguments[0].hasSuffix("xctest") {
246+
// Create proxies if we have a location where we can point them
247+
if let proxyTo = try? Swiftly.currentPlatform.findSwiftlyBin(installSwiftly: false) {
248248
// Ensure swiftly doesn't overwrite any existing executables without getting confirmation first.
249-
let swiftlyBin = Swiftly.currentPlatform.swiftlyBinDir.appendingPathComponent("swiftly", isDirectory: false)
250-
let systemManagedSwiftlyBin = try Swiftly.currentPlatform.systemManagedBinary(CommandLine.arguments[0])
251249
let swiftlyBinDir = Swiftly.currentPlatform.swiftlyBinDir
252250
let swiftlyBinDirContents = (try? FileManager.default.contentsOfDirectory(atPath: swiftlyBinDir.path)) ?? [String]()
253251
let toolchainBinDir = Swiftly.currentPlatform.findToolchainBinDir(version)
254252
let toolchainBinDirContents = try FileManager.default.contentsOfDirectory(atPath: toolchainBinDir.path)
255253

256-
let proxyTo = if let systemManagedSwiftlyBin = systemManagedSwiftlyBin {
257-
systemManagedSwiftlyBin
258-
} else {
259-
swiftlyBin.path
260-
}
261-
262254
let existingProxies = swiftlyBinDirContents.filter { bin in
263255
do {
264256
let linkTarget = try FileManager.default.destinationOfSymbolicLink(atPath: swiftlyBinDir.appendingPathComponent(bin).path)

Sources/SwiftlyCore/Platform.swift

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -267,27 +267,61 @@ extension Platform {
267267
}
268268
}
269269

270-
public func systemManagedBinary(_ cmd: String) throws -> String? {
271-
let userHome = FileManager.default.homeDirectoryForCurrentUser
272-
let binLocs = [cmd] + ProcessInfo.processInfo.environment["PATH"]!.components(separatedBy: ":").map { $0 + "/" + cmd }
273-
var bin: String?
274-
for binLoc in binLocs {
275-
if FileManager.default.fileExists(atPath: binLoc) {
276-
bin = binLoc
277-
break
278-
}
270+
// Find the resting place for the swiftly binary, installing ourselves there if possible.
271+
public func findSwiftlyBin(installSwiftly: Bool) throws -> String? {
272+
let swiftlyHomeBin = self.swiftlyBinDir.appendingPathComponent("swiftly", isDirectory: false).path
273+
274+
// First, let's find out where we are.
275+
let cmd = CommandLine.arguments[0]
276+
let cmdAbsolute = if cmd.hasPrefix("/") {
277+
cmd
278+
} else {
279+
([FileManager.default.currentDirectoryPath] + (ProcessInfo.processInfo.environment["PATH"]?.components(separatedBy: ":") ?? [])).map {
280+
$0 + "/" + cmd
281+
}.filter {
282+
FileManager.default.fileExists(atPath: $0)
283+
}.first
284+
}
285+
286+
// We couldn't find outselves in the usual places, so if we're not going to be installing
287+
// swiftly then we can assume that we are running from the final location.
288+
if cmdAbsolute == nil && !installSwiftly && FileManager.default.fileExists(atPath: swiftlyHomeBin) {
289+
return swiftlyHomeBin
279290
}
280-
guard let bin = bin else {
281-
throw Error(message: "Could not locate source of \(cmd) binary in either the PATH, relative, or absolute path")
291+
292+
// If we are system managed then we know where swiftly should be, no installation necessary.
293+
let userHome = FileManager.default.homeDirectoryForCurrentUser
294+
if let cmdAbsolute, !cmdAbsolute.hasPrefix(userHome.path + "/") && (cmdAbsolute.hasPrefix("/usr/") || cmdAbsolute.hasPrefix("/opt/") || cmdAbsolute.hasPrefix("/bin/")) {
295+
return cmdAbsolute
282296
}
283297

284-
// If the binary is in the user's home directory, or is not in system locations ("/usr", "/opt", "/bin")
285-
// then it is expected to be outside of a system package location and we manage the binary ourselves.
286-
if bin.hasPrefix(userHome.path + "/") || (!bin.hasPrefix("/usr") && !bin.hasPrefix("/opt") && !bin.hasPrefix("/bin")) {
298+
// If we're running inside an xctest or we couldn't determine our absolute path then
299+
// we don't install nor do we have a swiftly location for the proxies.
300+
guard let cmdAbsolute, !cmdAbsolute.hasSuffix("xctest") else {
287301
return nil
288302
}
289303

290-
return bin
304+
// We're installed and running in our bin directory, return our location
305+
if cmdAbsolute == swiftlyHomeBin {
306+
return swiftlyHomeBin
307+
}
308+
309+
if installSwiftly {
310+
SwiftlyCore.print("Installing swiftly in \(swiftlyHomeBin)...")
311+
312+
if FileManager.default.fileExists(atPath: swiftlyHomeBin) {
313+
try FileManager.default.removeItem(atPath: swiftlyHomeBin)
314+
}
315+
316+
do {
317+
try FileManager.default.moveItem(atPath: cmdAbsolute, toPath: swiftlyHomeBin)
318+
} catch {
319+
try FileManager.default.copyItem(atPath: cmdAbsolute, toPath: swiftlyHomeBin)
320+
SwiftlyCore.print("Swiftly has been copied into the installation directory. You can remove '\(cmd)'. It is no longer needed.")
321+
}
322+
}
323+
324+
return FileManager.default.fileExists(atPath: swiftlyHomeBin) ? swiftlyHomeBin : nil
291325
}
292326

293327
public func findToolchainBinDir(_ toolchain: ToolchainVersion) -> URL {

0 commit comments

Comments
 (0)