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
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ internal static class RestoreCommandParser

private static IEnumerable<CliOption> FullRestoreOptions() =>
ImplicitRestoreOptions(true, true, true, true).Concat(
new CliOption[] {
[
CommonOptions.VerbosityOption,
CommonOptions.InteractiveMsBuildForwardOption,
CommonOptions.ArtifactsPathOption,
new ForwardedOption<bool>("--use-lock-file")
{
Description = LocalizableStrings.CmdUseLockFileOptionDescription,
Expand All @@ -46,7 +47,8 @@ private static IEnumerable<CliOption> FullRestoreOptions() =>
new ForwardedOption<bool>("--force-evaluate")
{
Description = LocalizableStrings.CmdReevaluateOptionDescription
}.ForwardAs("-property:RestoreForceEvaluate=true") });
}.ForwardAs("-property:RestoreForceEvaluate=true"),
]);

private static readonly CliCommand Command = ConstructCommand();

Expand Down
1 change: 1 addition & 0 deletions src/Cli/dotnet/commands/dotnet-run/RunCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ private static CliCommand ConstructCommand()
command.Options.Add(CommonOptions.ArchitectureOption);
command.Options.Add(CommonOptions.OperatingSystemOption);
command.Options.Add(CommonOptions.DisableBuildServersOption);
command.Options.Add(CommonOptions.ArtifactsPathOption);

command.Arguments.Add(ApplicationArguments);

Expand Down
16 changes: 12 additions & 4 deletions src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using Microsoft.Build.Framework;
using Microsoft.Extensions.DependencyModel;
using NuGet.Packaging;
Expand Down Expand Up @@ -253,7 +254,7 @@ public DependencyContextBuilder WithPackagesThatWereFiltered(Dictionary<PackageI
return this;
}

public DependencyContext Build()
public DependencyContext Build(string[] userRuntimeAssemblies = null)
{
CalculateExcludedLibraries();

Expand All @@ -269,7 +270,7 @@ public DependencyContext Build()
foreach (var library in _dependencyLibraries.Values
.Where(l => !l.ExcludeFromRuntime && l.Type != "runtimepack"))
{
var runtimeLibrary = GetRuntimeLibrary(library);
var runtimeLibrary = GetRuntimeLibrary(library, userRuntimeAssemblies);
if (runtimeLibrary != null)
{
runtimeLibraries.Add(runtimeLibrary);
Expand Down Expand Up @@ -505,7 +506,7 @@ private IEnumerable<RuntimeLibrary> GetRuntimePackLibraries()
});
}

private RuntimeLibrary GetRuntimeLibrary(DependencyLibrary library)
private RuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, string[] userRuntimeAssemblies)
{
GetCommonLibraryProperties(library,
out string hash,
Expand All @@ -527,7 +528,14 @@ private RuntimeLibrary GetRuntimeLibrary(DependencyLibrary library)

if (library.Type == "project" && !(referenceProjectInfo is UnreferencedProjectInfo))
{
runtimeAssemblyGroups.Add(new RuntimeAssetGroup(string.Empty, referenceProjectInfo.OutputName));
var fileName = Path.GetFileNameWithoutExtension(library.Path);
var assemblyPath = userRuntimeAssemblies?.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).Equals(fileName));
runtimeAssemblyGroups.Add(new RuntimeAssetGroup(string.Empty,
[ new RuntimeFile(
referenceProjectInfo.OutputName,
library.Version.ToString(),
assemblyPath is null || !File.Exists(assemblyPath) ? string.Empty : FileVersionInfo.GetVersionInfo(assemblyPath).FileVersion)
]));

resourceAssemblies.AddRange(referenceProjectInfo.ResourceAssemblies
.Select(r => new ResourceAssembly(r.RelativePath, r.Culture)));
Expand Down
2 changes: 1 addition & 1 deletion src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ bool ShouldIncludeRuntimeAsset(ITaskItem item)
.Concat(ResolvedRuntimeTargetsFiles.Select(f => new ResolvedFile(f, true)));
builder = builder.WithResolvedNuGetFiles(resolvedNuGetFiles);

DependencyContext dependencyContext = builder.Build();
DependencyContext dependencyContext = builder.Build(UserRuntimeAssemblies);

var writer = new DependencyContextWriter();
using (var fileStream = File.Create(depsFilePath))
Expand Down
3 changes: 2 additions & 1 deletion test/dotnet-MsiInstallation.Tests/Framework/VMTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,10 @@ protected CommandResult InstallWorkload(string workloadName)
return result;
}

