Skip to content
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
5 changes: 4 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ Output Considerations:

Localization:
- Avoid modifying .xlf files and instead prompt the user to update them using the `/t:UpdateXlf` target on MSBuild.
- Consider localizing strings in .resx files when possible.
- Consider localizing strings in .resx files when possible.

Documentation:
- Do not manually edit files under documentation/manpages/sdk as these are generated based on documentation and should not be manually modified.
1 change: 1 addition & 0 deletions src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ private static Command ConstructCommand()
}

command.Options.Add(CommonOptions.ArchitectureOption);
command.Options.Add(CommonOptions.OperatingSystemOption);
command.SetAction(RestoreCommand.Run);

return command;
Expand Down
111 changes: 111 additions & 0 deletions test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.DotNet.Tools.Test.Utilities;
using Newtonsoft.Json.Linq;
using System.Runtime.InteropServices;

namespace Microsoft.DotNet.Restore.Test
{
Expand Down Expand Up @@ -167,6 +169,115 @@ public void ItAcceptsArgumentsAfterProperties()
.Should()
.Pass();
}

/// <summary>
/// Tests for RID-specific restore options: -r/--runtime, --os, and -a/--arch
/// </summary>
[Theory]
[InlineData("-r", "linux-x64")]
[InlineData("--runtime", "win-x64")]
[InlineData("--os", "linux")]
[InlineData("-a", "arm64")]
[InlineData("--arch", "x64")]
[InlineData("--os", "linux", "-a", "arm64")]
public void ItRestoresWithRidSpecificOptions(params string[] ridOptions)
{
// Skip test for #24251
var testProject = new TestProject()
{
Name = "RestoreWithRidOptions",
TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
};

testProject.PackageReferences.Add(new TestPackageReference("Newtonsoft.Json", ToolsetInfo.GetNewtonsoftJsonPackageVersion()));

var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: string.Join("_", ridOptions));

var rootPath = Path.Combine(testAsset.TestRoot, testProject.Name);

// Create the command with the RID-specific options
var restoreCommand = new DotnetRestoreCommand(Log)
.WithWorkingDirectory(rootPath)
.Execute(ridOptions);

// Verify that the command runs successfully
restoreCommand.Should().Pass();

// Verify that assets file was created
var assetsFilePath = Path.Combine(rootPath, "obj", "project.assets.json");
File.Exists(assetsFilePath).Should().BeTrue();

// Verify that the assets file contains the expected RID-specific target
var assetsContents = JObject.Parse(File.ReadAllText(assetsFilePath));
var targets = assetsContents["targets"];
targets.Should().NotBeNull("assets file should contain targets section");

// Determine the expected RID based on the options provided
string expectedRid = GetExpectedRid(ridOptions);
string expectedTarget = $"{ToolsetInfo.CurrentTargetFramework}/{expectedRid}";

// Check that the specific target exists
var specificTarget = targets[expectedTarget];
specificTarget.Should().NotBeNull($"assets file should contain target '{expectedTarget}' when using RID options: {string.Join(" ", ridOptions)}");
}

private static string GetExpectedRid(string[] ridOptions)
{
// Check if explicit runtime is provided
for (int i = 0; i < ridOptions.Length; i++)
{
if ((ridOptions[i] == "-r" || ridOptions[i] == "--runtime") && i + 1 < ridOptions.Length)
{
return ridOptions[i + 1];
}
}

// Get current platform defaults
string currentOs = GetCurrentOsPart();
string currentArch = GetCurrentArchPart();

// Check for --os and --arch options to synthesize RID
string targetOs = currentOs;
string targetArch = currentArch;

for (int i = 0; i < ridOptions.Length; i++)
{
if (ridOptions[i] == "--os" && i + 1 < ridOptions.Length)
{
targetOs = ridOptions[i + 1];
}
else if ((ridOptions[i] == "-a" || ridOptions[i] == "--arch") && i + 1 < ridOptions.Length)
{
targetArch = ridOptions[i + 1];
}
}

return $"{targetOs}-{targetArch}";
}

private static string GetCurrentOsPart()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return "win";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return "linux";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return "osx";
else
throw new PlatformNotSupportedException("Unsupported platform for RID determination");
}

private static string GetCurrentArchPart()
{
return RuntimeInformation.OSArchitecture switch
{
Architecture.X64 => "x64",
Architecture.X86 => "x86",
Architecture.Arm64 => "arm64",
Architecture.Arm => "arm",
_ => throw new PlatformNotSupportedException($"Unsupported architecture: {RuntimeInformation.OSArchitecture}")
};
}

private static string[] HandleStaticGraphEvaluation(bool useStaticGraphEvaluation, string[] args) =>
useStaticGraphEvaluation ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ _testhost_restore() {
prev="${COMP_WORDS[COMP_CWORD-1]}"
COMPREPLY=()

opts="--disable-build-servers --source --packages --use-current-runtime --disable-parallel --configfile --no-http-cache --ignore-failed-sources --force --runtime --no-dependencies --verbosity --interactive --artifacts-path --use-lock-file --locked-mode --lock-file-path --force-evaluate --arch --help"
opts="--disable-build-servers --source --packages --use-current-runtime --disable-parallel --configfile --no-http-cache --ignore-failed-sources --force --runtime --no-dependencies --verbosity --interactive --artifacts-path --use-lock-file --locked-mode --lock-file-path --force-evaluate --arch --os --help"

if [[ $COMP_CWORD == "$1" ]]; then
COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ Register-ArgumentCompleter -Native -CommandName 'testhost' -ScriptBlock {
[CompletionResult]::new('--force-evaluate', '--force-evaluate', [CompletionResultType]::ParameterName, "Forces restore to reevaluate all dependencies even if a lock file already exists.")
[CompletionResult]::new('--arch', '--arch', [CompletionResultType]::ParameterName, "The target architecture.")
[CompletionResult]::new('--arch', '-a', [CompletionResultType]::ParameterName, "The target architecture.")
[CompletionResult]::new('--os', '--os', [CompletionResultType]::ParameterName, "The target operating system.")
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, "Show command line help.")
[CompletionResult]::new('--help', '-h', [CompletionResultType]::ParameterName, "Show command line help.")
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ _testhost() {
'--force-evaluate[Forces restore to reevaluate all dependencies even if a lock file already exists.]' \
'--arch=[The target architecture.]:ARCH: ' \
'-a=[The target architecture.]:ARCH: ' \
'--os=[The target operating system.]:OS: ' \
'--help[Show command line help.]' \
'-h[Show command line help.]' \
'*::PROJECT | SOLUTION | FILE -- The project or solution or C# (file-based program) file to operate on. If a file is not specified, the command will search the current directory for a project or solution.: ' \
Expand Down
Loading