From 8d6284c094ee5bbf23eca503b663bddd002206af Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 May 2025 20:46:35 +0000 Subject: [PATCH 1/6] Add --os option to dotnet restore command Co-authored-by: marcpopMSFT <12663534+marcpopMSFT@users.noreply.github.com> --- documentation/manpages/sdk/dotnet-restore.1 | 13 +++++++++++-- .../dotnet/Commands/Restore/RestoreCommandParser.cs | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/documentation/manpages/sdk/dotnet-restore.1 b/documentation/manpages/sdk/dotnet-restore.1 index eacab58b3f3b..71325fac705c 100644 --- a/documentation/manpages/sdk/dotnet-restore.1 +++ b/documentation/manpages/sdk/dotnet-restore.1 @@ -26,11 +26,11 @@ dotnet-restore - Restores the dependencies and tools of a project. .IP .nf \f[C] -dotnet restore [] [--configfile ] [--disable-build-servers] +dotnet restore [] [-a|--arch ] [--configfile ] [--disable-build-servers] [--disable-parallel] [-f|--force] [--force-evaluate] [--ignore-failed-sources] [--interactive] [--lock-file-path ] [--locked-mode] - [--no-cache] [--no-dependencies] [--packages ] + [--no-cache] [--no-dependencies] [--os ] [--packages ] [-r|--runtime ] [-s|--source ] [--tl:[auto|on|off]] [--use-current-runtime, --ucr [true|false]] [--use-lock-file] [-v|--verbosity ] @@ -144,6 +144,15 @@ If you use this option, don\[cq]t use the \f[V]-r|--runtime\f[R] option. Available since .NET 6 Preview 7. .RE .IP \[bu] 2 +\f[B]\f[VB]--os \f[B]\f[R] +.RS 2 +.PP +Specifies the target operating system (OS). +This is a shorthand syntax for setting the Runtime Identifier (RID), where the provided value is combined with the default RID. +For example, on a \f[V]win-x64\f[R] machine, specifying \f[V]--os linux\f[R] sets the RID to \f[V]linux-x64\f[R]. +If you use this option, don\[cq]t use the \f[V]-r|--runtime\f[R] option. +.RE +.IP \[bu] 2 \f[B]\f[VB]--configfile \f[B]\f[R] .RS 2 .PP diff --git a/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs b/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs index 1579c4c800eb..436e02d6a297 100644 --- a/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs +++ b/src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs @@ -73,6 +73,7 @@ private static Command ConstructCommand() } command.Options.Add(CommonOptions.ArchitectureOption); + command.Options.Add(CommonOptions.OperatingSystemOption); command.SetAction(RestoreCommand.Run); return command; From db23fc92c9823b18f6593f1ad43f2add4bce2fe9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 May 2025 22:01:52 +0000 Subject: [PATCH 2/6] Add test for dotnet restore with -r, --os, and -a options Co-authored-by: marcpopMSFT <12663534+marcpopMSFT@users.noreply.github.com> --- .../Restore/GivenThatIWantToRestoreApp.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs b/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs index ff195897c56d..6841583218c1 100644 --- a/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs +++ b/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.DotNet.Tools.Test.Utilities; +using System.Runtime.InteropServices; namespace Microsoft.DotNet.Restore.Test { @@ -167,6 +168,44 @@ public void ItAcceptsArgumentsAfterProperties() .Should() .Pass(); } + + /// + /// Tests for RID-specific restore options: -r/--runtime, --os, and -a/--arch + /// + [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(); + } private static string[] HandleStaticGraphEvaluation(bool useStaticGraphEvaluation, string[] args) => useStaticGraphEvaluation ? From bacc17672452da55cef36095efbc7d87301ee76d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:44:44 +0000 Subject: [PATCH 3/6] Fix completion test baselines for --os option in restore command Co-authored-by: marcpopMSFT <12663534+marcpopMSFT@users.noreply.github.com> --- .../bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh | 2 +- .../pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 | 1 + .../zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh b/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh index 04baf61a558c..1e61c0df86d4 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh +++ b/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh @@ -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") ) diff --git a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 index 8e57a763897b..38d7994134f4 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 +++ b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 @@ -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.") ) diff --git a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh index 9736bd37d270..cccab3722015 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh +++ b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh @@ -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.: ' \ From bf09c54aa0a82e42f5bf245cfda488e8b36479e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Jun 2025 20:59:14 +0000 Subject: [PATCH 4/6] Revert generated manpage changes and update copilot instructions Co-authored-by: marcpopMSFT <12663534+marcpopMSFT@users.noreply.github.com> --- .github/copilot-instructions.md | 5 ++++- documentation/manpages/sdk/dotnet-restore.1 | 13 ++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f8efeffcba17..2b187a949b6b 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -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. \ No newline at end of file +- 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. \ No newline at end of file diff --git a/documentation/manpages/sdk/dotnet-restore.1 b/documentation/manpages/sdk/dotnet-restore.1 index 71325fac705c..eacab58b3f3b 100644 --- a/documentation/manpages/sdk/dotnet-restore.1 +++ b/documentation/manpages/sdk/dotnet-restore.1 @@ -26,11 +26,11 @@ dotnet-restore - Restores the dependencies and tools of a project. .IP .nf \f[C] -dotnet restore [] [-a|--arch ] [--configfile ] [--disable-build-servers] +dotnet restore [] [--configfile ] [--disable-build-servers] [--disable-parallel] [-f|--force] [--force-evaluate] [--ignore-failed-sources] [--interactive] [--lock-file-path ] [--locked-mode] - [--no-cache] [--no-dependencies] [--os ] [--packages ] + [--no-cache] [--no-dependencies] [--packages ] [-r|--runtime ] [-s|--source ] [--tl:[auto|on|off]] [--use-current-runtime, --ucr [true|false]] [--use-lock-file] [-v|--verbosity ] @@ -144,15 +144,6 @@ If you use this option, don\[cq]t use the \f[V]-r|--runtime\f[R] option. Available since .NET 6 Preview 7. .RE .IP \[bu] 2 -\f[B]\f[VB]--os \f[B]\f[R] -.RS 2 -.PP -Specifies the target operating system (OS). -This is a shorthand syntax for setting the Runtime Identifier (RID), where the provided value is combined with the default RID. -For example, on a \f[V]win-x64\f[R] machine, specifying \f[V]--os linux\f[R] sets the RID to \f[V]linux-x64\f[R]. -If you use this option, don\[cq]t use the \f[V]-r|--runtime\f[R] option. -.RE -.IP \[bu] 2 \f[B]\f[VB]--configfile \f[B]\f[R] .RS 2 .PP From f71118c81e86cea807456a8a839b7ec63a2785d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Jun 2025 20:33:55 +0000 Subject: [PATCH 5/6] Add RID-specific assets validation to restore test Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../Restore/GivenThatIWantToRestoreApp.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs b/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs index 6841583218c1..3ca6b3015058 100644 --- a/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs +++ b/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs @@ -2,6 +2,7 @@ // 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 @@ -205,6 +206,22 @@ public void ItRestoresWithRidSpecificOptions(params string[] ridOptions) // 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 RID-specific targets when using RID options + if (ridOptions.Contains("-r") || ridOptions.Contains("--runtime") || + ridOptions.Contains("--os") || ridOptions.Contains("-a") || ridOptions.Contains("--arch")) + { + var assetsContents = JObject.Parse(File.ReadAllText(assetsFilePath)); + var targets = assetsContents["targets"]; + targets.Should().NotBeNull("assets file should contain targets section"); + + // Check for RID-specific targets (targets with RID have names containing "/") + var ridSpecificTargets = targets.Children() + .Where(target => target.Name.Contains("/")) + .ToList(); + + ridSpecificTargets.Should().NotBeEmpty("assets file should contain RID-specific targets when using RID options"); + } } private static string[] HandleStaticGraphEvaluation(bool useStaticGraphEvaluation, string[] args) => From 5a4097ccc0de4cc551fc47e14d89a1c5b1df8968 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Jun 2025 20:46:35 +0000 Subject: [PATCH 6/6] Improve RID-specific test validation based on review feedback Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> --- .../Restore/GivenThatIWantToRestoreApp.cs | 81 ++++++++++++++++--- 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs b/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs index 3ca6b3015058..66699f4bfd89 100644 --- a/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs +++ b/test/dotnet.Tests/CommandTests/Restore/GivenThatIWantToRestoreApp.cs @@ -207,21 +207,76 @@ public void ItRestoresWithRidSpecificOptions(params string[] ridOptions) var assetsFilePath = Path.Combine(rootPath, "obj", "project.assets.json"); File.Exists(assetsFilePath).Should().BeTrue(); - // Verify that the assets file contains RID-specific targets when using RID options - if (ridOptions.Contains("-r") || ridOptions.Contains("--runtime") || - ridOptions.Contains("--os") || ridOptions.Contains("-a") || ridOptions.Contains("--arch")) + // 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++) { - var assetsContents = JObject.Parse(File.ReadAllText(assetsFilePath)); - var targets = assetsContents["targets"]; - targets.Should().NotBeNull("assets file should contain targets section"); - - // Check for RID-specific targets (targets with RID have names containing "/") - var ridSpecificTargets = targets.Children() - .Where(target => target.Name.Contains("/")) - .ToList(); - - ridSpecificTargets.Should().NotBeEmpty("assets file should contain RID-specific targets when using RID options"); + 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) =>