Skip to content

Commit

Permalink
Support floating prerelease and stable packages at the same time with…
Browse files Browse the repository at this point in the history
… the same version range (enable absolute latest scenario) (#3247)
  • Loading branch information
nkolev92 authored Mar 17, 2020
1 parent 106bb59 commit 69458fe
Show file tree
Hide file tree
Showing 8 changed files with 1,068 additions and 34 deletions.
140 changes: 124 additions & 16 deletions src/NuGet.Core/NuGet.Versioning/FloatRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,37 @@ public bool Satisfies(NuGetVersion version)
if (_minVersion != null)
{
// everything beyond this point requires a version
if (_floatBehavior == NuGetVersionFloatBehavior.Prerelease)
if (_floatBehavior == NuGetVersionFloatBehavior.PrereleaseRevision)
{
// allow the stable version to match
return _minVersion.Major == version.Major
&& _minVersion.Minor == version.Minor
&& _minVersion.Patch == version.Patch
&& ((version.IsPrerelease && version.Release.StartsWith(_releasePrefix, StringComparison.OrdinalIgnoreCase))
|| !version.IsPrerelease);
}
else if (_floatBehavior == NuGetVersionFloatBehavior.PrereleasePatch)
{
// allow the stable version to match
return _minVersion.Major == version.Major
&& _minVersion.Minor == version.Minor
&& ((version.IsPrerelease && version.Release.StartsWith(_releasePrefix, StringComparison.OrdinalIgnoreCase))
|| !version.IsPrerelease);
}
else if (FloatBehavior == NuGetVersionFloatBehavior.PrereleaseMinor)
{
// allow the stable version to match
return _minVersion.Major == version.Major
&& ((version.IsPrerelease && version.Release.StartsWith(_releasePrefix, StringComparison.OrdinalIgnoreCase))
|| !version.IsPrerelease);
}
else if (FloatBehavior == NuGetVersionFloatBehavior.PrereleaseMajor)
{
// allow the stable version to match
return (version.IsPrerelease && version.Release.StartsWith(_releasePrefix, StringComparison.OrdinalIgnoreCase))
|| !version.IsPrerelease;
}
else if (_floatBehavior == NuGetVersionFloatBehavior.Prerelease)
{
// allow the stable version to match
return VersionComparer.Version.Equals(_minVersion, version)
Expand Down Expand Up @@ -134,9 +164,7 @@ public bool Satisfies(NuGetVersion version)
/// </summary>
public static FloatRange Parse(string versionString)
{
FloatRange range = null;

TryParse(versionString, out range);
TryParse(versionString, out FloatRange range);

return range;
}
Expand All @@ -148,32 +176,86 @@ public static bool TryParse(string versionString, out FloatRange range)
{
range = null;

if (versionString != null)
if (versionString != null && !string.IsNullOrWhiteSpace(versionString))
{
var starPos = versionString.IndexOf('*');

var actualVersion = versionString;
var firstStarPosition = versionString.IndexOf('*');
var lastStarPosition = versionString.LastIndexOf('*');
string releasePrefix = null;

if (versionString.Length == 1
&& starPos == 0)
&& firstStarPosition == 0)
{
range = new FloatRange(NuGetVersionFloatBehavior.Major, new NuGetVersion(new Version(0, 0)));
}
// * must appear as the last char in the string.
else if (versionString.Equals("*-*"))
{
range = new FloatRange(NuGetVersionFloatBehavior.AbsoluteLatest, new NuGetVersion("0.0.0-0"), releasePrefix: string.Empty);
}
else if (firstStarPosition != lastStarPosition && lastStarPosition != -1 && versionString.IndexOf('+') == -1)
{
var behavior = NuGetVersionFloatBehavior.None;
// 2 *s are only allowed in prerelease versions.
var dashPosition = versionString.IndexOf('-');
string actualVersion = null;

if (dashPosition != -1 &&
lastStarPosition == versionString.Length - 1 && // Last star is at the end of the full string
firstStarPosition == (dashPosition-1) // First star is right before the first dash.
)
{
// Get the stable part.
var stablePart = versionString.Substring(0, dashPosition - 1); // Get the part without the *
stablePart += "0";
var versionParts = CalculateVersionParts(stablePart);
switch (versionParts)
{
case 1:
behavior = NuGetVersionFloatBehavior.PrereleaseMajor;
break;
case 2:
behavior = NuGetVersionFloatBehavior.PrereleaseMinor;
break;
case 3:
behavior = NuGetVersionFloatBehavior.PrereleasePatch;
break;
case 4:
behavior = NuGetVersionFloatBehavior.PrereleaseRevision;
break;
default:
break;
}

var releaseVersion = versionString.Substring(dashPosition + 1);
releasePrefix = releaseVersion.Substring(0, releaseVersion.Length - 1);
var releasePart = releasePrefix;
if (releasePrefix.Length == 0 || releasePrefix.EndsWith("."))
{
// 1.0.0-* scenario, an empty label is not a valid version.
releasePart += "0";
}

actualVersion = stablePart + "-" + releasePart;
}

if (NuGetVersion.TryParse(actualVersion, out NuGetVersion version))
{
range = new FloatRange(behavior, version, releasePrefix);
}
}
// A single * can only appear as the last char in the string.
// * cannot appear in the metadata section after the +
else if (starPos == versionString.Length - 1 && versionString.IndexOf('+') == -1)
else if (lastStarPosition == versionString.Length - 1 && versionString.IndexOf('+') == -1)
{
var behavior = NuGetVersionFloatBehavior.None;

actualVersion = versionString.Substring(0, versionString.Length - 1);
var actualVersion = versionString.Substring(0, versionString.Length - 1);

if (versionString.IndexOf('-') == -1)
{
// replace the * with a 0
actualVersion += "0";

var versionParts = actualVersion.Split('.').Length;
var versionParts = CalculateVersionParts(actualVersion);

if (versionParts == 2)
{
Expand Down Expand Up @@ -214,7 +296,6 @@ public static bool TryParse(string versionString, out FloatRange range)
NuGetVersion version = null;
if (NuGetVersion.TryParse(actualVersion, out version))
{
// there is no float range for this version
range = new FloatRange(behavior, version, releasePrefix);
}
}
Expand All @@ -233,6 +314,22 @@ public static bool TryParse(string versionString, out FloatRange range)
return range != null;
}

private static int CalculateVersionParts(string line)
{
var count = 1;
if (line != null)
{
for (var i = 0; i < line.Length; i++)
{
if (line[i] == '.')
{
count++;
}
}
}
return count;
}

/// <summary>
/// Create a floating version string in the format: 1.0.0-alpha-*
/// </summary>
Expand All @@ -259,9 +356,20 @@ public override string ToString()
case NuGetVersionFloatBehavior.Major:
result = "*";
break;
case NuGetVersionFloatBehavior.PrereleaseRevision:
result = string.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}.*-{3}*", MinVersion.Major, MinVersion.Minor, MinVersion.Patch, _releasePrefix);
break;
case NuGetVersionFloatBehavior.PrereleasePatch:
result = string.Format(CultureInfo.InvariantCulture, "{0}.{1}.*-{2}*", MinVersion.Major, MinVersion.Minor, _releasePrefix);
break;
case NuGetVersionFloatBehavior.PrereleaseMinor:
result = string.Format(CultureInfo.InvariantCulture, "{0}.*-{1}*", MinVersion.Major, _releasePrefix);
break;
case NuGetVersionFloatBehavior.PrereleaseMajor:
result = string.Format(CultureInfo.InvariantCulture, "*-{1}*", MinVersion.Major, _releasePrefix);
break;
case NuGetVersionFloatBehavior.AbsoluteLatest:
// TODO: how should this be denoted?
result = string.Empty;
result = "*-*";
break;
default:
break;
Expand Down
27 changes: 24 additions & 3 deletions src/NuGet.Core/NuGet.Versioning/NuGetVersionFloatBehavior.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.

namespace NuGet.Versioning
Expand Down Expand Up @@ -39,8 +39,29 @@ public enum NuGetVersionFloatBehavior
Major,

/// <summary>
/// Float major and pre-release
/// Float major and pre-release, *-*
/// </summary>
AbsoluteLatest
AbsoluteLatest,

/// <summary>
/// Float revision and pre-release x.y.z.*-*
/// </summary>
PrereleaseRevision,

/// <summary>
/// Float patch and pre-release x.y.*-*
/// </summary>
PrereleasePatch,

/// <summary>
/// Float minor and pre-release x.*-*
/// </summary>
PrereleaseMinor,

/// <summary>
/// Float major and prerelease, but only with partial prerelease *-rc.*.
/// *-* is captured by <see cref="AbsoluteLatest"/>
/// </summary>
PrereleaseMajor,
}
}
4 changes: 4 additions & 0 deletions src/NuGet.Core/NuGet.Versioning/VersionRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ public bool IsBetter(NuGetVersion current, NuGetVersion considering)
if (!HasPrereleaseBounds
&& considering.IsPrerelease
&& _floatRange?.FloatBehavior != NuGetVersionFloatBehavior.Prerelease
&& _floatRange?.FloatBehavior != NuGetVersionFloatBehavior.PrereleaseMajor
&& _floatRange?.FloatBehavior != NuGetVersionFloatBehavior.PrereleaseMinor
&& _floatRange?.FloatBehavior != NuGetVersionFloatBehavior.PrereleasePatch
&& _floatRange?.FloatBehavior != NuGetVersionFloatBehavior.PrereleaseRevision
&& _floatRange?.FloatBehavior != NuGetVersionFloatBehavior.AbsoluteLatest)
{
return false;
Expand Down
8 changes: 4 additions & 4 deletions src/NuGet.Core/NuGet.Versioning/VersionRangeFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public static VersionRange Parse(string value, bool allowFloating)
if (!TryParse(value, allowFloating, out versionInfo))
{
throw new ArgumentException(
String.Format(CultureInfo.CurrentCulture,
string.Format(CultureInfo.CurrentCulture,
Resources.Invalidvalue, value));
}

Expand Down Expand Up @@ -101,7 +101,7 @@ public static bool TryParse(string value, bool allowFloating, out VersionRange v

var charArray = trimmedValue.ToCharArray();

// * is the only range below 3 chars
// * is the only 1 char range
if (allowFloating
&& charArray.Length == 1
&& charArray[0] == '*')
Expand Down Expand Up @@ -195,7 +195,7 @@ public static bool TryParse(string value, bool allowFloating, out VersionRange v
minVersionString = trimmedValue;
}

if (!String.IsNullOrWhiteSpace(minVersionString))
if (!string.IsNullOrWhiteSpace(minVersionString))
{
// parse the min version string
if (allowFloating && minVersionString.Contains("*"))
Expand Down Expand Up @@ -224,7 +224,7 @@ public static bool TryParse(string value, bool allowFloating, out VersionRange v
}

// parse the max version string, the max cannot float
if (!String.IsNullOrWhiteSpace(maxVersionString))
if (!string.IsNullOrWhiteSpace(maxVersionString))
{
if (!NuGetVersion.TryParse(maxVersionString, out maxVersion))
{
Expand Down
1 change: 0 additions & 1 deletion src/NuGet.Core/NuGet.Versioning/VersionRangeFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ private string GetShortString(VersionRange range)
/// </summary>
private string GetNormalizedString(VersionRange range)
{
// TODO: write out the float version
var sb = new StringBuilder();

sb.Append(range.HasLowerBound && range.IsMinInclusive ? '[' : '(');
Expand Down
Loading

0 comments on commit 69458fe

Please sign in to comment.