Skip to content

Commit

Permalink
support in nugetframework for net5.0 tfm
Browse files Browse the repository at this point in the history
Fixes: NuGet/Home#9089

support in nugetframework for net5.0.
Generally treated as netcoreapp5.0, except with a shortfoldername of net5.0

Spec: https://github.com/terrajobst/designs/blob/net5/accepted/2020/net5/net5.md
PR to merge into main design repo: dotnet/designs#92

Additional follow up work coming later:
- support for net5.0-ios14 or similar (and android, win, macos, etc..): NuGet/Home#9240
- some clean up given additional PR feedback: NuGet/Home#9260
  • Loading branch information
Rob Relyea authored Mar 5, 2020
1 parent 94300e1 commit 162e235
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public LockFile CreateLockFile(LockFile previousLockFile,
// Check if warnings should be displayed for the current framework.
var tfi = project.GetTargetFramework(targetGraph.Framework);

var warnForImportsOnGraph = tfi.Warn
bool warnForImportsOnGraph = tfi.Warn
&& (target.TargetFramework is FallbackFramework
|| target.TargetFramework is AssetTargetFallbackFramework);

Expand Down Expand Up @@ -398,4 +398,4 @@ private static bool HasTools(string file)
return file.StartsWith("tools/", StringComparison.OrdinalIgnoreCase);
}
}
}
}
22 changes: 15 additions & 7 deletions src/NuGet.Core/NuGet.Frameworks/CompatibilityProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
Expand All @@ -17,7 +17,7 @@ class CompatibilityProvider : IFrameworkCompatibilityProvider
{
private readonly IFrameworkNameProvider _mappings;
private readonly FrameworkExpander _expander;
private static readonly NuGetFrameworkFullComparer _fullComparer = new NuGetFrameworkFullComparer();
private static readonly NuGetFrameworkFullComparer FullComparer = new NuGetFrameworkFullComparer();
private readonly ConcurrentDictionary<CompatibilityCacheKey, bool> _cache;

public CompatibilityProvider(IFrameworkNameProvider mappings)
Expand Down Expand Up @@ -62,7 +62,7 @@ public bool IsCompatible(NuGetFramework target, NuGetFramework candidate)
bool? result = null;

// check if they are the exact same
if (_fullComparer.Equals(target, candidate))
if (FullComparer.Equals(target, candidate))
{
return true;
}
Expand Down Expand Up @@ -181,10 +181,18 @@ private bool IsCompatibleWithTarget(NuGetFramework target, NuGetFramework candid

private static bool IsCompatibleWithTargetCore(NuGetFramework target, NuGetFramework candidate)
{
// compare the frameworks
return (NuGetFramework.FrameworkNameComparer.Equals(target, candidate)
&& StringComparer.OrdinalIgnoreCase.Equals(target.Profile, candidate.Profile)
&& IsVersionCompatible(target.Version, candidate.Version));
if (target.IsNet5Era)
{
return NuGetFramework.FrameworkNameComparer.Equals(target, candidate)
&& IsVersionCompatible(target.Version, candidate.Version)
&& (!candidate.HasProfile || StringComparer.OrdinalIgnoreCase.Equals(target.Profile, candidate.Profile));
}
else
{
return NuGetFramework.FrameworkNameComparer.Equals(target, candidate)
&& IsVersionCompatible(target.Version, candidate.Version)
&& StringComparer.OrdinalIgnoreCase.Equals(target.Profile, candidate.Profile);
}
}

private static bool IsVersionCompatible(Version target, Version candidate)
Expand Down
16 changes: 14 additions & 2 deletions src/NuGet.Core/NuGet.Frameworks/FrameworkConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;

namespace NuGet.Frameworks
{
Expand All @@ -13,7 +14,7 @@ namespace NuGet.Frameworks
static class FrameworkConstants
{
public static readonly Version EmptyVersion = new Version(0, 0, 0, 0);
public static readonly Version MaxVersion = new Version(Int32.MaxValue, 0, 0, 0);
public static readonly Version MaxVersion = new Version(int.MaxValue, 0, 0, 0);
public static readonly Version Version5 = new Version(5, 0, 0, 0);
public static readonly Version Version10 = new Version(10, 0, 0, 0);
public static readonly FrameworkRange DotNetAll = new FrameworkRange(
Expand All @@ -33,6 +34,13 @@ public static class PlatformIdentifiers
public const string Windows = "Windows";
}

/// <summary>
/// Allowed list of profiles in Net5.0ERA
/// </summary>
internal static HashSet<string> FrameworkProfiles
= new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{ };

public static class FrameworkIdentifiers
{
public const string NetCoreApp = ".NETCoreApp";
Expand Down Expand Up @@ -180,6 +188,10 @@ public static readonly NuGetFramework NetCoreApp22
public static readonly NuGetFramework NetCoreApp30
= new NuGetFramework(FrameworkIdentifiers.NetCoreApp, new Version(3, 0, 0, 0));
public static readonly NuGetFramework NetCoreApp31
= new NuGetFramework(FrameworkIdentifiers.NetCoreApp, new Version(3, 1, 0, 0)); }
= new NuGetFramework(FrameworkIdentifiers.NetCoreApp, new Version(3, 1, 0, 0));

// .NET 5.0 and later has NetCoreApp identifier
public static readonly NuGetFramework Net50 = new NuGetFramework(FrameworkIdentifiers.NetCoreApp, Version5);
}
}
}
22 changes: 7 additions & 15 deletions src/NuGet.Core/NuGet.Frameworks/FrameworkNameProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
Expand Down Expand Up @@ -138,7 +138,7 @@ public bool TryGetVersion(string versionString, out Version version)
{
version = null;

if (String.IsNullOrEmpty(versionString))
if (string.IsNullOrEmpty(versionString))
{
version = new Version(0, 0);
}
Expand All @@ -160,7 +160,7 @@ public bool TryGetVersion(string versionString, out Version version)
// take only the first 4 digits and add dots
// 451 -> 4.5.1
// 81233 -> 8123
return Version.TryParse(String.Join(".", versionString.ToCharArray().Take(4)), out version);
return Version.TryParse(string.Join(".", versionString.ToCharArray().Take(4)), out version);
}
}

