Skip to content
Open
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
3 changes: 2 additions & 1 deletion eng/common/dotnet-install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Param(
[string] $verbosity = 'minimal',
[string] $architecture = '',
[string] $version = 'Latest',
[string] $channel = '',
[string] $runtime = 'dotnet',
[string] $RuntimeSourceFeed = '',
[string] $RuntimeSourceFeedKey = ''
Expand All @@ -17,7 +18,7 @@ try {
if ($architecture -and $architecture.Trim() -eq 'x86') {
$installdir = Join-Path $installdir 'x86'
}
InstallDotNet $installdir $version $architecture $runtime $true -RuntimeSourceFeed $RuntimeSourceFeed -RuntimeSourceFeedKey $RuntimeSourceFeedKey
InstallDotNet $installdir $version $architecture $runtime $true -RuntimeSourceFeed $RuntimeSourceFeed -RuntimeSourceFeedKey $RuntimeSourceFeedKey -Channel $channel
}
catch {
Write-Host $_.ScriptStackTrace
Expand Down
7 changes: 6 additions & 1 deletion eng/common/dotnet-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
. "$scriptroot/tools.sh"

version='Latest'
channel=''
architecture=''
runtime='dotnet'
runtimeSourceFeed=''
Expand All @@ -25,6 +26,10 @@ while [[ $# -gt 0 ]]; do
shift
version="$1"
;;
-channel|-c)
shift
channel="$1"
;;
-architecture|-a)
shift
architecture="$1"
Expand Down Expand Up @@ -85,7 +90,7 @@ if [[ $architecture != "" ]] && [[ $architecture != $buildarch ]]; then
dotnetRoot="$dotnetRoot/$architecture"
fi

InstallDotNet "$dotnetRoot" $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || {
InstallDotNet "$dotnetRoot" $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey "$channel" || {
local exit_code=$?
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "dotnet-install.sh failed (exit code '$exit_code')." >&2
ExitWithExitCode $exit_code
Expand Down
38 changes: 27 additions & 11 deletions eng/common/tools.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ function InstallDotNet([string] $dotnetRoot,
[bool] $skipNonVersionedFiles = $false,
[string] $runtimeSourceFeed = '',
[string] $runtimeSourceFeedKey = '',
[string] $channel = '',
[switch] $noPath) {

$dotnetVersionLabel = "'sdk v$version'"
Expand All @@ -301,21 +302,36 @@ function InstallDotNet([string] $dotnetRoot,
if ($runtime -eq "dotnet") { $runtimePath = $runtimePath + "\Microsoft.NETCore.App" }
if ($runtime -eq "aspnetcore") { $runtimePath = $runtimePath + "\Microsoft.AspNetCore.App" }
if ($runtime -eq "windowsdesktop") { $runtimePath = $runtimePath + "\Microsoft.WindowsDesktop.App" }
$runtimePath = $runtimePath + "\" + $version

$dotnetVersionLabel = "runtime toolset '$runtime/$architecture v$version'"

if (Test-Path $runtimePath) {
Write-Host " Runtime toolset '$runtime/$architecture v$version' already installed."
$installSuccess = $true
Exit

# When using channel, we can't check for an existing installation by version
# since we don't know which version will be installed
Copy link
Member

Choose a reason for hiding this comment

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

@mconnew would this be a problem for you? it means we'd run dotnet-install.ps1 everytime

Copy link
Member

Choose a reason for hiding this comment

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

@akoeplinger, would that only be when running restore? If running build -build doesn't trigger this, that would be fine.

if (-not $channel) {
$runtimePath = $runtimePath + "\" + $version
$dotnetVersionLabel = "runtime toolset '$runtime/$architecture v$version'"

if (Test-Path $runtimePath) {
Write-Host " Runtime toolset '$runtime/$architecture v$version' already installed."
$installSuccess = $true
return
}
} else {
$dotnetVersionLabel = "runtime toolset '$runtime/$architecture channel $channel'"
}
}

$installScript = GetDotNetInstallScript $dotnetRoot
$installParameters = @{
Version = $version
InstallDir = $dotnetRoot

# Use -Channel if specified, otherwise use -Version
if ($channel) {
$installParameters = @{
Channel = $channel
InstallDir = $dotnetRoot
}
} else {
$installParameters = @{
Version = $version
InstallDir = $dotnetRoot
}
}

if ($architecture) { $installParameters.Architecture = $architecture }
Expand Down
30 changes: 21 additions & 9 deletions eng/common/tools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ function InstallDotNet {
local root=$1
local version=$2
local runtime=$4
local channel="${8:-}"

local dotnetVersionLabel="'$runtime v$version'"
if [[ -n "${4:-}" ]] && [ "$4" != 'sdk' ]; then
Expand All @@ -201,21 +202,32 @@ function InstallDotNet {
*)
;;
esac
runtimePath="$runtimePath/$version"

dotnetVersionLabel="runtime toolset '$runtime/$architecture v$version'"

if [ -d "$runtimePath" ]; then
echo " Runtime toolset '$runtime/$architecture v$version' already installed."
local installSuccess=1
return

# When using channel, we can't check for an existing installation by version
# since we don't know which version will be installed
if [[ -z "$channel" ]]; then
runtimePath="$runtimePath/$version"
dotnetVersionLabel="runtime toolset '$runtime/$architecture v$version'"

if [ -d "$runtimePath" ]; then
echo " Runtime toolset '$runtime/$architecture v$version' already installed."
local installSuccess=1
return
fi
else
dotnetVersionLabel="runtime toolset '$runtime/$architecture channel $channel'"
fi
fi

GetDotNetInstallScript "$root"
local install_script=$_GetDotNetInstallScript

local installParameters=(--version $version --install-dir "$root")
# Use --channel if specified, otherwise use --version
if [[ -n "$channel" ]]; then
local installParameters=(--channel $channel --install-dir "$root")
else
local installParameters=(--version $version --install-dir "$root")
fi

if [[ -n "${3:-}" ]] && [ "$3" != 'unset' ]; then
installParameters+=(--architecture $3)
Expand Down
37 changes: 37 additions & 0 deletions src/Microsoft.DotNet.Arcade.Sdk.Tests/InstallDotNetCoreTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using System.Reflection;
using Xunit;

namespace Microsoft.DotNet.Arcade.Sdk.Tests
{
public class InstallDotNetCoreTests
{
[Theory]
[InlineData("8.0", true)]
[InlineData("10.0", true)]
[InlineData("3.1", true)]
[InlineData("8.0.22", false)]
[InlineData("10.0.1", false)]
[InlineData("8.0.0-preview.1", false)]
[InlineData("", false)]
[InlineData(null, false)]
[InlineData("8", false)]
[InlineData("8.0.1.2", false)]
[InlineData("v8.0", false)]
[InlineData("8.x", false)]
public void IsTwoPartVersion_DetectsCorrectFormat(string versionString, bool expected)
{
// Use reflection to call the private method
var task = new InstallDotNetCore();
var method = typeof(InstallDotNetCore).GetMethod("IsTwoPartVersion", BindingFlags.NonPublic | BindingFlags.Instance);

var result = (bool)method.Invoke(task, new object[] { versionString });

Assert.Equal(expected, result);
}
}
}
33 changes: 30 additions & 3 deletions src/Microsoft.DotNet.Arcade.Sdk/src/InstallDotNetCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;

namespace Microsoft.DotNet.Arcade.Sdk
{
Expand Down Expand Up @@ -106,8 +107,16 @@ public override bool Execute()
}

SemanticVersion version = null;
string channel = null;

// Check if the version is in major.minor format (e.g., "8.0", "10.0")
// This format should use the -channel parameter instead of -version
if (IsTwoPartVersion(item.Key))
{
channel = item.Key;
}
// Try to parse version
if (!SemanticVersion.TryParse(item.Key, out version))
else if (!SemanticVersion.TryParse(item.Key, out version))
{
var propertyName = item.Key.Trim(s_keyTrimChars);

Expand All @@ -123,9 +132,12 @@ public override bool Execute()
}
}

if (version != null)
if (version != null || channel != null)
{
string arguments = $"-runtime \"{runtimeItem.Key}\" -version \"{version.ToNormalizedString()}\"";
string arguments = channel != null
? $"-runtime \"{runtimeItem.Key}\" -channel \"{channel}\""
: $"-runtime \"{runtimeItem.Key}\" -version \"{version.ToNormalizedString()}\"";

if (!string.IsNullOrEmpty(architecture))
{
arguments += $" -architecture {architecture}";
Expand Down Expand Up @@ -204,6 +216,21 @@ private string GetArchitecture(string architecture)
return null;
}

/*
* Checks if a version string is in major.minor format (e.g., "8.0", "10.0").
* Returns true if the version has exactly two numeric parts separated by a dot.
*/
private bool IsTwoPartVersion(string versionString)
{
if (string.IsNullOrWhiteSpace(versionString))
Copy link
Member

Choose a reason for hiding this comment

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

@copilot Please use a regex for this detection.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to use regex pattern ^\d+\.\d+$ for version detection in commit a9584e4.

{
return false;
}

// Match exactly two numeric parts separated by a dot
return Regex.IsMatch(versionString, @"^\d+\.\d+$");
}

/*
* Parses a json token of this format
* { (runtime): [(version), ..., (version)] }
Expand Down
Loading