Skip to content

Dotnetup: Support installing multiple runtimes at once#53469

Draft
dsplaisted wants to merge 20 commits intodotnet:release/dnupfrom
dsplaisted:dotnetup-multi-runtime
Draft

Dotnetup: Support installing multiple runtimes at once#53469
dsplaisted wants to merge 20 commits intodotnet:release/dnupfrom
dsplaisted:dotnetup-multi-runtime

Conversation

@dsplaisted
Copy link
Member

This includes the changes from #53447, and adds support for specifying multiple runtimes to install. The archives will be downloaded concurrently.

image image

dsplaisted and others added 20 commits March 13, 2026 15:13
Extend IEnvShellProvider with GetProfilePaths(), GenerateProfileEntry(),
and GenerateActivationCommand() methods. Implement in all three providers:
- Bash: ~/.bashrc + login profile (~/.bash_profile or ~/.profile)
- Zsh: ~/.zshrc
- PowerShell: ~/.config/powershell/Microsoft.PowerShell_profile.ps1

Add ShellProfileManager for coordinating file I/O (add/remove entries,
backup, idempotency) and ShellDetection for resolving the current shell.

Hook profile modification into DotnetInstallManager.ConfigureInstallType()
on non-Windows so that 'sdk install --interactive' persists to profiles.

Implement DefaultInstallCommand.SetUserInstallRoot() for non-Windows,
replacing the 'not yet supported' error.

Print activation command after install so users can immediately use .NET
in their current terminal.

Closes dotnet#51582

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GenerateEnvScript now accepts an optional dotnetupDir parameter.
When provided, the dotnetup binary's directory is prepended to PATH
alongside the dotnet install path, so both dotnet and dotnetup are
available after sourcing the script.

The print-env-script command passes Path.GetDirectoryName(Environment.ProcessPath)
automatically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When switching to admin install on Unix, shell profile entries are
replaced with dotnetup-only versions that add dotnetup to PATH but
do not set DOTNET_ROOT or add the dotnet install path (since the
admin/system install manages dotnet).

Add --dotnetup-only flag to print-env-script command. When set, the
generated script only adds the dotnetup directory to PATH.

Add ShellProfileManager.ReplaceProfileEntries() for switching between
user and admin profile entries.

Add includeDotnet parameter to GenerateEnvScript and dotnetupOnly
parameter to GenerateProfileEntry/GenerateActivationCommand on
IEnvShellProvider.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restructure the document so that install and defaultinstall are presented
as the primary ways environment setup happens, with print-env-script
described as the underlying building block and standalone utility.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
EnvironmentVariableTarget.User has no persistent store on Unix in .NET,
so the SetEnvironmentVariable calls for DOTNET_ROOT and PATH were
effectively process-scoped and had no lasting effect. Shell profile
entries are the sole persistence mechanism on Unix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The shell providers generate eval-based commands, so the documentation
examples should match. Also use dot-source (.) instead of source for
POSIX compatibility.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ripts

The output of print-env-script is consumed via eval, not sourced as a
file. The 'source this script' instructions were misleading. Removed
from all three shell providers and the documentation examples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The generated scripts add both the dotnetup binary directory and the
dotnet install path to PATH. The documentation examples were missing
the dotnetup directory.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The command works on Unix by replacing profile entries with
dotnetup-only entries. The remaining gap is system-wide /etc/profile.d/
configuration, so reword the item to reflect that.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
On non-Windows, configuring the default install requires modifying
shell profile files. If the current shell cannot be detected or is not
supported, the profile modification would silently do nothing. Instead,
detect this up-front and skip the prompt with a warning message, so the
user knows why the default install setup was skipped.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the supported shells array and shell map from
PrintEnvScriptCommandParser into ShellDetection, eliminating the
duplicate dictionary and the duplicate LookupShellFromEnvironment
method. All callers now go through ShellDetection for shell lookup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AddProfileEntries now replaces existing entries in-place when found,
preserving the user's ordering in their profile file. This eliminates
the need for a separate ReplaceProfileEntries method and fixes the
case where AddProfileEntries would silently skip stale entries.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove duplicate '# dotnetup' constants from BashEnvShellProvider,
ZshEnvShellProvider, and PowerShellEnvShellProvider. All three now
reference ShellProfileManager.MarkerComment, ensuring the marker
used to generate entries always matches the one used to find them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add 'hash -d dotnet' (bash) and 'rehash' (zsh) to the generated
scripts so a stale cached dotnet path is cleared when the environment
is configured. This replaces the misleading comments that claimed
dotnetup would handle it automatically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the validator and completion source setup from the static
constructor into the ShellOption object initializer using collection
initializer syntax. Remove the now-unnecessary helper methods.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move IEnvShellProvider, BashEnvShellProvider, ZshEnvShellProvider,
PowerShellEnvShellProvider, ShellDetection, and ShellProfileManager
into a new Shell/ directory and namespace. These types are used across
multiple commands and don't belong in the PrintEnvScript namespace.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The test was checking that the first PATH entry containing 'dotnet' was
the install path. Now that the dotnetup directory is also added to PATH,
the dotnetup binary path (which contains 'dotnet' as a substring) can
appear first. Changed to simply verify the install path is contained in
PATH entries.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Change the runtime install parser from a single optional argument to
zero-or-more positional arguments, allowing commands like:
  dotnetup runtime install 8.0 9.0 10.0
  dotnetup runtime install aspnetcore@10.0 windowsdesktop@10.0

All specs are parsed and validated up front before any installs begin.
Installs then execute sequentially. When no specs are provided, the
behavior is unchanged (defaults to latest core runtime).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When multiple runtime specs are provided, downloads now run in
parallel with separate progress bars in a shared Spectre.Console
progress context. Extraction/installation remains serialized.

Key changes:
- DotnetArchiveExtractor accepts an optional shared IProgressReporter
  so multiple extractors can share one progress display session
- InstallerOrchestratorSingleton.InstallMultiple validates all requests,
  downloads concurrently via Task.WhenAll, then commits sequentially
- InstallExecutor.ExecuteInstallMultiple wraps the batch orchestration
  with status messages
- InstallWorkflow.ExecuteMultiple resolves shared context (install path,
  default install) once, then delegates to the batch executor
- RuntimeInstallCommand routes to ExecuteMultiple for 2+ specs

Single-spec installs continue through the existing code path unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Test multi-spec parser behavior: multiple positional args, mixed
component types, and that parsed values are correctly extracted.
Test InstallMultiple empty-list early return.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsplaisted dsplaisted force-pushed the dotnetup-multi-runtime branch from 62eee47 to 81006c5 Compare March 16, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant