Skip to content

Update documentation and online help around global default toolchains #224

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 1 commit into from
Feb 12, 2025
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 Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ Note that listing available snapshots before the latest release (major and minor

## use

Set the in-use toolchain. If no toolchain is provided, print the currently in-use toolchain, if any.
Set the in-use or default toolchain. If no toolchain is provided, print the currently in-use toolchain, if any.

```
swiftly use [--print-location] [--global-default] [--assume-yes] [--verbose] [<toolchain>] [--version] [--help]
Expand All @@ -158,7 +158,7 @@ swiftly use [--print-location] [--global-default] [--assume-yes] [--verbose] [<t

**--global-default:**

*Use the global default, ignoring any .swift-version files.*
*Set the global default toolchain that is used when there are no .swift-version files.*


**--assume-yes:**
Expand All @@ -176,7 +176,7 @@ swiftly use [--print-location] [--global-default] [--assume-yes] [--verbose] [<t
*The toolchain to use.*


If no toolchain is provided, the currently in-use toolchain will be printed, if any:
If no toolchain is provided, the currently in-use toolchain will be printed, if any. This is based on the current working directory and `.swift-version` files if one is present. If the in-use toolchain is also the global default then it will be shown as the default.

$ swiftly use

Expand Down
42 changes: 38 additions & 4 deletions Documentation/SwiftlyDocs.docc/use-toolchains.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ When you install a toolchain you can start using it right away. If you don't hav
```
$ swiftly install latest
$ swift --version
Swift version 6.0.1 (swift-6.0.1-RELEASE)
Swift version 6.0.3 (swift-6.0.3-RELEASE)
Target: aarch64-unknown-linux-gnu
$ swift build # Build with the current toolchain
```
Expand All @@ -27,11 +27,18 @@ $ swift build # Builds with the latest snapshot toolchain on the main branch
$ lldb # Run the debugger from the latest snapshot toolchain
```

The use command doesn't require a full version. It is sufficient to provide just a major version, or the major and minor versions. Swiftly will use the newest matching version that you have installed, if any.

```
$ swiftly use 5
swift --version # Version matches the 5.10.1 toolchain that was installed above
```

If you're not certain which toolchain is in-use then use the bare `swiftly use` command to provide details:

```
$ swiftly use
Swift 6.0.1 (default)
Swift 5.10.1 (default)
```

You can print the exact toolchain location with the `--print-location` flag:
Expand All @@ -54,7 +61,7 @@ $ cat .swift-version
6.0.1
```

When a team member uses swiftly with this git repository it can use the correct toolchain version automatically:
When a team member uses swiftly with this git repository the toolchain that is in use matches the version in the file.

```
$ cd path/to/git/repository
Expand All @@ -63,7 +70,7 @@ Swift version 6.0.1 (swift-6.0.1-RELEASE)
Target: aarch64-unknown-linux-gnu
```

If that team member doesn't have the toolchain installed on their system there will be a warning. They can install the selected toolchain automatically like this:
If that team member doesn't have the toolchain installed on their system there will be an error. They can install the selected toolchain automatically like this:

```
$ cd path/to/git/repository
Expand All @@ -77,3 +84,30 @@ $ swiftly run swift build +main-snapshot
```

> Note: The toolchain must be installed on your system before you can run with it.

The `.swift version` file, if it is present in your working directory (or parent) will select the toolchain that is in use. If you are working in a directory that doesn't have this file, then you can set a global default toolchain to use in these places.

```
$ swiftly use --global-default 6.0.1
```

Here the `--global-default` flag ensures that the default is set globally to the "6.0.1" toolchain whenever there isn't a swift version file, and there isn't a version specified in the `swiftly run` command. Also, this flag doesn't attempt to create a swift version file, or update it if it already exists.

## In use toolchains and default toolchains

When you list installed toolchains or use the `swiftly use` command to print the current in use toolchain there will be tags for both "in use" and "default." Sometimes the same toolchain will have both tags!

```
$ swiftly list
Installed release toolchains
----------------------------
Swift 6.0.3
Swift 6.0.2 (in use) (default)

Installed snapshot toolchains
-----------------------------
```

Whenever a toolchain is tagged as "in use" indicates the toolchain that will be used when running toolchain commands from your current working directory. The one that is selected is based either on what is in a `.swift-version` file or the global default if there is no such file there.

The default tag is used to show the global default toolchain, which is independent of any swift version file. The global default is there for cases where the file doesn't exist. It sets the toolchain that is in use in those cases.
26 changes: 13 additions & 13 deletions Sources/Swiftly/Use.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import SwiftlyCore

internal struct Use: SwiftlyCommand {
public static var configuration = CommandConfiguration(
abstract: "Set the in-use toolchain. If no toolchain is provided, print the currently in-use toolchain, if any."
abstract: "Set the in-use or default toolchain. If no toolchain is provided, print the currently in-use toolchain, if any."
)

@Flag(name: .shortAndLong, help: "Print the location of the in-use toolchain. This is valid only when there is no toolchain argument.")
var printLocation: Bool = false

@Flag(name: .shortAndLong, help: "Use the global default, ignoring any .swift-version files.")
@Flag(name: .shortAndLong, help: "Set the global default toolchain that is used when there are no .swift-version files.")
var globalDefault: Bool = false

@OptionGroup var root: GlobalOptions
Expand All @@ -19,7 +19,10 @@ internal struct Use: SwiftlyCommand {
"The toolchain to use.",
discussion: """

If no toolchain is provided, the currently in-use toolchain will be printed, if any:
If no toolchain is provided, the currently in-use toolchain will be printed, if any. \
This is based on the current working directory and `.swift-version` files if one is \
present. If the in-use toolchain is also the global default then it will be shown as \
the default.

$ swiftly use

Expand Down Expand Up @@ -107,18 +110,13 @@ internal struct Use: SwiftlyCommand {
internal static func execute(_ toolchain: ToolchainVersion, globalDefault: Bool, assumeYes: Bool = true, _ config: inout Config) async throws {
let (selectedVersion, result) = try await selectToolchain(config: &config, globalDefault: globalDefault)

if case let .swiftVersionFile(versionFile, _, _) = result {
if !assumeYes {
SwiftlyCore.print("The file `\(versionFile)` will be updated to set the new in-use toolchain for this project. Alternatively, you can set your default globally with the `--global-default` flag. Proceed with modifying this file?")

guard SwiftlyCore.promptForConfirmation(defaultBehavior: true) else {
SwiftlyCore.print("Aborting setting in-use toolchain")
return
}
}
var message: String

if case let .swiftVersionFile(versionFile, _, _) = result {
// We don't care in this case if there were any problems with the swift version files, just overwrite it with the new value

Choose a reason for hiding this comment

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

Do we still want to respect assumeYes here and if not, prompt the user?

Copy link
Member Author

@cmcgee1024 cmcgee1024 Feb 11, 2025

Choose a reason for hiding this comment

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

The feedback I've received is that because we're updating an existing file, not creating a new one, and the file is very simple it should be ok to continue without a prompt/assume-yes as long as we provide a clear message of what has happened.

The file `path/to/.swift-version` has been set to `6.0.3` (was 6.0.1)

With this information, one can reverse what has happened.

There is still a prompt and assume-yes in the case where a new file is created because it helps with discovering the feature, and happens less regularly.

try toolchain.name.write(to: versionFile, atomically: true, encoding: .utf8)

message = "The file `\(versionFile)` has been set to `\(toolchain)`"
} else if let newVersionFile = findNewVersionFile(), !globalDefault {
if !assumeYes {
SwiftlyCore.print("A new file `\(newVersionFile)` will be created to set the new in-use toolchain for this project. Alternatively, you can set your default globally with the `--global-default` flag. Proceed with creating this file?")
Expand All @@ -130,12 +128,14 @@ internal struct Use: SwiftlyCommand {
}

try toolchain.name.write(to: newVersionFile, atomically: true, encoding: .utf8)

message = "The file `\(newVersionFile)` has been set to `\(toolchain)`"
} else {
config.inUse = toolchain
try config.save()
message = "The global default toolchain has set to `\(toolchain)`"
}

var message = "Set the in-use toolchain to \(toolchain)"
if let selectedVersion = selectedVersion {
message += " (was \(selectedVersion.name))"
}
Expand Down