Skip to content

Change the default install path for macOS pkgs #259

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Sources/LinuxPlatform/Linux.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public struct Linux: Platform {

public init() {}

public var appDataDirectory: URL {
public var defaultSwiftlyHomeDirectory: URL {
if let dir = ProcessInfo.processInfo.environment["XDG_DATA_HOME"] {
return URL(fileURLWithPath: dir)
return URL(fileURLWithPath: dir).appendingPathComponent("swiftly", isDirectory: true)
} else {
return FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent(".local/share", isDirectory: true)
.appendingPathComponent(".local/share/swiftly", isDirectory: true)
}
}

Expand Down
13 changes: 7 additions & 6 deletions Sources/MacOSPlatform/MacOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ public struct SwiftPkgInfo: Codable {
public struct MacOS: Platform {
public init() {}

public var appDataDirectory: URL {
public var defaultSwiftlyHomeDirectory: URL {
FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/Application Support", isDirectory: true)
.appendingPathComponent(".swiftly", isDirectory: true)
}

public var swiftlyBinDir: URL {
SwiftlyCore.mockedHomeDir.map { $0.appendingPathComponent("bin", isDirectory: true) }
?? ProcessInfo.processInfo.environment["SWIFTLY_BIN_DIR"].map { URL(fileURLWithPath: $0) }
?? FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/Application Support/swiftly/bin", isDirectory: true)
.appendingPathComponent(".swiftly/bin", isDirectory: true)
}

public var swiftlyToolchainsDir: URL {
Expand Down Expand Up @@ -99,7 +99,7 @@ public struct MacOS: Platform {
} else {
homeDir = SwiftlyCore.mockedHomeDir ?? FileManager.default.homeDirectoryForCurrentUser

let installDir = homeDir.appendingPathComponent("usr/local")
let installDir = homeDir.appendingPathComponent(".swiftly")
try FileManager.default.createDirectory(atPath: installDir.path, withIntermediateDirectories: true)

// In the case of a mock for testing purposes we won't use the installer, perferring a manual process because
Expand All @@ -114,10 +114,11 @@ public struct MacOS: Platform {
throw SwiftlyError(message: "Payload file could not be found at \(tmpDir).")
}

try runProgram("tar", "-C", installDir.path, "-xf", payload.path)
SwiftlyCore.print("Extracting the swiftly package into \(installDir.path)...")
try runProgram("tar", "-C", installDir.path, "-xvf", payload.path, quiet: false)
}

try self.runProgram(homeDir.appendingPathComponent("usr/local/bin/swiftly").path, "init")
try self.runProgram(homeDir.appendingPathComponent(".swiftly/bin/swiftly").path, "init")
}

public func uninstall(_ toolchain: ToolchainVersion, verbose: Bool) throws {
Expand Down
30 changes: 8 additions & 22 deletions Sources/Swiftly/Init.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ internal struct Init: SwiftlyCommand {
\(Swiftly.currentPlatform.swiftlyHomeDir.path) - Data and configuration files directory including toolchains
\(Swiftly.currentPlatform.swiftlyBinDir.path) - Executables installation directory

These locations can be changed with SWIFTLY_HOME and SWIFTLY_BIN environment variables and run this again.
These locations can be changed with SWIFTLY_HOME_DIR and SWIFTLY_BIN_DIR environment variables and run this again.
\(installMsg)
""")

Expand All @@ -89,22 +89,6 @@ internal struct Init: SwiftlyCommand {
}
}

// Ensure swiftly doesn't overwrite any existing executables without getting confirmation first.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check had existed to check only if swiftly was already at the destination, prompting before overwriting it. The init subcommand is there to install swiftly, so it's not technically a problem if it's overwriting the binary in the destination. There is a separate check to see if it will be overwriting a user's configuration, and/or toolchains.

let swiftlyBinDir = Swiftly.currentPlatform.swiftlyBinDir
let swiftlyBinDirContents = (try? FileManager.default.contentsOfDirectory(atPath: swiftlyBinDir.path)) ?? [String]()
let willBeOverwritten = Set(["swiftly"]).intersection(swiftlyBinDirContents)
if !willBeOverwritten.isEmpty && !overwrite {
SwiftlyCore.print("The following existing executables will be overwritten:")

for executable in willBeOverwritten {
SwiftlyCore.print(" \(swiftlyBinDir.appendingPathComponent(executable).path)")
}

guard SwiftlyCore.promptForConfirmation(defaultBehavior: false) else {
throw SwiftlyError(message: "Swiftly installation has been cancelled")
}
}

let shell = if let s = ProcessInfo.processInfo.environment["SHELL"] {
s
} else {
Expand Down Expand Up @@ -239,14 +223,16 @@ internal struct Init: SwiftlyCommand {
(postInstall, pathChanged) = try await Install.execute(version: latestVersion, &config, useInstalledToolchain: true, verifySignature: true, verbose: verbose, assumeYes: assumeYes)
}

if addEnvToProfile && !quietShellFollowup {
if addEnvToProfile {
try Data(sourceLine.utf8).append(to: profileHome)

SwiftlyCore.print("""
To begin using installed swiftly from your current shell, first run the following command:
\(sourceLine)
if !quietShellFollowup {
SwiftlyCore.print("""
To begin using installed swiftly from your current shell, first run the following command:
\(sourceLine)

""")
""")
}
}

// Fish doesn't have path caching, so this might only be needed for bash/zsh
Expand Down
8 changes: 4 additions & 4 deletions Sources/SwiftlyCore/Platform.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ public struct RunProgramError: Swift.Error {
}

public protocol Platform {
/// The platform-specific location on disk where applications are
/// supposed to store their custom data.
var appDataDirectory: URL { get }
/// The platform-specific defaut location on disk for swiftly's home
/// directory.
var defaultSwiftlyHomeDirectory: URL { get }

/// The directory which stores the swiftly executable itself as well as symlinks
/// to executables in the "bin" directory of the active toolchain.
Expand Down Expand Up @@ -130,7 +130,7 @@ extension Platform {
public var swiftlyHomeDir: URL {
SwiftlyCore.mockedHomeDir
?? ProcessInfo.processInfo.environment["SWIFTLY_HOME_DIR"].map { URL(fileURLWithPath: $0) }
?? self.appDataDirectory.appendingPathComponent("swiftly", isDirectory: true)
?? self.defaultSwiftlyHomeDirectory
}

/// The URL of the configuration file in swiftly's home directory.
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftlyTests/SwiftlyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ public class MockToolchainDownloader: HTTPRequestExecutor {
#elseif os(macOS)
public func makeMockedSwiftly(from _: URL) throws -> Data {
let tmp = FileManager.default.temporaryDirectory.appendingPathComponent("swiftly-\(UUID())")
let swiftlyDir = tmp.appendingPathComponent("swiftly", isDirectory: true)
let swiftlyDir = tmp.appendingPathComponent(".swiftly", isDirectory: true)
let swiftlyBinDir = swiftlyDir.appendingPathComponent("bin")

try FileManager.default.createDirectory(
Expand Down Expand Up @@ -766,7 +766,7 @@ public class MockToolchainDownloader: HTTPRequestExecutor {
"--root",
swiftlyDir.path,
"--install-location",
"usr/local",
".swiftly",
"--version",
"\(self.latestSwiftlyVersion)",
"--identifier",
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftlyTests/UninstallTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,10 @@ final class UninstallTests: SwiftlyTests {
func testUninstallNotInstalled() async throws {
let toolchains = Set([Self.oldStable, Self.newStable, Self.newMainSnapshot, Self.oldReleaseSnapshot])
try await self.withMockedHome(homeName: Self.homeName, toolchains: toolchains, inUse: Self.newMainSnapshot) {
var config = try await Config.load()
var config = try Config.load()
config.inUse = Self.newMainSnapshot
config.installedToolchains.remove(Self.newMainSnapshot)
try await config.save()
try config.save()

var uninstall = try self.parseCommand(Uninstall.self, ["uninstall", "-y", Self.newMainSnapshot.name])
_ = try await uninstall.run()
Expand Down
12 changes: 6 additions & 6 deletions Tools/build-swiftly-release/BuildSwiftlyRelease.swift
Original file line number Diff line number Diff line change
Expand Up @@ -399,12 +399,12 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
try runProgram(strip, ".build/\(arch)-apple-macosx/release/swiftly")
}

let swiftlyBinDir = FileManager.default.currentDirectoryPath + "/.build/release/usr/local/bin"
let swiftlyBinDir = FileManager.default.currentDirectoryPath + "/.build/release/.swiftly/bin"
try? FileManager.default.createDirectory(atPath: swiftlyBinDir, withIntermediateDirectories: true)

try runProgram(lipo, ".build/x86_64-apple-macosx/release/swiftly", ".build/arm64-apple-macosx/release/swiftly", "-create", "-o", "\(swiftlyBinDir)/swiftly")

let swiftlyLicenseDir = FileManager.default.currentDirectoryPath + "/.build/release/usr/local/share/doc/swiftly/license"
let swiftlyLicenseDir = FileManager.default.currentDirectoryPath + "/.build/release/.swiftly/license"
try? FileManager.default.createDirectory(atPath: swiftlyLicenseDir, withIntermediateDirectories: true)
try await self.collectLicenses(swiftlyLicenseDir)

Expand All @@ -418,7 +418,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
"--root",
swiftlyBinDir + "/..",
"--install-location",
"usr/local",
".swiftly",
"--version",
self.version,
"--identifier",
Expand All @@ -433,7 +433,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
"--root",
swiftlyBinDir + "/..",
"--install-location",
"usr/local",
".swiftly",
"--version",
self.version,
"--identifier",
Expand All @@ -455,9 +455,9 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
try distFileContents.write(to: distFile, atomically: true, encoding: .utf8)

if let cert = cert {
try runProgram("productbuild", "--distribution", distFile.path, "--package-path", pkgFile.path, "--sign", cert, pkgFileReconfigured.path)
try runProgram("productbuild", "--distribution", distFile.path, "--package-path", pkgFile.deletingLastPathComponent().path, "--sign", cert, pkgFileReconfigured.path)
} else {
try runProgram("productbuild", "--distribution", distFile.path, "--package-path", pkgFile.path, pkgFileReconfigured.path)
try runProgram("productbuild", "--distribution", distFile.path, "--package-path", pkgFile.deletingLastPathComponent().path, pkgFileReconfigured.path)
}
try FileManager.default.removeItem(at: pkgFile)
try FileManager.default.copyItem(atPath: pkgFileReconfigured.path, toPath: pkgFile.path)
Expand Down