Skip to content

Commit 7ed3250

Browse files
authored
Use alias in BuildIntegratedInstallationContext, allowing aliased package installation and updating to work (#7102)
1 parent 03b0504 commit 7ed3250

16 files changed

Lines changed: 626 additions & 223 deletions

File tree

src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/GlobalSuppressions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'LegacyPackageReferenceProject.LegacyPackageReferenceProject(IVsProjectAdapter vsProjectAdapter, string projectId, INuGetProjectServices projectServices, IVsProjectThreadingService threadingService)', validate parameter 'vsProjectAdapter' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.#ctor(NuGet.VisualStudio.IVsProjectAdapter,System.String,NuGet.ProjectManagement.INuGetProjectServices,NuGet.PackageManagement.VisualStudio.IVsProjectThreadingService)")]
3333
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task LegacyPackageReferenceProject.AddFileToProjectAsync(string filePath)', validate parameter 'filePath' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.AddFileToProjectAsync(System.String)~System.Threading.Tasks.Task")]
3434
[assembly: SuppressMessage("Build", "CA1822:Member GetConfigFilePaths does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.GetConfigFilePaths(NuGet.Configuration.ISettings)~System.Collections.Generic.IList{System.String}")]
35-
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task<bool> LegacyPackageReferenceProject.InstallPackageAsync(string packageId, VersionRange range, INuGetProjectContext _, BuildIntegratedInstallationContext __, CancellationToken token)', validate parameter '__' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.InstallPackageAsync(System.String,NuGet.Versioning.VersionRange,NuGet.ProjectManagement.INuGetProjectContext,NuGet.ProjectManagement.BuildIntegratedInstallationContext,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Boolean}")]
3635
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'Task<bool> LegacyPackageReferenceProject.UninstallPackageAsync(PackageIdentity packageIdentity, INuGetProjectContext _, CancellationToken token)', validate parameter 'packageIdentity' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProject.UninstallPackageAsync(NuGet.Packaging.Core.PackageIdentity,NuGet.ProjectManagement.INuGetProjectContext,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Boolean}")]
3736
[assembly: SuppressMessage("Build", "CA1062:In externally visible method 'NuGetProject LegacyPackageReferenceProjectProvider.TryCreateNuGetProject(IVsProjectAdapter vsProjectAdapter, ProjectProviderContext context, bool forceProjectType)', validate parameter 'vsProjectAdapter' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.LegacyPackageReferenceProjectProvider.TryCreateNuGetProject(NuGet.VisualStudio.IVsProjectAdapter,NuGet.PackageManagement.VisualStudio.ProjectProviderContext,System.Boolean)~NuGet.ProjectManagement.NuGetProject")]
3837
[assembly: SuppressMessage("Build", "CA1031:Modify 'GetAssemblyReferences' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "<Pending>", Scope = "member", Target = "~M:NuGet.PackageManagement.VisualStudio.MicrosoftBuildEvaluationProjectUtility.GetAssemblyReferences(Microsoft.Build.Evaluation.Project)~System.Collections.Generic.IEnumerable{System.Tuple{Microsoft.Build.Evaluation.ProjectItem,System.Reflection.AssemblyName}}")]

src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/CpsPackageReferenceProject.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,8 @@ public override async Task<bool> InstallPackageAsync(
282282
ProjectFullPath));
283283
}
284284

285-
foreach (var framework in installationContext.SuccessfulFrameworks)
285+
foreach (var originalFramework in installationContext.SuccessfulFrameworks)
286286
{
287-
string originalFramework;
288-
if (!installationContext.OriginalFrameworks.TryGetValue(framework, out originalFramework))
289-
{
290-
originalFramework = framework.GetShortFolderName();
291-
}
292-
293287
var reference = await conditionalService.AddAsync(
294288
packageId,
295289
formattedRange,
@@ -386,13 +380,8 @@ public override async Task<bool> UninstallPackageAsync(string packageId, BuildIn
386380
ProjectFullPath));
387381
}
388382

389-
foreach (var framework in installationContext.SuccessfulFrameworks)
383+
foreach (var originalFramework in installationContext.SuccessfulFrameworks)
390384
{
391-
string originalFramework;
392-
if (!installationContext.OriginalFrameworks.TryGetValue(framework, out originalFramework))
393-
{
394-
originalFramework = framework.GetShortFolderName();
395-
}
396385
await conditionalService.RemoveAsync(packageId, TargetFrameworkCondition, originalFramework);
397386
}
398387
}

src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Projects/LegacyPackageReferenceProject.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,17 +233,21 @@ public override async Task<bool> InstallPackageAsync(
233233
string packageId,
234234
VersionRange range,
235235
INuGetProjectContext _,
236-
BuildIntegratedInstallationContext __,
236+
BuildIntegratedInstallationContext context,
237237
CancellationToken token)
238238
{
239+
if (string.IsNullOrEmpty(packageId)) throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.Argument_Cannot_Be_Null_Or_Empty, nameof(packageId)));
240+
if (range == null) throw new ArgumentNullException(nameof(range));
241+
if (context == null) throw new ArgumentNullException(nameof(context));
242+
239243
var dependency = new LibraryDependency()
240244
{
241245
LibraryRange = new LibraryRange(
242246
name: packageId,
243247
versionRange: range,
244248
typeConstraint: LibraryDependencyTarget.Package),
245-
SuppressParent = __.SuppressParent,
246-
IncludeType = __.IncludeType
249+
SuppressParent = context.SuppressParent,
250+
IncludeType = context.IncludeType
247251
};
248252

249253
await ProjectServices.References.AddOrUpdatePackageReferenceAsync(dependency, token);

src/NuGet.Core/NuGet.PackageManagement/BuildIntegratedInstallationContext.cs

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
#nullable disable
5-
64
using System.Collections.Generic;
7-
using NuGet.Frameworks;
85
using NuGet.LibraryModel;
96
using NuGet.ProjectManagement.Projects;
107