Expand All @@ -185,7 +185,7 @@ public string GetVersionString(string framework, Version version)
versionParts.Push(version.Revision > 0 ? version.Revision : 0);

// By default require the version to have 2 digits, for legacy frameworks 1 is allowed
var minPartCount = _singleDigitVersionFrameworks.Contains(framework) ? 1 : 2;
var minPartCount = SingleDigitVersionFrameworks.Contains(framework) ? 1 : 2;

// remove all trailing zeros beyond the minor version
while ((versionParts.Count > minPartCount
Expand All @@ -198,20 +198,12 @@ public string GetVersionString(string framework, Version version)
// netcoreapp, or if any parts of the version are over 9 we need to use decimals
if (string.Equals(
framework,
FrameworkConstants.FrameworkIdentifiers.NetPlatform,
FrameworkConstants.FrameworkIdentifiers.NetCoreApp,
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
framework,
FrameworkConstants.FrameworkIdentifiers.NetStandard,
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
framework,
FrameworkConstants.FrameworkIdentifiers.NetStandardApp,
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
framework,
FrameworkConstants.FrameworkIdentifiers.NetCoreApp,
StringComparison.OrdinalIgnoreCase)
|| versionParts.Any(x => x > 9))
{
// An additional zero is needed for decimals
Expand All @@ -232,7 +224,7 @@ public string GetVersionString(string framework, Version version)
}

// Legacy frameworks that are allowed to have a single digit for the version number
private static readonly HashSet<string> _singleDigitVersionFrameworks = new HashSet<string>(
private static readonly HashSet<string> SingleDigitVersionFrameworks = new HashSet<string>(
new string[] {
FrameworkConstants.FrameworkIdentifiers.Windows,
FrameworkConstants.FrameworkIdentifiers.WindowsPhone,
Expand Down Expand Up @@ -502,7 +494,7 @@ public bool TryGetPortableProfileNumber(string profile, out int profileNumber)
if (profile.StartsWith("Profile", StringComparison.OrdinalIgnoreCase))
{
var trimmed = profile.Substring(7, profile.Length - 7);
return Int32.TryParse(trimmed, out profileNumber);
return int.TryParse(trimmed, out profileNumber);
}

profileNumber = -1;
Expand Down
52 changes: 35 additions & 17 deletions src/NuGet.Core/NuGet.Frameworks/NuGetFramework.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
Expand All @@ -23,7 +23,7 @@ partial class NuGetFramework : IEquatable<NuGetFramework>
private readonly string _frameworkIdentifier;
private readonly Version _frameworkVersion;
private readonly string _frameworkProfile;
private const string _portable = "portable";
private const string Portable = "portable";
private int? _hashCode;

public NuGetFramework(NuGetFramework framework)
Expand All @@ -41,6 +41,8 @@ public NuGetFramework(string framework, Version version)
{
}

private const int Version5 = 5;

public NuGetFramework(string frameworkIdentifier, Version frameworkVersion, string frameworkProfile)
{
if (frameworkIdentifier == null)
Expand All @@ -56,6 +58,7 @@ public NuGetFramework(string frameworkIdentifier, Version frameworkVersion, stri
_frameworkIdentifier = frameworkIdentifier;
_frameworkVersion = NormalizeVersion(frameworkVersion);
_frameworkProfile = frameworkProfile ?? string.Empty;
IsNet5Era = (_frameworkVersion.Major >= Version5 && StringComparer.OrdinalIgnoreCase.Equals(FrameworkConstants.FrameworkIdentifiers.NetCoreApp, _frameworkIdentifier));
}

/// <summary>
Expand All @@ -79,7 +82,7 @@ public Version Version
/// </summary>
public bool HasProfile
{
get { return !String.IsNullOrEmpty(Profile); }
get { return !string.IsNullOrEmpty(Profile); }
}

/// <summary>
Expand Down Expand Up @@ -113,20 +116,20 @@ public string GetDotNetFrameworkName(IFrameworkNameProvider mappings)

if (framework.IsSpecificFramework)
{
var parts = new List<string>(3) { framework.Framework };
var parts = new List<string>(3) { Framework };

parts.Add(String.Format(CultureInfo.InvariantCulture, "Version=v{0}", GetDisplayVersion(framework.Version)));
parts.Add(string.Format(CultureInfo.InvariantCulture, "Version=v{0}", GetDisplayVersion(framework.Version)));

if (!String.IsNullOrEmpty(framework.Profile))
if (!string.IsNullOrEmpty(framework.Profile))
{
parts.Add(String.Format(CultureInfo.InvariantCulture, "Profile={0}", framework.Profile));
parts.Add(string.Format(CultureInfo.InvariantCulture, "Profile={0}", framework.Profile));
}

result = String.Join(",", parts);
result = string.Join(",", parts);
}
else
{
result = String.Format(CultureInfo.InvariantCulture, "{0},Version=v0.0", framework.Framework);
result = string.Format(CultureInfo.InvariantCulture, "{0},Version=v0.0", framework.Framework);
}

return result;
Expand All @@ -141,6 +144,14 @@ public string GetShortFolderName()
return GetShortFolderName(DefaultFrameworkNameProvider.Instance);
}

/// <summary>
/// Helper that is .NET 5 Era aware to replace identifier when appropriate
/// </summary>
private string GetFrameworkIdentifier()
{
return IsNet5Era ? FrameworkConstants.FrameworkIdentifiers.Net : Framework;
}

/// <summary>
/// Creates the shortened version of the framework using the given mappings.
/// </summary>
Expand All @@ -156,12 +167,14 @@ public virtual string GetShortFolderName(IFrameworkNameProvider mappings)
var shortFramework = string.Empty;

// get the framework
if (!mappings.TryGetShortIdentifier(framework.Framework, out shortFramework))
if (!mappings.TryGetShortIdentifier(
GetFrameworkIdentifier(),
out shortFramework))
{
shortFramework = GetLettersAndDigitsOnly(framework.Framework);
}

if (String.IsNullOrEmpty(shortFramework))
if (string.IsNullOrEmpty(shortFramework))
{
throw new FrameworkException(string.Format(
CultureInfo.CurrentCulture,
Expand Down Expand Up @@ -195,7 +208,7 @@ public virtual string GetShortFolderName(IFrameworkNameProvider mappings)
// sort the PCL frameworks by alphabetical order
var sortedFrameworks = required.Select(e => e.GetShortFolderName(mappings)).OrderBy(e => e, StringComparer.OrdinalIgnoreCase).ToList();

sb.Append(String.Join("+", sortedFrameworks));
sb.Append(string.Join("+", sortedFrameworks));
}
else
{
Expand All @@ -216,7 +229,7 @@ public virtual string GetShortFolderName(IFrameworkNameProvider mappings)
shortProfile = framework.Profile;
}

if (!String.IsNullOrEmpty(shortProfile))
if (!string.IsNullOrEmpty(shortProfile))
{
sb.Append("-");
sb.Append(shortProfile);
Expand All @@ -234,7 +247,7 @@ public virtual string GetShortFolderName(IFrameworkNameProvider mappings)

private static string GetDisplayVersion(Version version)
{
var sb = new StringBuilder(String.Format(CultureInfo.InvariantCulture, "{0}.{1}", version.Major, version.Minor));
var sb = new StringBuilder(string.Format(CultureInfo.InvariantCulture, "{0}.{1}", version.Major, version.Minor));

if (version.Build > 0
|| version.Revision > 0)
Expand All @@ -256,7 +269,7 @@ private static string GetLettersAndDigitsOnly(string s)

foreach (var c in s.ToCharArray())
{
if (Char.IsLetterOrDigit(c))
if (char.IsLetterOrDigit(c))
{
sb.Append(c);
}
Expand All @@ -282,7 +295,7 @@ public bool IsPackageBased
get
{
// For these frameworks all versions are packages based.
if (_packagesBased.Contains(Framework))
if (PackagesBased.Contains(Framework))
{
return true;
}
Expand Down Expand Up @@ -334,6 +347,11 @@ public bool IsSpecificFramework
get { return !IsAgnostic && !IsAny && !IsUnsupported; }
}

/// <summary>
/// True if this framework is Net5 or later, until we invent something new.
/// </summary>
internal bool IsNet5Era { get; set; }

/// <summary>
/// Full framework comparison of the identifier, version, profile, platform, and platform version
/// </summary>
Expand Down Expand Up @@ -408,7 +426,7 @@ private static Version NormalizeVersion(Version version)
/// <summary>
/// Frameworks that are packages based across all versions.
/// </summary>
private static readonly SortedSet<string> _packagesBased = new SortedSet<string>(
private static readonly SortedSet<string> PackagesBased = new SortedSet<string>(
new[]
{
FrameworkConstants.FrameworkIdentifiers.DnxCore,
Expand Down
Loading

0 comments on commit 162e235

Please sign in to comment.