protected WorkloadSet GetRollback()
protected WorkloadSet GetRollback(string directory = null)
{
var result = VM.CreateRunCommand("dotnet", "workload", "update", "--print-rollback")
.WithWorkingDirectory(directory)
.WithIsReadOnly(true)
.Execute();

Expand Down
55 changes: 55 additions & 0 deletions test/dotnet-MsiInstallation.Tests/WorkloadSetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,51 @@ public void UpdateToWorkloadSetVersionWithManifestsNotAvailable()
GetWorkloadVersion().Should().Be(workloadVersionBeforeUpdate);
}

[Fact]
public void UpdateWorkloadSetViaGlobalJson()
{
InstallSdk();

var versionToUpdateTo = "8.0.300-preview.0.24217.2";
var directory = "C:\\SdkTesting";

string originalVersion = GetWorkloadVersion();

var rollback = GetRollback(directory);

VM.WriteFile("C:\\SdkTesting\\global.json", @$"{{""sdk"":{{""workloadVersion"":""{versionToUpdateTo}""}}}}").Execute().Should().Pass();

GetWorkloadVersion(directory).Should().Be(versionToUpdateTo);

// The version should have changed but not yet the manifests. Since we expect both, getting the rollback should fail.
var result = VM.CreateRunCommand("dotnet", "workload", "update", "--print-rollback")
.WithWorkingDirectory(directory)
.WithIsReadOnly(true)
.Execute();

result.Should().Fail();
result.StdErr.Should().Contain("FileNotFoundException");
result.StdErr.Should().Contain(versionToUpdateTo);

AddNuGetSource(@"C:\SdkTesting\workloadsets", directory);

VM.CreateRunCommand("dotnet", "workload", "update").WithWorkingDirectory(directory).Execute().Should().Pass();

GetRollback(directory).Should().NotBe(rollback);
}

string GetWorkloadVersion(string workingDirectory = null)
{
var result = VM.CreateRunCommand("dotnet", "workload", "--version")
.WithWorkingDirectory(workingDirectory)
.WithIsReadOnly(true)
.Execute();

result.Should().Pass();

return result.StdOut;
}

string GetUpdateMode()
{
var result = VM.CreateRunCommand("dotnet", "workload", "config", "--update-mode")
Expand All @@ -223,5 +268,15 @@ string GetUpdateMode()

return result.StdOut;
}

void AddNuGetSource(string source, string directory = null)
{
VM.CreateRunCommand("dotnet", "nuget", "add", "source", source)
.WithWorkingDirectory(directory)
.WithDescription($"Add {source} to NuGet.config")
.Execute()
.Should()
.Pass();
}
}
}
62 changes: 62 additions & 0 deletions test/dotnet.Tests/ParserTests/BuildRelatedCommandParserTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.CommandLine;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLineValidation;
using Microsoft.DotNet.Tools.Common;
using Parser = Microsoft.DotNet.Cli.Parser;

namespace Microsoft.DotNet.Tests.ParserTests
{
public class BuildRelatedCommandParserTests
{

/// <summary>
/// These commands all implicitly use MSBuild under the covers and generally should expose
/// the same set of property- and behavior-impacting options.
/// </summary>
private static string[] BuildRelatedCommands = [
"build",
"clean",
"pack",
"publish",
"restore",
"run",
"test"
];

private static string[] OptionsToVerify = [
"--artifacts-path"
];

public static TheoryData<string, string> BuildRelatedCommandsAndOptions()
{
var data = new TheoryData<string, string>();
foreach (var cmd in BuildRelatedCommands)
{
foreach (var opt in OptionsToVerify)
{
data.Add(cmd, opt);
}
}
return data;
}

[MemberData(nameof(BuildRelatedCommandsAndOptions))]
[Theory]
public void Build(string command, string option)
{
var cliCommand = Parser.Instance.RootCommand.Children.OfType<CliCommand>().FirstOrDefault(c => c.Name == command);
if (cliCommand is null)
{
throw new ArgumentException($"Command {command} not found in the dotnet CLI");
}
var cliOption = cliCommand.Children.OfType<CliOption>().FirstOrDefault(o => o.Name == option || o.Aliases.Contains(option));
if (cliOption is null)
{
throw new ArgumentException($"Option {option} not found in the {command} command");
}
}
}
}