Skip to content

Commit

Permalink
[automated] Merge branch 'release/9.0.1xx' => 'release/9.0.2xx' (#43759)
Browse files Browse the repository at this point in the history
  • Loading branch information
v-wuzhai authored Sep 29, 2024
2 parents bebdad0 + 014b168 commit a87c170
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Runtime.Versioning;
using Microsoft.Deployment.DotNet.Releases;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ToolPackage;
using Microsoft.DotNet.Workloads.Workload.Install;
using Microsoft.DotNet.Workloads.Workload.List;
using Microsoft.NET.Sdk.WorkloadManifestReader;
Expand Down Expand Up @@ -33,19 +32,61 @@ internal static class VisualStudioWorkloads
"Microsoft.VisualStudio.Product.Enterprise",
};

/// <summary>
/// Default prefix to use for Visual Studio component and component group IDs.
/// </summary>
private static readonly string s_visualStudioComponentPrefix = "Microsoft.NET.Component";

/// <summary>
/// Well-known prefixes used by some workloads that can be replaced when generating component IDs.
/// </summary>
private static readonly string[] s_wellKnownWorkloadPrefixes = { "Microsoft.NET.", "Microsoft." };

/// <summary>
/// The SWIX package ID wrapping the SDK installer in Visual Studio. The ID should contain
/// the SDK version as a suffix, e.g., "Microsoft.NetCore.Toolset.5.0.403".
/// </summary>
private static readonly string s_visualStudioSdkPackageIdPrefix = "Microsoft.NetCore.Toolset.";

/// <summary>
/// Gets a set of workload components based on the available set of workloads for the current SDK.
/// Gets a dictionary of mapping possible Visual Studio component IDs to .NET workload IDs in the current SDK.
/// </summary>
/// <param name="workloadResolver">The workload resolver used to obtain available workloads.</param>
/// <returns>A collection of Visual Studio component IDs corresponding to workload IDs.</returns>
internal static IEnumerable<string> GetAvailableVisualStudioWorkloads(IWorkloadResolver workloadResolver) =>
workloadResolver.GetAvailableWorkloads().Select(w => w.Id.ToString().Replace('-', '.'));
/// <returns>A dictionary of Visual Studio component IDs corresponding to workload IDs.</returns>
internal static Dictionary<string, string> GetAvailableVisualStudioWorkloads(IWorkloadResolver workloadResolver)
{
Dictionary<string, string> visualStudioComponentWorkloads = new(StringComparer.OrdinalIgnoreCase);

// Iterate through all the available workload IDs and generate potential Visual Studio
// component IDs that map back to the original workload ID. This ensures that we
// can do reverse lookups for special cases where a workload ID contains a prefix
// corresponding with the full VS component ID prefix. For example,
// Microsoft.NET.Component.runtime.android would be a valid component ID for both
// microsoft-net-runtime-android and runtime-android.
foreach (var workload in workloadResolver.GetAvailableWorkloads())
{
string workloadId = workload.Id.ToString();
// Old style VS components simply replaced '-' with '.' in the workload ID.
string componentId = workload.Id.ToString().Replace('-', '.');

visualStudioComponentWorkloads.Add(componentId, workloadId);

// Starting in .NET 9.0 and VS 17.12, workload components will follow the VS naming convention.
foreach (string wellKnownPrefix in s_wellKnownWorkloadPrefixes)
{
if (componentId.StartsWith(wellKnownPrefix, StringComparison.OrdinalIgnoreCase))
{
componentId = componentId.Substring(wellKnownPrefix.Length);
break;
}
}

componentId = s_visualStudioComponentPrefix + "." + componentId;
visualStudioComponentWorkloads.Add(componentId, workloadId);
}

return visualStudioComponentWorkloads;
}

/// <summary>
/// Finds all workloads installed by all Visual Studio instances given that the
Expand All @@ -59,7 +100,7 @@ internal static IEnumerable<string> GetAvailableVisualStudioWorkloads(IWorkloadR
internal static void GetInstalledWorkloads(IWorkloadResolver workloadResolver,
InstalledWorkloadsCollection installedWorkloads, SdkFeatureBand? sdkFeatureBand = null)
{
IEnumerable<string> visualStudioWorkloadIds = GetAvailableVisualStudioWorkloads(workloadResolver);
Dictionary<string, string> visualStudioWorkloadIds = GetAvailableVisualStudioWorkloads(workloadResolver);
HashSet<string> installedWorkloadComponents = new();

// Visual Studio instances contain a large set of packages and we have to perform a linear
Expand Down Expand Up @@ -105,10 +146,9 @@ internal static void GetInstalledWorkloads(IWorkloadResolver workloadResolver,
continue;
}

if (visualStudioWorkloadIds.Contains(packageId, StringComparer.OrdinalIgnoreCase))
if (visualStudioWorkloadIds.TryGetValue(packageId, out string workloadId))
{
// Normalize back to an SDK style workload ID.
installedWorkloadComponents.Add(packageId.Replace('.', '-'));
installedWorkloadComponents.Add(workloadId);
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/Installer/finalizer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,15 @@ add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/we4703>) # Potentially uninitia
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/we4789>) # destination of memory copy is too small
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/we4995>) # 'function': name was marked as #pragma deprecated
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/we4996>) # 'function': was declared deprecated also 'std::'
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/guard:cf>) # Enable control flow guard

add_executable(Finalizer
finalizer.cpp
native.rc
)

add_link_options(/guard:cf)

# These are normally part of a .vcxproj in Visual Studio, but appears to be missing when CMAKE generates a .vcxproj for arm64.
target_link_libraries(Finalizer shell32.lib)
target_link_libraries(Finalizer advapi32.lib)
Expand Down
13 changes: 13 additions & 0 deletions test/dotnet-workload-list.Tests/GivenDotnetWorkloadList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.CommandLine;
using ManifestReaderTests;
using Microsoft.DotNet.Workloads.Workload;
using Microsoft.DotNet.Workloads.Workload.List;
using Microsoft.NET.Sdk.WorkloadManifestReader;
using ListStrings = Microsoft.DotNet.Workloads.Workload.List.LocalizableStrings;
Expand Down Expand Up @@ -37,6 +38,18 @@ public void GivenNoWorkloadsAreInstalledListIsEmpty()
_reporter.Lines.Count.Should().Be(6);
}

[WindowsOnlyFact]
public void GivenAvailableWorkloadsItCanComputeVisualStudioIds()
{
var workloadResolver = WorkloadResolver.CreateForTests(new MockManifestProvider(("SampleManifest", _manifestPath, "5.0.0", "6.0.100")), Directory.GetCurrentDirectory());

#pragma warning disable CA1416 // Validate platform compatibility
var availableWorkloads = VisualStudioWorkloads.GetAvailableVisualStudioWorkloads(workloadResolver);
availableWorkloads.Should().Contain("mock.workload.1", "mock-workload-1");
availableWorkloads.Should().Contain("Microsoft.NET.Component.mock.workload.1", "mock-workload-1");
#pragma warning restore CA1416 // Validate platform compatibility
}

[Fact]
public void GivenNoWorkloadsAreInstalledMachineReadableListIsEmpty()
{
Expand Down

0 comments on commit a87c170

Please sign in to comment.