@@ -15,49 +12,24 @@ namespace NuGet.ProjectManagement
1512
/// </summary>
1613
public class BuildIntegratedInstallationContext
1714
{
18-
public BuildIntegratedInstallationContext(
19-
IEnumerable<NuGetFramework> successfulFrameworks,
20-
IEnumerable<NuGetFramework> unsucessfulFrameworks,
21-
IDictionary<NuGetFramework, string> originalFrameworks,
22-
bool areAllPackagesConditional)
23-
{
24-
SuccessfulFrameworks = successfulFrameworks;
25-
UnsuccessfulFrameworks = unsucessfulFrameworks;
26-
OriginalFrameworks = originalFrameworks;
27-
AreAllPackagesConditional = areAllPackagesConditional;
28-
}
29-
30-
public BuildIntegratedInstallationContext(
31-
IEnumerable<NuGetFramework> successfulFrameworks,
32-
IEnumerable<NuGetFramework> unsucessfulFrameworks,
33-
IDictionary<NuGetFramework, string> originalFrameworks)
34-
: this(successfulFrameworks, unsucessfulFrameworks, originalFrameworks, areAllPackagesConditional: false)
35-
{ }
36-
3715
/// <summary>
3816
/// Shows the frameworks for which a preview restore operation was successful. Only use it
3917
/// in case of single package install case, and only for CpsPackageReference projects.
4018
/// </summary>
41-
public IEnumerable<NuGetFramework> SuccessfulFrameworks { get; }
19+
public required List<string> SuccessfulFrameworks { get; init; }
4220

4321
/// <summary>
4422
/// Shows the frameworks for which a preview restore operation was unsuccessful. Only use it
4523
/// in case of single package install case, and only for CpsPackageReference projects.
4624
/// </summary>
47-
public IEnumerable<NuGetFramework> UnsuccessfulFrameworks { get; }
48-
49-
/// <summary>
50-
/// A mapping to allow the original framework string to fetched. This is important because MSBuild target
51-
/// framework evaluation depends on the target framework string matching exactly.
52-
/// </summary>
53-
public IDictionary<NuGetFramework, string> OriginalFrameworks { get; }
25+
public required List<string> UnsuccessfulFrameworks { get; init; }
5426

5527
/// <summary>
5628
/// Indicates that all packages are suspected to be conditionally installed. In particular, a package is installed to all frameworks, but it is expected to use the conditional updating/unisntalling APIs.
5729
/// Indicators of packages being conditional is that a package contains different versions in different frameworks.
5830
/// This value is only relevant when <see cref="UnsuccessfulFrameworks"/> is empty, and <see cref="SuccessfulFrameworks"/> contains all frameworks.
5931
/// </summary>
60-
public bool AreAllPackagesConditional { get; }
32+
public bool AreAllPackagesConditional { get; init; }
6133

6234
/// <summary>
6335
/// Define transitive behavior for each package dependency for the current project.

src/NuGet.Core/NuGet.PackageManagement/NuGet.PackageManagement.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
<Compile Include="$(SharedDirectory)\SharedExtensions.cs" />
5555
<Compile Include="$(SharedDirectory)\TaskResult.cs" />
5656
<Compile Include="$(SharedDirectory)\XmlUtility.cs" />
57+
<Compile Include="$(SharedDirectory)\IsExternalInit.cs" />
58+
<Compile Include="$(SharedDirectory)\RequiredModifierAttributes.cs" />
5759
</ItemGroup>
5860

5961
<ItemGroup>

src/NuGet.Core/NuGet.PackageManagement/NuGetPackageManager.cs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3077,14 +3077,10 @@ internal async Task<IEnumerable<ResolvedAction>> PreviewBuildIntegratedProjectsA
30773077
.Result
30783078
.CompatibilityCheckResults
30793079
.Where(t => !t.Success)
3080-
.Select(t => t.Graph.Framework)
3080+
.Select(t => t.Graph.TargetAlias ?? string.Empty)
30813081
.Distinct()
30823082
.ToList();
30833083

3084-
var originalFrameworks = updatedPackageSpec
3085-
.TargetFrameworks
3086-
.ToDictionary(x => x.FrameworkName, x => x.TargetAlias);
3087-
30883084
List<(NuGetProjectAction, BuildIntegratedInstallationContext)> projectActionsAndInstallationContexts = new(nuGetProjectActions.Length);
30893085

30903086
foreach (var action in nuGetProjectActions)
@@ -3096,7 +3092,7 @@ internal async Task<IEnumerable<ResolvedAction>> PreviewBuildIntegratedProjectsA
30963092
NuGetProjectActionType.Uninstall => originalPackageSpec,
30973093
_ => throw new InvalidOperationException("Unknown NuGetProjectActionType"),
30983094
};
3099-
BuildIntegratedInstallationContext installationContext = CreateInstallationContextForPackageId(action.PackageIdentity.Id, referencePackageSpec, originalPackageSpec, unsuccessfulFrameworks, originalFrameworks);
3095+
BuildIntegratedInstallationContext installationContext = CreateInstallationContextForPackageId(action.PackageIdentity.Id, referencePackageSpec, originalPackageSpec, unsuccessfulFrameworks);
31003096
projectActionsAndInstallationContexts.Add((action, installationContext));
31013097
}
31023098

