Created
February 25, 2015 07:56
-
-
Save emgarten/e1d6bd5dd3bbfb1ae4e2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace NuGet.Versioning | |
{ | |
/// <summary> | |
/// VersionFloatComparer orders versions around a floating range. The range in this | |
/// case is only the floating part. | |
/// Ex: [1.0.*, 2.0.0) has a floating range of [1.0.0, 1.1.0) | |
/// Filtering on the [1.0.0, 2.0.0) range needs to happen outside of this class, it will not be | |
/// taken into account here. | |
/// | |
/// Ordering: | |
/// 1. The highest version that satisfies the range. | |
/// 2. The lowest version above the range is ordered next. | |
/// 3. The highest version below the range is after that. | |
/// | |
/// #3 Should always be filtered out first since the lower bound used to describe the floating range is a hard minimum. | |
/// </summary> | |
public class VersionFloatComparer : IVersionFloatComparer | |
{ | |
private readonly IVersionComparer _versionComparer; | |
private readonly VersionRangeBase _floatRange; | |
/// <summary> | |
/// Sorts a set of versions based on a floating range. | |
/// </summary> | |
/// <param name="floatRange">The floating part of the range. Ex: [1.0.*, 2.0.0) has a floating range of [1.0.0, 1.1.0)</param> | |
public VersionFloatComparer(VersionRangeBase floatRange) | |
: this(floatRange, VersionComparer.Default) | |
{ | |
} | |
/// <summary> | |
/// Sorts a set of versions based on a floating range. | |
/// </summary> | |
/// <param name="floatRange">The floating part of the range. Ex: [1.0.*, 2.0.0) has a floating range of [1.0.0, 1.1.0)</param> | |
/// <param name="versionComparer">NuGetVersion comparer</param> | |
public VersionFloatComparer(VersionRangeBase floatRange, IVersionComparer versionComparer) | |
{ | |
if (floatRange == null) | |
{ | |
throw new ArgumentNullException("floatRange"); | |
} | |
if (versionComparer == null) | |
{ | |
throw new ArgumentNullException("IVersionComparer"); | |
} | |
if (!floatRange.HasLowerBound) | |
{ | |
throw new ArgumentException("floatRange must have a lower bound"); | |
} | |
_floatRange = floatRange; | |
_versionComparer = versionComparer; | |
} | |
/// <summary> | |
/// Order versions based on which is the best match for the floating version. | |
/// The first item in the sorted list will be the best match, last is worst. | |
/// </summary> | |
public int Compare(NuGetVersion x, NuGetVersion y) | |
{ | |
if (Object.ReferenceEquals(x, y)) | |
{ | |
return 0; | |
} | |
// null versions should not exist, but if they do they go at the end | |
if (Object.ReferenceEquals(y, null)) | |
{ | |
return -1; | |
} | |
if (Object.ReferenceEquals(x, null)) | |
{ | |
return 1; | |
} | |
// check if either version is in the floating range | |
bool xInRange = _floatRange.Satisfies(x, _versionComparer); | |
bool yInRange = _floatRange.Satisfies(x, _versionComparer); | |
if (xInRange && !yInRange) | |
{ | |
// take the version in the range | |
return -1; | |
} | |
else if(yInRange && !xInRange) | |
{ | |
// take the version in the range | |
return 1; | |
} | |
else if (xInRange && yInRange) | |
{ | |
// compare in reverse to prefer the highest one | |
return _versionComparer.Compare(y, x); | |
} | |
else | |
{ | |
// neither are in range | |
int xToLower = _versionComparer.Compare(x, _floatRange.MinVersion); | |
int yToLower = _versionComparer.Compare(y, _floatRange.MinVersion); | |
if (xToLower < 0 && yToLower > 0) | |
{ | |
// favor the version above the range | |
return 1; | |
} | |
else if (xToLower > 0 && yToLower < 0) | |
{ | |
// favor the version above the range | |
return -1; | |
} | |
else if (xToLower > 0 && yToLower > 0) | |
{ | |
// favor the lower version if we are above the range | |
return _versionComparer.Compare(x, y); | |
} | |
else if (xToLower < 0 && yToLower < 0) | |
{ | |
// favor the higher version if we are below the range | |
return _versionComparer.Compare(y, x); | |
} | |
} | |
// favor the higher version if nothing else works | |
// this may also be hit if both versions are equal | |
return _versionComparer.Compare(y, x); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment