Skip to content

Commit

Permalink
Support for numeric only release labels with floating ranges
Browse files Browse the repository at this point in the history
* Allow 1.0.0-* to float from 1.0.0-0 instead of 1.0.0-- which is a non-numeric label.
* Treat floating labels that end with . in the same way as labels ending in - when converting to non-snapshot versions for display purposes.

Fixes NuGet/Home#4513
  • Loading branch information
emgarten committed Aug 2, 2017
1 parent 53fee13 commit 313a378
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 41 deletions.
Expand Up @@ -220,7 +220,7 @@ public static bool IsGreaterThanOrEqualTo(VersionRange nearVersion, VersionRange
}

nearMinVersion = GetReleaseLabelFreeVersion(nearVersion);
nearRelease = nearVersion.Float.MinVersion.Release;
nearRelease = nearVersion.Float.OriginalReleasePrefix;
}
else
{
Expand All @@ -237,7 +237,7 @@ public static bool IsGreaterThanOrEqualTo(VersionRange nearVersion, VersionRange
}

farMinVersion = GetReleaseLabelFreeVersion(farVersion);
farRelease = farVersion.Float.MinVersion.Release;
farRelease = farVersion.Float.OriginalReleasePrefix;
}
else
{
Expand All @@ -251,8 +251,6 @@ public static bool IsGreaterThanOrEqualTo(VersionRange nearVersion, VersionRange
return result > 0;
}

nearRelease = nearRelease?.Trim('-');
farRelease = farRelease?.Trim('-');
if (string.IsNullOrEmpty(nearRelease))
{
// near is 1.0.0-*
Expand Down
44 changes: 19 additions & 25 deletions src/NuGet.Core/NuGet.Versioning/FloatRange.cs
Expand Up @@ -59,26 +59,21 @@ public FloatRange(NuGetVersionFloatBehavior floatBehavior, NuGetVersion minVersi
/// <summary>
/// True if a min range exists.
/// </summary>
public bool HasMinVersion
{
get { return _minVersion != null; }
}

public bool HasMinVersion => _minVersion != null;
/// <summary>
/// The minimum version of the float range. This is null for cases such as *
/// </summary>
public NuGetVersion MinVersion
{
get { return _minVersion; }
}
public NuGetVersion MinVersion => _minVersion;

/// <summary>
/// Defined float behavior
/// </summary>
public NuGetVersionFloatBehavior FloatBehavior
{
get { return _floatBehavior; }
}
public NuGetVersionFloatBehavior FloatBehavior => _floatBehavior;

/// <summary>
/// The original release label. Invalid labels are allowed here.
/// </summary>
public string OriginalReleasePrefix => _releasePrefix;

/// <summary>
/// True if the given version falls into the floating range.
Expand Down Expand Up @@ -202,17 +197,16 @@ public static bool TryParse(string versionString, out FloatRange range)
{
releasePrefix = actualVersion.Substring(versionString.LastIndexOf('-') + 1);

if (actualVersion.EndsWith("-"))
// For numeric labels 0 is the lowest. For alpha-numeric - is the lowest.
if (releasePrefix.Length == 0 || actualVersion.EndsWith("."))
{
// remove the empty release label, the version will be release but
// the behavior will have to account for this
actualVersion += "-";
// 1.0.0-* scenario, an empty label is not a valid version.
actualVersion += "0";
}
else if (actualVersion.EndsWith("."))
else if (actualVersion.EndsWith("-"))
{
// ending with a . is not allowed
// TODO: solve this better
actualVersion += "0";
// Append a dash to allow floating on the next character.
actualVersion += "-";
}
}
}
Expand Down Expand Up @@ -251,16 +245,16 @@ public override string ToString()
result = MinVersion.ToNormalizedString();
break;
case NuGetVersionFloatBehavior.Prerelease:
result = String.Format(VersionFormatter.Instance, "{0:V}-{1}*", MinVersion, _releasePrefix);
result = string.Format(VersionFormatter.Instance, "{0:V}-{1}*", MinVersion, _releasePrefix);
break;
case NuGetVersionFloatBehavior.Revision:
result = String.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}.*", MinVersion.Major, MinVersion.Minor, MinVersion.Patch);
result = string.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}.*", MinVersion.Major, MinVersion.Minor, MinVersion.Patch);
break;
case NuGetVersionFloatBehavior.Patch:
result = String.Format(CultureInfo.InvariantCulture, "{0}.{1}.*", MinVersion.Major, MinVersion.Minor);
result = string.Format(CultureInfo.InvariantCulture, "{0}.{1}.*", MinVersion.Major, MinVersion.Minor);
break;
case NuGetVersionFloatBehavior.Minor:
result = String.Format(CultureInfo.InvariantCulture, "{0}.*", MinVersion.Major);
result = string.Format(CultureInfo.InvariantCulture, "{0}.*", MinVersion.Major);
break;
case NuGetVersionFloatBehavior.Major:
result = "*";
Expand Down
25 changes: 16 additions & 9 deletions src/NuGet.Core/NuGet.Versioning/VersionRange.cs
Expand Up @@ -317,21 +317,28 @@ private static NuGetVersion GetNonSnapshotVersion(NuGetVersion version)

var lastLabel = version.ReleaseLabels.LastOrDefault() ?? string.Empty;

if (lastLabel.EndsWith("-", StringComparison.Ordinal))
var endsWithZero = lastLabel == "0";
var endsWithDash = lastLabel.EndsWith("-", StringComparison.Ordinal);