@@ -3190,18 +3186,18 @@ internal async Task<IEnumerable<ResolvedAction>> PreviewBuildIntegratedProjectsA
31903186
/// The "successful" frameworks are the ones that contain the package and are not part of the failed list.
31913187
/// The "unsuccessful" frameworks are the ones that never had the package or are part of the unsuccessful list.
31923188
/// </summary>>
3193-
internal static BuildIntegratedInstallationContext CreateInstallationContextForPackageId(string packageIdentityId, PackageSpec packageSpec, PackageSpec originalPackageSpec, List<NuGetFramework> unsuccessfulFrameworks, Dictionary<NuGetFramework, string> originalFrameworks)
3189+
internal static BuildIntegratedInstallationContext CreateInstallationContextForPackageId(string packageIdentityId, PackageSpec packageSpec, PackageSpec originalPackageSpec, List<string> unsuccessfulFrameworks)
31943190
{
31953191
var frameworksWithResultingPackage = packageSpec
31963192
.TargetFrameworks
31973193
.Where(e => e.Dependencies.Any(a => string.Equals(a.Name, packageIdentityId, StringComparison.OrdinalIgnoreCase)))
3198-
.Select(e => e.FrameworkName)
3194+
.Select(e => e.TargetAlias ?? string.Empty)
31993195
.Distinct();
32003196

32013197
var frameworksWithoutResultingPackage = packageSpec
32023198
.TargetFrameworks
32033199
.Where(e => !e.Dependencies.Any(a => string.Equals(a.Name, packageIdentityId, StringComparison.OrdinalIgnoreCase)))
3204-
.Select(e => e.FrameworkName)
3200+
.Select(e => e.TargetAlias ?? string.Empty)
32053201
.Distinct();
32063202

32073203
var successfulFrameworksWithPackage = frameworksWithResultingPackage
@@ -3210,11 +3206,12 @@ internal static BuildIntegratedInstallationContext CreateInstallationContextForP
32103206

32113207
var areAllPackagesConditional = DoesPackageAppearWithDifferentVersions(packageIdentityId, originalPackageSpec);
32123208

3213-
return new BuildIntegratedInstallationContext(
3214-
successfulFrameworksWithPackage,
3215-
unsuccessfulFrameworks.Union(frameworksWithoutResultingPackage).Distinct(),
3216-
originalFrameworks,
3217-
areAllPackagesConditional);
3209+
return new BuildIntegratedInstallationContext()
3210+
{
3211+
SuccessfulFrameworks = successfulFrameworksWithPackage,
3212+
UnsuccessfulFrameworks = unsuccessfulFrameworks.Union(frameworksWithoutResultingPackage).Distinct().ToList(),
3213+
AreAllPackagesConditional = areAllPackagesConditional
3214+
};
32183215
}
32193216

32203217
private static bool DoesPackageAppearWithDifferentVersions(string packageIdentityId, PackageSpec packageSpec)
@@ -3335,7 +3332,11 @@ public async Task ExecuteBuildIntegratedProjectActionsAsync(
33353332
originalAction.PackageIdentity);
33363333

33373334
var framework = installationContext.SuccessfulFrameworks.First();
3338-
var resolvedAction = projectAction.RestoreResult.LockFile.PackageSpec.TargetFrameworks.FirstOrDefault(fm => fm.FrameworkName.Equals(framework))
3335+
3336+
TargetFrameworkInformation matchingTfi = projectAction.RestoreResult.LockFile.PackageSpec.TargetFrameworks.Count == 1 ?
3337+
projectAction.RestoreResult.LockFile.PackageSpec.TargetFrameworks[0] :
3338+
projectAction.RestoreResult.LockFile.PackageSpec.TargetFrameworks.FirstOrDefault(fm => fm.TargetAlias.Equals(framework));
3339+
var resolvedAction = matchingTfi
33393340
.Dependencies.First(dependency => dependency.Name.Equals(originalAction.PackageIdentity.Id, StringComparison.OrdinalIgnoreCase));
33403341

33413342
installationContext.SuppressParent = resolvedAction.SuppressParent;

