Skip to content

Commit

Permalink
Merge branch 'release/9.0.2xx' into SourcePackageUsings
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat authored Dec 10, 2024
2 parents b31ecfc + 83b8a1b commit f2a8a80
Show file tree
Hide file tree
Showing 14 changed files with 197 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.DotNet.Cli.Utils;

namespace Microsoft.DotNet.CommandFactory
{
public class CompositeCommandResolver : ICommandResolver
{
private const string CommandResolveEvent = "commandresolution/commandresolved";
private IList<ICommandResolver> _orderedCommandResolvers;

public IEnumerable<ICommandResolver> OrderedCommandResolvers
Expand Down Expand Up @@ -33,6 +36,12 @@ public CommandSpec Resolve(CommandResolverArguments commandResolverArguments)

if (commandSpec != null)
{
TelemetryEventEntry.TrackEvent(CommandResolveEvent, new Dictionary<string, string>()
{
{ "commandName", commandResolverArguments is null ? string.Empty : Sha256Hasher.HashWithNormalizedCasing(commandResolverArguments.CommandName) },
{ "commandResolver", commandResolver.GetType().ToString() }
});

return commandSpec;
}
}
Expand Down
37 changes: 37 additions & 0 deletions src/Cli/dotnet/commands/dotnet-workload/WorkloadUtilities.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 Microsoft.Deployment.DotNet.Releases;

namespace Microsoft.DotNet.Workloads.Workload
{
internal class WorkloadUtilities
{
internal static int VersionCompare(string first, string second)
{
if (first.Equals(second))
{
return 0;
}

var firstDash = first.IndexOf('-');
var secondDash = second.IndexOf('-');
firstDash = firstDash < 0 ? first.Length : firstDash;
secondDash = secondDash < 0 ? second.Length : secondDash;

var firstVersion = new Version(first.Substring(0, firstDash));
var secondVersion = new Version(second.Substring(0, secondDash));

var comparison = firstVersion.CompareTo(secondVersion);
if (comparison != 0)
{
return comparison;
}

var modifiedFirst = new ReleaseVersion(1, 1, 1, firstDash == first.Length ? null : first.Substring(firstDash));
var modifiedSecond = new ReleaseVersion(1, 1, 1, secondDash == second.Length ? null : second.Substring(secondDash));

return modifiedFirst.CompareTo(modifiedSecond);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ public async Task<WorkloadSet> GetWorkloadSetContentsAsync(string workloadSetVer
}

public void InstallWorkloads(IEnumerable<WorkloadId> workloadIds, SdkFeatureBand sdkFeatureBand, ITransactionContext transactionContext, DirectoryPath? offlineCache = null)
{
InstallWorkloads(workloadIds, sdkFeatureBand, transactionContext, overwriteExistingPacks: false, offlineCache);
}

public void InstallWorkloads(IEnumerable<WorkloadId> workloadIds, SdkFeatureBand sdkFeatureBand, ITransactionContext transactionContext, bool overwriteExistingPacks, DirectoryPath? offlineCache = null)
{
var packInfos = GetPacksInWorkloads(workloadIds);

Expand All @@ -146,7 +151,11 @@ public void InstallWorkloads(IEnumerable<WorkloadId> workloadIds, SdkFeatureBand
transactionContext.Run(
action: () =>
{
if (!PackIsInstalled(packInfo))
if (PackIsInstalled(packInfo) && !overwriteExistingPacks)
{
_reporter.WriteLine(string.Format(LocalizableStrings.WorkloadPackAlreadyInstalledMessage, packInfo.ResolvedPackageId, packInfo.Version));
}
else
{
shouldRollBackPack = true;
string packagePath;
Expand Down Expand Up @@ -175,22 +184,30 @@ public void InstallWorkloads(IEnumerable<WorkloadId> workloadIds, SdkFeatureBand

if (IsSingleFilePack(packInfo))
{
File.Copy(packagePath, packInfo.Path);
File.Copy(packagePath, packInfo.Path, overwrite: overwriteExistingPacks);
}
else
{
var tempExtractionDir = Path.Combine(_tempPackagesDir.Value, $"{packInfo.ResolvedPackageId}-{packInfo.Version}-extracted");
tempDirsToDelete.Add(tempExtractionDir);

// This directory should have been deleted, but remove it just in case
if (overwriteExistingPacks && Directory.Exists(tempExtractionDir))
{
Directory.Delete(tempExtractionDir, recursive: true);
}

Directory.CreateDirectory(tempExtractionDir);
var packFiles = _nugetPackageDownloader.ExtractPackageAsync(packagePath, new DirectoryPath(tempExtractionDir)).GetAwaiter().GetResult();

if (overwriteExistingPacks && Directory.Exists(packInfo.Path))
{
Directory.Delete(packInfo.Path, recursive: true);
}

FileAccessRetrier.RetryOnMoveAccessFailure(() => DirectoryPath.MoveDirectory(tempExtractionDir, packInfo.Path));
}
}
else
{
_reporter.WriteLine(string.Format(LocalizableStrings.WorkloadPackAlreadyInstalledMessage, packInfo.ResolvedPackageId, packInfo.Version));
}
}

WritePackInstallationRecord(packInfo, sdkFeatureBand);
},
Expand Down Expand Up @@ -237,8 +254,7 @@ public void InstallWorkloads(IEnumerable<WorkloadId> workloadIds, SdkFeatureBand

public void RepairWorkloads(IEnumerable<WorkloadId> workloadIds, SdkFeatureBand sdkFeatureBand, DirectoryPath? offlineCache = null)
{
// TODO: Actually re-extract the packs to fix any corrupted files.
CliTransaction.RunNew(context => InstallWorkloads(workloadIds, sdkFeatureBand, context, offlineCache));
CliTransaction.RunNew(context => InstallWorkloads(workloadIds, sdkFeatureBand, context, overwriteExistingPacks: true, offlineCache));
}

string GetManifestInstallDirForFeatureBand(string sdkFeatureBand)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ void GarbageCollectWorkloadSets()
// If there isn't a rollback state file, don't garbage collect the latest workload set installed for the feature band
if (installedWorkloadSets.Any())
{
var latestWorkloadSetVersion = installedWorkloadSets.Keys.MaxBy(k => new ReleaseVersion(k));
var latestWorkloadSetVersion = installedWorkloadSets.Keys.Aggregate((s1, s2) => WorkloadUtilities.VersionCompare(s1, s2) >= 0 ? s1 : s2);
_workloadSets[latestWorkloadSetVersion] = GCAction.Keep;
_verboseReporter.WriteLine($"GC: Keeping latest installed workload set version {latestWorkloadSetVersion}");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.CommandLine;
using Microsoft.DotNet.Workloads.Workload;
using Microsoft.DotNet.Workloads.Workload.Search;
using LocalizableStrings = Microsoft.DotNet.Workloads.Workload.Search.LocalizableStrings;

Expand Down Expand Up @@ -56,6 +57,15 @@ private static CliCommand ConstructCommand()
}
});

command.Validators.Add(result =>
{
var versionArgument = result.GetValue(WorkloadVersionArgument);
if (versionArgument is not null && !WorkloadSetVersion.IsWorkloadSetPackageVersion(versionArgument))
{
result.AddError(string.Format(CommandLineValidation.LocalizableStrings.UnrecognizedCommandOrArgument, versionArgument));
}
});

command.SetAction(parseResult => new WorkloadSearchVersionsCommand(parseResult).Execute());

return command;
Expand Down
26 changes: 15 additions & 11 deletions src/Common/WorkloadSetVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,46 @@ namespace Microsoft.DotNet.Workloads.Workload
{
static class WorkloadSetVersion
{
public static string ToWorkloadSetPackageVersion(string workloadSetVersion, out SdkFeatureBand sdkFeatureBand)
private static string[] SeparateCoreComponents(string workloadSetVersion, out string[] sections)
{
sections = workloadSetVersion.Split(['-', '+'], 2);
return sections[0].Split('.');
}

public static bool IsWorkloadSetPackageVersion(string workloadSetVersion)
{
string[] sections = workloadSetVersion.Split(new char[] { '-', '+' }, 2);
string versionCore = sections[0];
string? preReleaseOrBuild = sections.Length > 1 ? sections[1] : null;
int coreComponentsLength = SeparateCoreComponents(workloadSetVersion, out _).Length;
return coreComponentsLength >= 3 && coreComponentsLength <= 4;
}

string[] coreComponents = versionCore.Split('.');
public static string ToWorkloadSetPackageVersion(string workloadSetVersion, out SdkFeatureBand sdkFeatureBand)
{
string[] coreComponents = SeparateCoreComponents(workloadSetVersion, out string[] sections);
string major = coreComponents[0];
string minor = coreComponents[1];
string patch = coreComponents[2];

string packageVersion = $"{major}.{patch}.";
if (coreComponents.Length == 3)
{
// No workload set patch version
packageVersion += "0";

// Use preview specifier (if any) from workload set version as part of SDK feature band
sdkFeatureBand = new SdkFeatureBand(workloadSetVersion);
}
else
{
// Workload set version has workload patch version (ie 4 components)
packageVersion += coreComponents[3];

// Don't include any preview specifiers in SDK feature band
sdkFeatureBand = new SdkFeatureBand($"{major}.{minor}.{patch}");
}

if (preReleaseOrBuild != null)
if (sections.Length > 1)
{
// Figure out if we split on a '-' or '+'
char separator = workloadSetVersion[sections[0].Length];
packageVersion += separator + preReleaseOrBuild;
packageVersion += separator + sections[1];
}

return packageVersion;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,10 @@ private static int VersionCompare(string first, string second)
return comparison;
}

var modifiedFirst = "1.1.1" + (firstDash == first.Length ? string.Empty : first.Substring(firstDash));
var modifiedSecond = "1.1.1" + (secondDash == second.Length ? string.Empty : second.Substring(secondDash));
var modifiedFirst = new ReleaseVersion(1, 1, 1, firstDash == first.Length ? null : first.Substring(firstDash));
var modifiedSecond = new ReleaseVersion(1, 1, 1, secondDash == second.Length ? null : second.Substring(secondDash));

return new ReleaseVersion(modifiedFirst).CompareTo(new ReleaseVersion(modifiedSecond));
return modifiedFirst.CompareTo(modifiedSecond);
}

void ThrowExceptionIfManifestsNotAvailable()
Expand Down
38 changes: 38 additions & 0 deletions src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal class DependencyContextBuilder
private Dictionary<string, List<ReferenceInfo>> _compileReferences;
private Dictionary<string, List<ResolvedFile>> _resolvedNuGetFiles;
private Dictionary<string, SingleProjectInfo> _referenceProjectInfos;
private IEnumerable<string> _excludeFromPublishPackageIds;
private Dictionary<string, List<RuntimePackAssetInfo>> _runtimePackAssets;
private CompilationOptions _compilationOptions;
private string _referenceAssembliesPath;
Expand Down Expand Up @@ -204,6 +205,12 @@ public DependencyContextBuilder WithReferenceProjectInfos(Dictionary<string, Sin
return this;
}

public DependencyContextBuilder WithExcludeFromPublishAssets(IEnumerable<string> excludeFromPublishPackageIds)
{
_excludeFromPublishPackageIds = excludeFromPublishPackageIds;
return this;
}

public DependencyContextBuilder WithMainProjectInDepsFile(bool includeMainProjectInDepsFile)
{
_includeMainProjectInDepsFile = includeMainProjectInDepsFile;
Expand Down Expand Up @@ -814,6 +821,37 @@ private void CalculateExcludedLibraries()
{
_dependencyLibraries[packageToExcludeFromRuntime].ExcludeFromRuntime = true;
}

// Include transitive dependencies of all top-level dependencies
Dictionary<string, DependencyLibrary> includedDependencies = new(StringComparer.OrdinalIgnoreCase);
Stack<string> dependencyListToWalk = new(_mainProjectDependencies);

while (dependencyListToWalk.Count != 0)
{
var dependencyName = dependencyListToWalk.Pop();
// There may not be a library in the assets file if a referenced project has
// PrivateAssets="all" for a package reference, and there is a package in the graph
// that depends on the same package.
if (!includedDependencies.ContainsKey(dependencyName) &&
_excludeFromPublishPackageIds?.Contains(dependencyName) != true &&
_dependencyLibraries.TryGetValue(dependencyName, out var dependencyLibrary))
{
includedDependencies.Add(dependencyName, dependencyLibrary);
foreach (var newDependency in _libraryDependencies[dependencyName])
{
dependencyListToWalk.Push(newDependency.Name);
}
}
}

foreach (var dependencyLibrary in _dependencyLibraries.Values)
{
if (!includedDependencies.ContainsKey(dependencyLibrary.Name))
{
dependencyLibrary.ExcludeFromCompilation = true;
dependencyLibrary.ExcludeFromRuntime = true;
}
}
}

private string GetReferenceLibraryName(ReferenceInfo reference)
Expand Down
3 changes: 3 additions & 0 deletions src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public class GenerateDepsFile : TaskBase

public ITaskItem CompilerOptions { get; set; }

public ITaskItem[] ExcludeFromPublishPackageReferences { get; set; } = Array.Empty<ITaskItem>();

public ITaskItem[] RuntimeStorePackages { get; set; }

// NuGet compilation assets
Expand Down Expand Up @@ -232,6 +234,7 @@ bool ShouldIncludeRuntimeAsset(ITaskItem item)
.WithDirectReferences(directReferences)
.WithDependencyReferences(dependencyReferences)
.WithReferenceProjectInfos(referenceProjects)
.WithExcludeFromPublishAssets(PackageReferenceConverter.GetPackageIds(ExcludeFromPublishPackageReferences))
.WithRuntimePackAssets(runtimePackAssets)
.WithCompilationOptions(compilationOptions)
.WithReferenceAssembliesPath(FrameworkReferenceResolver.GetDefaultReferenceAssembliesPath())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,7 @@ Copyright (c) .NET Foundation. All rights reserved.
PlatformLibraryName="$(MicrosoftNETPlatformLibrary)"
RuntimeFrameworks="@(RuntimeFramework)"
CompilerOptions="@(DependencyFileCompilerOptions)"
ExcludeFromPublishPackageReferences="@(_ExcludeFromPublishPackageReference)"
RuntimeStorePackages="@(RuntimeStorePackages)"
CompileReferences="@(ResolvedCompileFileDefinitions)"
ResolvedNuGetFiles="@(_ResolvedNuGetFilesForPublish)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ Copyright (c) .NET Foundation. All rights reserved.
PlatformLibraryName="$(MicrosoftNETPlatformLibrary)"
RuntimeFrameworks="@(RuntimeFramework)"
CompilerOptions="@(DependencyFileCompilerOptions)"
ExcludeFromPublishPackageReferences="@(_ExcludeFromPublishPackageReference)"
CompileReferences="@(ResolvedCompileFileDefinitions)"
ResolvedNuGetFiles="@(NativeCopyLocalItems);@(ResourceCopyLocalItems);@(RuntimeCopyLocalItems)"
UserRuntimeAssemblies="@(UserRuntimeAssembly)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,32 @@ public void It_can_preserve_compilation_context_and_reference_netstandard_librar
}
}

[Theory]
[InlineData("RazorSimpleMvc22", "netcoreapp2.2", "SimpleMvc22")]
[InlineData("DesktopReferencingNetStandardLibrary", "net46", "Library")]
public void PackageReferences_with_private_assets_do_not_appear_in_deps_file(string asset, string targetFramework, string exeName)
{
var testAsset = _testAssetsManager
.CopyTestAsset(asset)
.WithSource();

var buildCommand = new BuildCommand(testAsset);
buildCommand.Execute().Should().Pass();

using (var depsJsonFileStream = File.OpenRead(Path.Combine(buildCommand.GetOutputDirectory(targetFramework).FullName, exeName + ".deps.json")))
{
var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream);
if (asset.Equals("DesktopReferencingNetStandardLibrary"))
{
dependencyContext.CompileLibraries.Any(l => l.Name.Equals("Library")).Should().BeTrue();
}
else
{
dependencyContext.CompileLibraries.Any(l => l.Name.Equals("Microsoft.AspNetCore.App")).Should().BeFalse();
}
}
}

[WindowsOnlyFact]
public void It_resolves_assembly_conflicts_with_a_NETFramework_library()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,18 @@ public void Build_ProducesDepsFileWithCompilationContext_ButNoReferences()
depsFile.Should().Exist();
var dependencyContext = ReadDependencyContext(depsFile.FullName);

// Ensure some compile references exist
var packageReference = dependencyContext.CompileLibraries.First(l => l.Name == "System.Runtime.CompilerServices.Unsafe");
packageReference.Assemblies.Should().NotBeEmpty();
if (TargetFramework.Equals("netcoreapp2.2"))
{
// Ensure compile references from a PrivateAssets="all" PackageReference don't exist
var packageReference = dependencyContext.CompileLibraries.FirstOrDefault(l => l.Name == "System.Runtime.CompilerServices.Unsafe", defaultValue: null);
packageReference.Should().BeNull();
}
else
{
// Ensure some compile references exist
var packageReference = dependencyContext.CompileLibraries.First(l => l.Name == "System.Runtime.CompilerServices.Unsafe");
packageReference.Assemblies.Should().NotBeEmpty();
}

var projectReference = dependencyContext.CompileLibraries.First(l => l.Name == TestProjectName);
projectReference.Assemblies.Should().NotBeEmpty();
Expand Down
Loading

0 comments on commit f2a8a80

Please sign in to comment.