if (endsWithZero || endsWithDash)
{
var fixedReleaseLabel = string.Empty;

if (lastLabel.EndsWith("--", StringComparison.Ordinal))
{
// For labels such as rc1-* an additional - is added by nuget
fixedReleaseLabel = lastLabel.Substring(0, lastLabel.Length - 2);
}
else
if (endsWithDash)
{
// Remove the - for 1.0.0-* (1.0.0--)
fixedReleaseLabel = lastLabel.Substring(0, lastLabel.Length - 1);
if (lastLabel.EndsWith("--", StringComparison.Ordinal))
{
// For labels such as rc1-* an additional - is added by nuget
fixedReleaseLabel = lastLabel.Substring(0, lastLabel.Length - 2);
}
else
{
// Remove the - for 1.0.0-* (1.0.0--)
fixedReleaseLabel = lastLabel.Substring(0, lastLabel.Length - 1);
}
}

// Remove the last label and add in the fixed label if one exists.
var fixedLabels = version.ReleaseLabels.Take(version.ReleaseLabels.Count() - 1).ToList();

if (!string.IsNullOrEmpty(fixedReleaseLabel))
Expand Down
Expand Up @@ -42,7 +42,7 @@ public async Task ProjectKNuGetProject_WithVersionRange_GetInstalledPackagesAsyn
Assert.Equal(1, actual.Count());
var packageReference = actual.First();
Assert.Equal("foo", packageReference.PackageIdentity.Id);
Assert.Equal(NuGetVersion.Parse("1.0.0--"), packageReference.PackageIdentity.Version);
Assert.Equal(NuGetVersion.Parse("1.0.0-0"), packageReference.PackageIdentity.Version);
}
}

Expand Down
Expand Up @@ -123,7 +123,7 @@ public void FloatingRange_FloatPre()
{
var range = FloatRange.Parse("1.0.0-*");

Assert.Equal("1.0.0--", range.MinVersion.ToNormalizedString());
Assert.Equal("1.0.0-0", range.MinVersion.ToNormalizedString());
Assert.Equal(NuGetVersionFloatBehavior.Prerelease, range.FloatBehavior);
}

Expand Down
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.Collections.Generic;
using System.Linq;
using Xunit;

namespace NuGet.Versioning.Test
Expand All @@ -16,6 +17,56 @@ public void VersionRangeFloatParsing_Prerelease()
Assert.True(range.MinVersion.IsPrerelease);
}

[Theory]
[InlineData("1.0.0-*", "1.0.0-0")]
[InlineData("1.0.0-0*", "1.0.0-0")]
[InlineData("1.0.0--*", "1.0.0--")]
[InlineData("1.0.0-a-*", "1.0.0-a-")]
[InlineData("1.0.0-a.*", "1.0.0-a.0")]
public void VersionRangeFloatParsing_PrereleaseWithNumericOnlyLabelVerifyMinVersion(string rangeString, string expected)
{
var range = VersionRange.Parse(rangeString);

Assert.Equal(expected, range.MinVersion.ToNormalizedString());
}

[Theory]
[InlineData("1.0.0-0")]
[InlineData("1.0.0-100")]
[InlineData("1.0.0-0.0.0.0")]
[InlineData("1.0.0-0+0-0")]
public void VersionRangeFloatParsing_PrereleaseWithNumericOnlyLabelVerifySatisfies(string version)
{
var range = VersionRange.Parse("1.0.0-*");

Assert.True(range.Satisfies(NuGetVersion.Parse(version)));
}

[Theory]
[InlineData("1.0.0-a*", "1.0.0-a.0")]
[InlineData("1.0.0-a*", "1.0.0-a-0")]
[InlineData("1.0.0-a*", "1.0.0-a")]
public void VersionRangeFloatParsing_VerifySatisfiesForFloatingRange(string rangeString, string version)
{
var range = VersionRange.Parse(rangeString);

Assert.True(range.Satisfies(NuGetVersion.Parse(version)));
}

[Theory]
[InlineData("1.0.0-*", "0", "")]
[InlineData("1.0.0-a*", "a", "a")]
[InlineData("1.0.0-a-*", "a-", "a-")]
[InlineData("1.0.0-a.*", "a.0", "a.")]
[InlineData("1.0.0-0*", "0", "0")]
public void VersionRangeFloatParsing_VerifyReleaseLabels(string rangeString, string versionLabel, string originalLabel)
{
var range = VersionRange.Parse(rangeString);

Assert.Equal(versionLabel, range.Float.MinVersion.Release);
Assert.Equal(originalLabel, range.Float.OriginalReleasePrefix);
}

[Theory]
[InlineData("1.0.0")]
[InlineData("[1.0.0]")]
Expand Down
Expand Up @@ -172,7 +172,7 @@ public void VersionRange_MetadataIsIgnored_FormatRemovesMetadata_PrettyPrint()
[InlineData("1.0.0-*", "1.0.0")]
[InlineData("2.0.0-*", "2.0.0")]
[InlineData("1.0.0-rc1-*", "1.0.0-rc1")]
[InlineData("1.0.0-5.1.*", "1.0.0-5.1.0")]
[InlineData("1.0.0-5.1.*", "1.0.0-5.1")]
[InlineData("1.0.0-5.1.0-*", "1.0.0-5.1.0")]
[InlineData("1.0.*", "1.0.0")]
[InlineData("1.*", "1.0.0")]
Expand Down

0 comments on commit 313a378

Please sign in to comment.