src/NuGet.Core/NuGet.PackageManagement/PublicAPI.Shipped.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -368,15 +368,10 @@ NuGet.PackageManagement.VersionConstraints.ExactRelease = 8 -> NuGet.PackageMana
368368
NuGet.PackageManagement.VersionConstraints.None = 0 -> NuGet.PackageManagement.VersionConstraints
369369
NuGet.ProjectManagement.BuildIntegratedInstallationContext
370370
NuGet.ProjectManagement.BuildIntegratedInstallationContext.AreAllPackagesConditional.get -> bool
371-
~NuGet.ProjectManagement.BuildIntegratedInstallationContext.BuildIntegratedInstallationContext(System.Collections.Generic.IEnumerable<NuGet.Frameworks.NuGetFramework> successfulFrameworks, System.Collections.Generic.IEnumerable<NuGet.Frameworks.NuGetFramework> unsucessfulFrameworks, System.Collections.Generic.IDictionary<NuGet.Frameworks.NuGetFramework, string> originalFrameworks) -> void
372-
~NuGet.ProjectManagement.BuildIntegratedInstallationContext.BuildIntegratedInstallationContext(System.Collections.Generic.IEnumerable<NuGet.Frameworks.NuGetFramework> successfulFrameworks, System.Collections.Generic.IEnumerable<NuGet.Frameworks.NuGetFramework> unsucessfulFrameworks, System.Collections.Generic.IDictionary<NuGet.Frameworks.NuGetFramework, string> originalFrameworks, bool areAllPackagesConditional) -> void
373371
NuGet.ProjectManagement.BuildIntegratedInstallationContext.IncludeType.get -> NuGet.LibraryModel.LibraryIncludeFlags
374372
NuGet.ProjectManagement.BuildIntegratedInstallationContext.IncludeType.set -> void
375-
~NuGet.ProjectManagement.BuildIntegratedInstallationContext.OriginalFrameworks.get -> System.Collections.Generic.IDictionary<NuGet.Frameworks.NuGetFramework, string>
376-
~NuGet.ProjectManagement.BuildIntegratedInstallationContext.SuccessfulFrameworks.get -> System.Collections.Generic.IEnumerable<NuGet.Frameworks.NuGetFramework>
377373
NuGet.ProjectManagement.BuildIntegratedInstallationContext.SuppressParent.get -> NuGet.LibraryModel.LibraryIncludeFlags
378374
NuGet.ProjectManagement.BuildIntegratedInstallationContext.SuppressParent.set -> void
379-
~NuGet.ProjectManagement.BuildIntegratedInstallationContext.UnsuccessfulFrameworks.get -> System.Collections.Generic.IEnumerable<NuGet.Frameworks.NuGetFramework>
380375
NuGet.ProjectManagement.BuildIntegratedPackageReference
381376
~NuGet.ProjectManagement.BuildIntegratedPackageReference.BuildIntegratedPackageReference(NuGet.LibraryModel.LibraryDependency dependency, NuGet.Frameworks.NuGetFramework projectFramework) -> void
382377
~NuGet.ProjectManagement.BuildIntegratedPackageReference.BuildIntegratedPackageReference(NuGet.LibraryModel.LibraryDependency dependency, NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Packaging.Core.PackageIdentity installedVersion) -> void
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
#nullable enable
2+
NuGet.ProjectManagement.BuildIntegratedInstallationContext.AreAllPackagesConditional.init -> void
3+
NuGet.ProjectManagement.BuildIntegratedInstallationContext.BuildIntegratedInstallationContext() -> void
4+
NuGet.ProjectManagement.BuildIntegratedInstallationContext.SuccessfulFrameworks.get -> System.Collections.Generic.List<string!>!
5+
NuGet.ProjectManagement.BuildIntegratedInstallationContext.SuccessfulFrameworks.init -> void
6+
NuGet.ProjectManagement.BuildIntegratedInstallationContext.UnsuccessfulFrameworks.get -> System.Collections.Generic.List<string!>!
7+
NuGet.ProjectManagement.BuildIntegratedInstallationContext.UnsuccessfulFrameworks.init -> void

0 commit comments

Comments
 (0)