Replaced SemanticVersion.cs with the unmodified SemVersion.cs from original author.
This commit is contained in:
parent
09d362eac1
commit
64a2c35c0c
@ -40,8 +40,8 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\Katteker\SemanticVersion.cs">
|
<Compile Include="..\Katteker\Common\SemVersion.cs">
|
||||||
<Link>SemanticVersion.cs</Link>
|
<Link>SemVersion.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
@ -5,7 +5,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Katteker;
|
using Semver;
|
||||||
|
|
||||||
namespace AppStub
|
namespace AppStub
|
||||||
{
|
{
|
||||||
@ -26,13 +26,13 @@ namespace AppStub
|
|||||||
var files = directory.EnumerateFiles(location.Name, SearchOption.AllDirectories)
|
var files = directory.EnumerateFiles(location.Name, SearchOption.AllDirectories)
|
||||||
.Where(x => x.Directory?.Name.StartsWith("app-") == true);
|
.Where(x => x.Directory?.Name.StartsWith("app-") == true);
|
||||||
|
|
||||||
var entries = new SortedList<SemanticVersion, FileInfo>();
|
var entries = new SortedList<SemVersion, FileInfo>();
|
||||||
|
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
var version = SemanticVersion.TryParse(file.Directory?.Name.Replace("app-", ""), out var value)
|
var version = SemVersion.TryParse(file.Directory?.Name.Replace("app-", ""), out var value)
|
||||||
? value
|
? value
|
||||||
: new SemanticVersion(0);
|
: new SemVersion(0);
|
||||||
entries.Add(version, file);
|
entries.Add(version, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ namespace AppStub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DeleteOldVersionDirectories(IEnumerable<KeyValuePair<SemanticVersion, FileInfo>> dirEntries)
|
private static void DeleteOldVersionDirectories(IEnumerable<KeyValuePair<SemVersion, FileInfo>> dirEntries)
|
||||||
{
|
{
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
foreach (var directoryInfo in dirEntries)
|
foreach (var directoryInfo in dirEntries)
|
||||||
|
@ -1,268 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace AppStub
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A hybrid implementation of SemVer that supports semantic versioning as described at http://semver.org while not
|
|
||||||
/// strictly enforcing it to
|
|
||||||
/// allow older 4-digit versioning schemes to continue working.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
//[TypeConverter(typeof(SemanticVersionTypeConverter))]
|
|
||||||
public sealed class SemanticVersion : IComparable, IComparable<SemanticVersion>, IEquatable<SemanticVersion>
|
|
||||||
{
|
|
||||||
private const RegexOptions Flags =
|
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;
|
|
||||||
|
|
||||||
private static readonly Regex SemanticVersionRegex =
|
|
||||||
new Regex(@"^(?<Version>\d+(\s*\.\s*\d+){0,3})(?<Release>-[a-z][0-9a-z-]*)?$", Flags);
|
|
||||||
|
|
||||||
private static readonly Regex StrictSemanticVersionRegex =
|
|
||||||
new Regex(@"^(?<Version>\d+(\.\d+){2})(?<Release>-[a-z][0-9a-z-]*)?$", Flags);
|
|
||||||
|
|
||||||
private readonly string _originalString;
|
|
||||||
|
|
||||||
public SemanticVersion(string version)
|
|
||||||
: this(Parse(version))
|
|
||||||
{
|
|
||||||
// The constructor normalizes the version string so that it we do not need to normalize it every time we need to operate on it.
|
|
||||||
// The original string represents the original form in which the version is represented to be used when printing.
|
|
||||||
_originalString = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int build, int revision)
|
|
||||||
: this(new Version(major, minor, build, revision))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int build, string specialVersion)
|
|
||||||
: this(new Version(major, minor, build), specialVersion)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(Version version)
|
|
||||||
: this(version, string.Empty)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(Version version, string specialVersion)
|
|
||||||
: this(version, specialVersion, null)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private SemanticVersion(Version version, string specialVersion, string originalString)
|
|
||||||
{
|
|
||||||
if (version == null)
|
|
||||||
throw new ArgumentNullException(nameof(version));
|
|
||||||
Version = NormalizeVersionValue(version);
|
|
||||||
SpecialVersion = specialVersion ?? string.Empty;
|
|
||||||
_originalString = string.IsNullOrEmpty(originalString)
|
|
||||||
? version + (!string.IsNullOrEmpty(specialVersion) ? '-' + specialVersion : null)
|
|
||||||
: originalString;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SemanticVersion(SemanticVersion semVer)
|
|
||||||
{
|
|
||||||
_originalString = semVer.ToString();
|
|
||||||
Version = semVer.Version;
|
|
||||||
SpecialVersion = semVer.SpecialVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the normalized version portion.
|
|
||||||
/// </summary>
|
|
||||||
public Version Version { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public string SpecialVersion { get; }
|
|
||||||
|
|
||||||
public int CompareTo(object obj)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(obj, null))
|
|
||||||
return 1;
|
|
||||||
var other = obj as SemanticVersion;
|
|
||||||
if (other == null)
|
|
||||||
throw new ArgumentException("Type Must Be A Semantic Version", nameof(obj));
|
|
||||||
return CompareTo(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(SemanticVersion other)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(other, null))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
var result = Version.CompareTo(other.Version);
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
var empty = string.IsNullOrEmpty(SpecialVersion);
|
|
||||||
var otherEmpty = string.IsNullOrEmpty(other.SpecialVersion);
|
|
||||||
if (empty && otherEmpty)
|
|
||||||
return 0;
|
|
||||||
if (empty)
|
|
||||||
return 1;
|
|
||||||
if (otherEmpty)
|
|
||||||
return -1;
|
|
||||||
return StringComparer.OrdinalIgnoreCase.Compare(SpecialVersion, other.SpecialVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(SemanticVersion other)
|
|
||||||
{
|
|
||||||
return !ReferenceEquals(null, other) &&
|
|
||||||
Version.Equals(other.Version) &&
|
|
||||||
SpecialVersion.Equals(other.SpecialVersion, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetOriginalVersionComponents()
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(_originalString))
|
|
||||||
{
|
|
||||||
// search the start of the SpecialVersion part, if any
|
|
||||||
var dashIndex = _originalString.IndexOf('-');
|
|
||||||
var original = dashIndex != -1 ? _originalString.Substring(0, dashIndex) : _originalString;
|
|
||||||
|
|
||||||
return SplitAndPadVersionString(original);
|
|
||||||
}
|
|
||||||
return SplitAndPadVersionString(Version.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string[] SplitAndPadVersionString(string version)
|
|
||||||
{
|
|
||||||
var a = version.Split('.');
|
|
||||||
if (a.Length == 4)
|
|
||||||
{
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
// if 'a' has less than 4 elements, we pad the '0' at the end
|
|
||||||
// to make it 4.
|
|
||||||
var b = new string[4] {"0", "0", "0", "0"};
|
|
||||||
Array.Copy(a, 0, b, 0, a.Length);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an
|
|
||||||
/// optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static SemanticVersion Parse(string version)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
throw new ArgumentException(nameof(version));
|
|
||||||
|
|
||||||
if (!TryParse(version, out var semVer))
|
|
||||||
throw new ArgumentException("Invalid Version String", nameof(version));
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an
|
|
||||||
/// optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryParse(string version, out SemanticVersion value)
|
|
||||||
{
|
|
||||||
return TryParseInternal(version, SemanticVersionRegex, out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using strict semantic versioning rules that allows exactly 3 components and an optional
|
|
||||||
/// special version.
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryParseStrict(string version, out SemanticVersion value)
|
|
||||||
{
|
|
||||||
return TryParseInternal(version, StrictSemanticVersionRegex, out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryParseInternal(string version, Regex regex, out SemanticVersion semVer)
|
|
||||||
{
|
|
||||||
semVer = null;
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var match = regex.Match(version.Trim());
|
|
||||||
if (!match.Success || !Version.TryParse(match.Groups["Version"].Value, out var versionValue))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
semVer = new SemanticVersion(NormalizeVersionValue(versionValue),
|
|
||||||
match.Groups["Release"].Value.TrimStart('-'), version.Replace(" ", ""));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to parse the version token as a SemanticVersion.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An instance of SemanticVersion if it parses correctly, null otherwise.</returns>
|
|
||||||
public static SemanticVersion ParseOptionalVersion(string version)
|
|
||||||
{
|
|
||||||
TryParse(version, out var semVer);
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Version NormalizeVersionValue(Version version)
|
|
||||||
{
|
|
||||||
return new Version(version.Major,
|
|
||||||
version.Minor,
|
|
||||||
Math.Max(version.Build, 0),
|
|
||||||
Math.Max(version.Revision, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(version1, null))
|
|
||||||
return ReferenceEquals(version2, null);
|
|
||||||
return version1.Equals(version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return !(version1 == version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (version1 == null)
|
|
||||||
throw new ArgumentNullException(nameof(version1));
|
|
||||||
return version1.CompareTo(version2) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return version1 == version2 || version1 < version2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (version1 == null)
|
|
||||||
throw new ArgumentNullException(nameof(version1));
|
|
||||||
return version2 < version1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return version1 == version2 || version1 > version2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _originalString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
var semVer = obj as SemanticVersion;
|
|
||||||
return !ReferenceEquals(null, semVer) && Equals(semVer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
var hashCode = Version.GetHashCode();
|
|
||||||
if (SpecialVersion != null)
|
|
||||||
hashCode = hashCode * 4567 + SpecialVersion.GetHashCode();
|
|
||||||
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,268 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace Katteker.AppStub
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A hybrid implementation of SemVer that supports semantic versioning as described at http://semver.org while not
|
|
||||||
/// strictly enforcing it to
|
|
||||||
/// allow older 4-digit versioning schemes to continue working.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
//[TypeConverter(typeof(SemanticVersionTypeConverter))]
|
|
||||||
public sealed class SemanticVersion : IComparable, IComparable<SemanticVersion>, IEquatable<SemanticVersion>
|
|
||||||
{
|
|
||||||
private const RegexOptions Flags =
|
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;
|
|
||||||
|
|
||||||
private static readonly Regex SemanticVersionRegex =
|
|
||||||
new Regex(@"^(?<Version>\d+(\s*\.\s*\d+){0,3})(?<Release>-[a-z][0-9a-z-]*)?$", Flags);
|
|
||||||
|
|
||||||
private static readonly Regex StrictSemanticVersionRegex =
|
|
||||||
new Regex(@"^(?<Version>\d+(\.\d+){2})(?<Release>-[a-z][0-9a-z-]*)?$", Flags);
|
|
||||||
|
|
||||||
private readonly string _originalString;
|
|
||||||
|
|
||||||
public SemanticVersion(string version)
|
|
||||||
: this(Parse(version))
|
|
||||||
{
|
|
||||||
// The constructor normalizes the version string so that it we do not need to normalize it every time we need to operate on it.
|
|
||||||
// The original string represents the original form in which the version is represented to be used when printing.
|
|
||||||
_originalString = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int build, int revision)
|
|
||||||
: this(new Version(major, minor, build, revision))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int build, string specialVersion)
|
|
||||||
: this(new Version(major, minor, build), specialVersion)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(Version version)
|
|
||||||
: this(version, string.Empty)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(Version version, string specialVersion)
|
|
||||||
: this(version, specialVersion, null)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private SemanticVersion(Version version, string specialVersion, string originalString)
|
|
||||||
{
|
|
||||||
if (version == null)
|
|
||||||
throw new ArgumentNullException(nameof(version));
|
|
||||||
Version = NormalizeVersionValue(version);
|
|
||||||
SpecialVersion = specialVersion ?? string.Empty;
|
|
||||||
_originalString = string.IsNullOrEmpty(originalString)
|
|
||||||
? version + (!string.IsNullOrEmpty(specialVersion) ? '-' + specialVersion : null)
|
|
||||||
: originalString;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SemanticVersion(SemanticVersion semVer)
|
|
||||||
{
|
|
||||||
_originalString = semVer.ToString();
|
|
||||||
Version = semVer.Version;
|
|
||||||
SpecialVersion = semVer.SpecialVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the normalized version portion.
|
|
||||||
/// </summary>
|
|
||||||
public Version Version { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public string SpecialVersion { get; }
|
|
||||||
|
|
||||||
public int CompareTo(object obj)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(obj, null))
|
|
||||||
return 1;
|
|
||||||
var other = obj as SemanticVersion;
|
|
||||||
if (other == null)
|
|
||||||
throw new ArgumentException("Type Must Be A Semantic Version", nameof(obj));
|
|
||||||
return CompareTo(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(SemanticVersion other)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(other, null))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
var result = Version.CompareTo(other.Version);
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
var empty = string.IsNullOrEmpty(SpecialVersion);
|
|
||||||
var otherEmpty = string.IsNullOrEmpty(other.SpecialVersion);
|
|
||||||
if (empty && otherEmpty)
|
|
||||||
return 0;
|
|
||||||
if (empty)
|
|
||||||
return 1;
|
|
||||||
if (otherEmpty)
|
|
||||||
return -1;
|
|
||||||
return StringComparer.OrdinalIgnoreCase.Compare(SpecialVersion, other.SpecialVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(SemanticVersion other)
|
|
||||||
{
|
|
||||||
return !ReferenceEquals(null, other) &&
|
|
||||||
Version.Equals(other.Version) &&
|
|
||||||
SpecialVersion.Equals(other.SpecialVersion, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetOriginalVersionComponents()
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(_originalString))
|
|
||||||
{
|
|
||||||
// search the start of the SpecialVersion part, if any
|
|
||||||
var dashIndex = _originalString.IndexOf('-');
|
|
||||||
var original = dashIndex != -1 ? _originalString.Substring(0, dashIndex) : _originalString;
|
|
||||||
|
|
||||||
return SplitAndPadVersionString(original);
|
|
||||||
}
|
|
||||||
return SplitAndPadVersionString(Version.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string[] SplitAndPadVersionString(string version)
|
|
||||||
{
|
|
||||||
var a = version.Split('.');
|
|
||||||
if (a.Length == 4)
|
|
||||||
{
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
// if 'a' has less than 4 elements, we pad the '0' at the end
|
|
||||||
// to make it 4.
|
|
||||||
var b = new string[4] {"0", "0", "0", "0"};
|
|
||||||
Array.Copy(a, 0, b, 0, a.Length);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an
|
|
||||||
/// optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static SemanticVersion Parse(string version)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
throw new ArgumentException(nameof(version));
|
|
||||||
|
|
||||||
if (!TryParse(version, out var semVer))
|
|
||||||
throw new ArgumentException("Invalid Version String", nameof(version));
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an
|
|
||||||
/// optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryParse(string version, out SemanticVersion value)
|
|
||||||
{
|
|
||||||
return TryParseInternal(version, SemanticVersionRegex, out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using strict semantic versioning rules that allows exactly 3 components and an optional
|
|
||||||
/// special version.
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryParseStrict(string version, out SemanticVersion value)
|
|
||||||
{
|
|
||||||
return TryParseInternal(version, StrictSemanticVersionRegex, out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryParseInternal(string version, Regex regex, out SemanticVersion semVer)
|
|
||||||
{
|
|
||||||
semVer = null;
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var match = regex.Match(version.Trim());
|
|
||||||
if (!match.Success || !Version.TryParse(match.Groups["Version"].Value, out var versionValue))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
semVer = new SemanticVersion(NormalizeVersionValue(versionValue),
|
|
||||||
match.Groups["Release"].Value.TrimStart('-'), version.Replace(" ", ""));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to parse the version token as a SemanticVersion.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An instance of SemanticVersion if it parses correctly, null otherwise.</returns>
|
|
||||||
public static SemanticVersion ParseOptionalVersion(string version)
|
|
||||||
{
|
|
||||||
TryParse(version, out var semVer);
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Version NormalizeVersionValue(Version version)
|
|
||||||
{
|
|
||||||
return new Version(version.Major,
|
|
||||||
version.Minor,
|
|
||||||
Math.Max(version.Build, 0),
|
|
||||||
Math.Max(version.Revision, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(version1, null))
|
|
||||||
return ReferenceEquals(version2, null);
|
|
||||||
return version1.Equals(version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return !(version1 == version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (version1 == null)
|
|
||||||
throw new ArgumentNullException(nameof(version1));
|
|
||||||
return version1.CompareTo(version2) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return version1 == version2 || version1 < version2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (version1 == null)
|
|
||||||
throw new ArgumentNullException(nameof(version1));
|
|
||||||
return version2 < version1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return version1 == version2 || version1 > version2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _originalString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
var semVer = obj as SemanticVersion;
|
|
||||||
return !ReferenceEquals(null, semVer) && Equals(semVer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
var hashCode = Version.GetHashCode();
|
|
||||||
if (SpecialVersion != null)
|
|
||||||
hashCode = hashCode * 4567 + SpecialVersion.GetHashCode();
|
|
||||||
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,6 +3,7 @@ using System.Drawing;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Katteker;
|
using Katteker;
|
||||||
|
using Semver;
|
||||||
using TsudaKageyu;
|
using TsudaKageyu;
|
||||||
using Vestris.ResourceLib;
|
using Vestris.ResourceLib;
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ namespace KattekerCreator
|
|||||||
|
|
||||||
public string AssemblyIconPath { get; }
|
public string AssemblyIconPath { get; }
|
||||||
|
|
||||||
public SemanticVersion AssemblyVersion { get; private set; }
|
public SemVersion AssemblyVersion { get; private set; }
|
||||||
|
|
||||||
public string Company => _company ?? string.Empty;
|
public string Company => _company ?? string.Empty;
|
||||||
|
|
||||||
@ -82,13 +83,13 @@ namespace KattekerCreator
|
|||||||
return applicationIcon;
|
return applicationIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SemanticVersion GetSemanticVersion(string productVersion)
|
private static SemVersion GetSemanticVersion(string productVersion)
|
||||||
{
|
{
|
||||||
productVersion = productVersion.Replace(',', '.');
|
productVersion = productVersion.Replace(',', '.');
|
||||||
if (SemanticVersion.TryParse(productVersion, out var semanticVersion))
|
if (SemVersion.TryParse(productVersion, out var semanticVersion))
|
||||||
return semanticVersion?.Change(build: string.Empty);
|
return semanticVersion?.Change(build: string.Empty);
|
||||||
Version.TryParse(productVersion, out var version);
|
Version.TryParse(productVersion, out var version);
|
||||||
return SemanticVersion.Parse(version.ToString(3));
|
return SemVersion.Parse(version.ToString(3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,270 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace KattekerCreator
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A hybrid implementation of SemVer that supports semantic versioning as described at http://semver.org while not
|
|
||||||
/// strictly enforcing it to
|
|
||||||
/// allow older 4-digit versioning schemes to continue working.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
//[TypeConverter(typeof(SemanticVersionTypeConverter))]
|
|
||||||
public sealed class SemanticVersion : IComparable, IComparable<SemanticVersion>, IEquatable<SemanticVersion>
|
|
||||||
{
|
|
||||||
private const RegexOptions Flags =
|
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;
|
|
||||||
|
|
||||||
private static readonly Regex SemanticVersionRegex =
|
|
||||||
new Regex(@"^(?<Version>\d+(\s*\.\s*\d+){0,3})(?<Release>-[a-z][0-9a-z-]*)?$", Flags);
|
|
||||||
|
|
||||||
private static readonly Regex StrictSemanticVersionRegex =
|
|
||||||
new Regex(@"^(?<Version>\d+(\.\d+){2})(?<Release>-[a-z][0-9a-z-]*)?$", Flags);
|
|
||||||
|
|
||||||
private readonly string _originalString;
|
|
||||||
|
|
||||||
public SemanticVersion(string version)
|
|
||||||
: this(Parse(version))
|
|
||||||
{
|
|
||||||
// The constructor normalizes the version string so that it we do not need to normalize it every time we need to operate on it.
|
|
||||||
// The original string represents the original form in which the version is represented to be used when printing.
|
|
||||||
_originalString = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int build, int revision)
|
|
||||||
: this(new Version(major, minor, build, revision))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int build, string specialVersion)
|
|
||||||
: this(new Version(major, minor, build), specialVersion)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(Version version)
|
|
||||||
: this(version, string.Empty)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(Version version, string specialVersion)
|
|
||||||
: this(version, specialVersion, null)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private SemanticVersion(Version version, string specialVersion, string originalString)
|
|
||||||
{
|
|
||||||
if (version == null)
|
|
||||||
throw new ArgumentNullException(nameof(version));
|
|
||||||
Version = NormalizeVersionValue(version);
|
|
||||||
SpecialVersion = specialVersion ?? string.Empty;
|
|
||||||
_originalString = string.IsNullOrEmpty(originalString)
|
|
||||||
? version + (!string.IsNullOrEmpty(specialVersion) ? '-' + specialVersion : null)
|
|
||||||
: originalString;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SemanticVersion(SemanticVersion semVer)
|
|
||||||
{
|
|
||||||
_originalString = semVer.ToString();
|
|
||||||
Version = semVer.Version;
|
|
||||||
SpecialVersion = semVer.SpecialVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the normalized version portion.
|
|
||||||
/// </summary>
|
|
||||||
public Version Version { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public string SpecialVersion { get; }
|
|
||||||
|
|
||||||
public int CompareTo(object obj)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(obj, null))
|
|
||||||
return 1;
|
|
||||||
var other = obj as SemanticVersion;
|
|
||||||
if (other == null)
|
|
||||||
throw new ArgumentException("Type Must Be A Semantic Version", nameof(obj));
|
|
||||||
return CompareTo(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(SemanticVersion other)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(other, null))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
var result = Version.CompareTo(other.Version);
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
var empty = string.IsNullOrEmpty(SpecialVersion);
|
|
||||||
var otherEmpty = string.IsNullOrEmpty(other.SpecialVersion);
|
|
||||||
if (empty && otherEmpty)
|
|
||||||
return 0;
|
|
||||||
if (empty)
|
|
||||||
return 1;
|
|
||||||
if (otherEmpty)
|
|
||||||
return -1;
|
|
||||||
return StringComparer.OrdinalIgnoreCase.Compare(SpecialVersion, other.SpecialVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(SemanticVersion other)
|
|
||||||
{
|
|
||||||
return !ReferenceEquals(null, other) &&
|
|
||||||
Version.Equals(other.Version) &&
|
|
||||||
SpecialVersion.Equals(other.SpecialVersion, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[] GetOriginalVersionComponents()
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(_originalString))
|
|
||||||
{
|
|
||||||
// search the start of the SpecialVersion part, if any
|
|
||||||
var dashIndex = _originalString.IndexOf('-');
|
|
||||||
var original = dashIndex != -1 ? _originalString.Substring(0, dashIndex) : _originalString;
|
|
||||||
|
|
||||||
return SplitAndPadVersionString(original);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SplitAndPadVersionString(Version.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string[] SplitAndPadVersionString(string version)
|
|
||||||
{
|
|
||||||
var a = version.Split('.');
|
|
||||||
if (a.Length == 4)
|
|
||||||
{
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if 'a' has less than 4 elements, we pad the '0' at the end
|
|
||||||
// to make it 4.
|
|
||||||
var b = new string[4] {"0", "0", "0", "0"};
|
|
||||||
Array.Copy(a, 0, b, 0, a.Length);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an
|
|
||||||
/// optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static SemanticVersion Parse(string version)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
throw new ArgumentException(nameof(version));
|
|
||||||
|
|
||||||
if (!TryParse(version, out var semVer))
|
|
||||||
throw new ArgumentException("Invalid Version String", nameof(version));
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an
|
|
||||||
/// optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryParse(string version, out SemanticVersion value)
|
|
||||||
{
|
|
||||||
return TryParseInternal(version, SemanticVersionRegex, out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using strict semantic versioning rules that allows exactly 3 components and an optional
|
|
||||||
/// special version.
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryParseStrict(string version, out SemanticVersion value)
|
|
||||||
{
|
|
||||||
return TryParseInternal(version, StrictSemanticVersionRegex, out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryParseInternal(string version, Regex regex, out SemanticVersion semVer)
|
|
||||||
{
|
|
||||||
semVer = null;
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var match = regex.Match(version.Trim());
|
|
||||||
if (!match.Success || !Version.TryParse(match.Groups["Version"].Value, out var versionValue))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
semVer = new SemanticVersion(NormalizeVersionValue(versionValue),
|
|
||||||
match.Groups["Release"].Value.TrimStart('-'), version.Replace(" ", ""));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to parse the version token as a SemanticVersion.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An instance of SemanticVersion if it parses correctly, null otherwise.</returns>
|
|
||||||
public static SemanticVersion ParseOptionalVersion(string version)
|
|
||||||
{
|
|
||||||
TryParse(version, out var semVer);
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Version NormalizeVersionValue(Version version)
|
|
||||||
{
|
|
||||||
return new Version(version.Major,
|
|
||||||
version.Minor,
|
|
||||||
Math.Max(version.Build, 0),
|
|
||||||
Math.Max(version.Revision, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(version1, null))
|
|
||||||
return ReferenceEquals(version2, null);
|
|
||||||
return version1.Equals(version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return !(version1 == version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (version1 == null)
|
|
||||||
throw new ArgumentNullException(nameof(version1));
|
|
||||||
return version1.CompareTo(version2) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return version1 == version2 || version1 < version2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (version1 == null)
|
|
||||||
throw new ArgumentNullException(nameof(version1));
|
|
||||||
return version2 < version1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return version1 == version2 || version1 > version2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _originalString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
var semVer = obj as SemanticVersion;
|
|
||||||
return !ReferenceEquals(null, semVer) && Equals(semVer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
var hashCode = Version.GetHashCode();
|
|
||||||
if (SpecialVersion != null)
|
|
||||||
hashCode = hashCode * 4567 + SpecialVersion.GetHashCode();
|
|
||||||
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Katteker;
|
using Katteker;
|
||||||
|
using Semver;
|
||||||
|
|
||||||
namespace KattekerCreator
|
namespace KattekerCreator
|
||||||
{
|
{
|
||||||
@ -16,7 +17,7 @@ namespace KattekerCreator
|
|||||||
public string Executable { get; set; }
|
public string Executable { get; set; }
|
||||||
public string CompanyName { get; set; }
|
public string CompanyName { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public SemanticVersion Version { get; set; }
|
public SemVersion Version { get; set; }
|
||||||
public Version LegacyVersion => Version.ToSystemVersion();
|
public Version LegacyVersion => Version.ToSystemVersion();
|
||||||
public string HelpUrl { get; set; }
|
public string HelpUrl { get; set; }
|
||||||
public long InstallSize { get; set; }
|
public long InstallSize { get; set; }
|
||||||
|
61
Katteker.Gui/ChangelogHelper.cs
Normal file
61
Katteker.Gui/ChangelogHelper.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Katteker.Gui
|
||||||
|
{
|
||||||
|
internal static class ChangelogHelper
|
||||||
|
{
|
||||||
|
private static string GenerateHtmlifyChangelog(string text, string extension)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
switch (extension)
|
||||||
|
{
|
||||||
|
case ".txt":
|
||||||
|
var plainText = WebUtility.HtmlEncode(text);
|
||||||
|
result = plainText.Replace(Environment.NewLine, "<br />");
|
||||||
|
break;
|
||||||
|
case ".md":
|
||||||
|
result = CommonMark.CommonMarkConverter.Convert(text);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = text;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task<string> LoadChangelogAsync(string filename, string path)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(filename) || !string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
if (!path.EndsWith("/", StringComparison.Ordinal))
|
||||||
|
path += "/";
|
||||||
|
var webReq = WebRequest.Create(path + filename);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var response = await webReq.GetResponseAsync().ConfigureAwait(false))
|
||||||
|
using (var sr = new StreamReader(response.GetResponseStream()))
|
||||||
|
{
|
||||||
|
return GenerateHtmlifyChangelog(await sr.ReadToEndAsync().ConfigureAwait(false),
|
||||||
|
Path.GetExtension(filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (WebException)
|
||||||
|
{
|
||||||
|
var changelogFilename = Path.GetFileName(filename);
|
||||||
|
if (changelogFilename == null) return GenerateHtmlifyChangelog("Changelog not found", ".txt");
|
||||||
|
var currentChangelogPath = Path.Combine(Environment.CurrentDirectory, changelogFilename);
|
||||||
|
if (File.Exists(currentChangelogPath))
|
||||||
|
{
|
||||||
|
return GenerateHtmlifyChangelog(File.ReadAllText(currentChangelogPath), Path.GetExtension(filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GenerateHtmlifyChangelog("Changelog not found", ".txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
Katteker.Gui/packages.config
Normal file
4
Katteker.Gui/packages.config
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="CommonMark.NET" version="0.15.1" targetFramework="net45" />
|
||||||
|
</packages>
|
1779
Katteker/Common/MarkdownSharp.cs
Normal file
1779
Katteker/Common/MarkdownSharp.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,85 +1,100 @@
|
|||||||
using System;
|
using System;
|
||||||
|
#if !NETSTANDARD
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Security.Permissions;
|
using System.Security.Permissions;
|
||||||
|
#endif
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Katteker
|
namespace Semver
|
||||||
{
|
{
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A semantic version implementation.
|
/// A semantic version implementation.
|
||||||
/// Conforms to v2.0.0 of http://semver.org/
|
/// Conforms to v2.0.0 of http://semver.org/
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if NETSTANDARD
|
||||||
|
public sealed class SemVersion : IComparable<SemVersion>, IComparable
|
||||||
|
#else
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public sealed class SemanticVersion : IComparable<SemanticVersion>, IComparable, ISerializable
|
public sealed class SemVersion : IComparable<SemVersion>, IComparable, ISerializable
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
private static readonly Regex parseEx =
|
static Regex parseEx =
|
||||||
new Regex(@"^(?<major>\d+)(\.(?<minor>\d+))?(\.(?<patch>\d+))?(\-(?<pre>[0-9A-Za-z\-\.]+))?(\+(?<build>[0-9A-Za-z\-\.]+))?$",
|
new Regex(@"^(?<major>\d+)" +
|
||||||
|
@"(\.(?<minor>\d+))?" +
|
||||||
|
@"(\.(?<patch>\d+))?" +
|
||||||
|
@"(\-(?<pre>[0-9A-Za-z\-\.]+))?" +
|
||||||
|
@"(\+(?<build>[0-9A-Za-z\-\.]+))?$",
|
||||||
|
#if NETSTANDARD
|
||||||
|
RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
|
||||||
|
#else
|
||||||
RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
|
RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !NETSTANDARD
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SemanticVersion" /> class.
|
/// Initializes a new instance of the <see cref="SemVersion" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <exception cref="ArgumentNullException"></exception>
|
/// <exception cref="ArgumentNullException"></exception>
|
||||||
private SemanticVersion(SerializationInfo info, StreamingContext context)
|
private SemVersion(SerializationInfo info, StreamingContext context)
|
||||||
{
|
{
|
||||||
if (info == null) throw new ArgumentNullException(nameof(info));
|
if (info == null) throw new ArgumentNullException("info");
|
||||||
var semVersion = Parse(info.GetString("SemanticVersion"));
|
var semVersion = Parse(info.GetString("SemVersion"));
|
||||||
Major = semVersion.Major;
|
Major = semVersion.Major;
|
||||||
Minor = semVersion.Minor;
|
Minor = semVersion.Minor;
|
||||||
Patch = semVersion.Patch;
|
Patch = semVersion.Patch;
|
||||||
Prerelease = semVersion.Prerelease;
|
Prerelease = semVersion.Prerelease;
|
||||||
Build = semVersion.Build;
|
Build = semVersion.Build;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SemanticVersion" /> class.
|
/// Initializes a new instance of the <see cref="SemVersion" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="major">The major version.</param>
|
/// <param name="major">The major version.</param>
|
||||||
/// <param name="minor">The minor version.</param>
|
/// <param name="minor">The minor version.</param>
|
||||||
/// <param name="patch">The patch version.</param>
|
/// <param name="patch">The patch version.</param>
|
||||||
/// <param name="prerelease">The prerelease version (eg. "alpha").</param>
|
/// <param name="prerelease">The prerelease version (eg. "alpha").</param>
|
||||||
/// <param name="build">The build eg ("nightly.232").</param>
|
/// <param name="build">The build eg ("nightly.232").</param>
|
||||||
public SemanticVersion(int major, int minor = 0, int patch = 0, string prerelease = "", string build = "")
|
public SemVersion(int major, int minor = 0, int patch = 0, string prerelease = "", string build = "")
|
||||||
{
|
{
|
||||||
Major = major;
|
this.Major = major;
|
||||||
Minor = minor;
|
this.Minor = minor;
|
||||||
Patch = patch;
|
this.Patch = patch;
|
||||||
|
|
||||||
Prerelease = prerelease ?? "";
|
this.Prerelease = prerelease ?? "";
|
||||||
Build = build ?? "";
|
this.Build = build ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SemanticVersion"/> class.
|
/// Initializes a new instance of the <see cref="SemVersion"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="version">The <see cref="System.Version"/> that is used to initialize
|
/// <param name="version">The <see cref="System.Version"/> that is used to initialize
|
||||||
/// the Major, Minor, Patch and Build properties.</param>
|
/// the Major, Minor, Patch and Build properties.</param>
|
||||||
public SemanticVersion(Version version)
|
public SemVersion(Version version)
|
||||||
{
|
{
|
||||||
if (version == null)
|
if (version == null)
|
||||||
throw new ArgumentNullException(nameof(version));
|
throw new ArgumentNullException("version");
|
||||||
|
|
||||||
Major = version.Major;
|
this.Major = version.Major;
|
||||||
Minor = version.Minor;
|
this.Minor = version.Minor;
|
||||||
|
|
||||||
if (version.Revision >= 0)
|
if (version.Revision >= 0)
|
||||||
{
|
{
|
||||||
Patch = version.Revision;
|
this.Patch = version.Revision;
|
||||||
}
|
}
|
||||||
|
|
||||||
Prerelease = string.Empty;
|
this.Prerelease = String.Empty;
|
||||||
|
|
||||||
if (version.Build > 0)
|
if (version.Build > 0)
|
||||||
{
|
{
|
||||||
Build = version.Build.ToString();
|
this.Build = version.Build.ToString();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Build = string.Empty;
|
this.Build = String.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,21 +103,29 @@ namespace Katteker
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="version">The version string.</param>
|
/// <param name="version">The version string.</param>
|
||||||
/// <param name="strict">If set to <c>true</c> minor and patch version are required, else they default to 0.</param>
|
/// <param name="strict">If set to <c>true</c> minor and patch version are required, else they default to 0.</param>
|
||||||
/// <returns>The SemanticVersion object.</returns>
|
/// <returns>The SemVersion object.</returns>
|
||||||
/// <exception cref="System.InvalidOperationException">When a invalid version string is passed.</exception>
|
/// <exception cref="System.InvalidOperationException">When a invalid version string is passed.</exception>
|
||||||
public static SemanticVersion Parse(string version, bool strict = false)
|
public static SemVersion Parse(string version, bool strict = false)
|
||||||
{
|
{
|
||||||
var match = parseEx.Match(version);
|
var match = parseEx.Match(version);
|
||||||
if (!match.Success)
|
if (!match.Success)
|
||||||
throw new ArgumentException("Invalid version.", nameof(version));
|
throw new ArgumentException("Invalid version.", "version");
|
||||||
|
|
||||||
|
#if NETSTANDARD
|
||||||
|
var major = int.Parse(match.Groups["major"].Value);
|
||||||
|
#else
|
||||||
var major = int.Parse(match.Groups["major"].Value, CultureInfo.InvariantCulture);
|
var major = int.Parse(match.Groups["major"].Value, CultureInfo.InvariantCulture);
|
||||||
|
#endif
|
||||||
|
|
||||||
var minorMatch = match.Groups["minor"];
|
var minorMatch = match.Groups["minor"];
|
||||||
var minor = 0;
|
int minor = 0;
|
||||||
if (minorMatch.Success)
|
if (minorMatch.Success)
|
||||||
{
|
{
|
||||||
|
#if NETSTANDARD
|
||||||
|
minor = int.Parse(minorMatch.Value);
|
||||||
|
#else
|
||||||
minor = int.Parse(minorMatch.Value, CultureInfo.InvariantCulture);
|
minor = int.Parse(minorMatch.Value, CultureInfo.InvariantCulture);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (strict)
|
else if (strict)
|
||||||
{
|
{
|
||||||
@ -110,10 +133,14 @@ namespace Katteker
|
|||||||
}
|
}
|
||||||
|
|
||||||
var patchMatch = match.Groups["patch"];
|
var patchMatch = match.Groups["patch"];
|
||||||
var patch = 0;
|
int patch = 0;
|
||||||
if (patchMatch.Success)
|
if (patchMatch.Success)
|
||||||
{
|
{
|
||||||
|
#if NETSTANDARD
|
||||||
|
patch = int.Parse(patchMatch.Value);
|
||||||
|
#else
|
||||||
patch = int.Parse(patchMatch.Value, CultureInfo.InvariantCulture);
|
patch = int.Parse(patchMatch.Value, CultureInfo.InvariantCulture);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (strict)
|
else if (strict)
|
||||||
{
|
{
|
||||||
@ -123,19 +150,19 @@ namespace Katteker
|
|||||||
var prerelease = match.Groups["pre"].Value;
|
var prerelease = match.Groups["pre"].Value;
|
||||||
var build = match.Groups["build"].Value;
|
var build = match.Groups["build"].Value;
|
||||||
|
|
||||||
return new SemanticVersion(major, minor, patch, prerelease, build);
|
return new SemVersion(major, minor, patch, prerelease, build);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses the specified string to a semantic version.
|
/// Parses the specified string to a semantic version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="version">The version string.</param>
|
/// <param name="version">The version string.</param>
|
||||||
/// <param name="semver">When the method returns, contains a SemanticVersion instance equivalent
|
/// <param name="semver">When the method returns, contains a SemVersion instance equivalent
|
||||||
/// to the version string passed in, if the version string was valid, or <c>null</c> if the
|
/// to the version string passed in, if the version string was valid, or <c>null</c> if the
|
||||||
/// version string was not valid.</param>
|
/// version string was not valid.</param>
|
||||||
/// <param name="strict">If set to <c>true</c> minor and patch version are required, else they default to 0.</param>
|
/// <param name="strict">If set to <c>true</c> minor and patch version are required, else they default to 0.</param>
|
||||||
/// <returns><c>False</c> when a invalid version string is passed, otherwise <c>true</c>.</returns>
|
/// <returns><c>False</c> when a invalid version string is passed, otherwise <c>true</c>.</returns>
|
||||||
public static bool TryParse(string version, out SemanticVersion semver, bool strict = false)
|
public static bool TryParse(string version, out SemVersion semver, bool strict = false)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -155,7 +182,7 @@ namespace Katteker
|
|||||||
/// <param name="versionA">The first version.</param>
|
/// <param name="versionA">The first version.</param>
|
||||||
/// <param name="versionB">The second version.</param>
|
/// <param name="versionB">The second version.</param>
|
||||||
/// <returns>If versionA is equal to versionB <c>true</c>, else <c>false</c>.</returns>
|
/// <returns>If versionA is equal to versionB <c>true</c>, else <c>false</c>.</returns>
|
||||||
public static bool Equals(SemanticVersion versionA, SemanticVersion versionB)
|
public static bool Equals(SemVersion versionA, SemVersion versionB)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(versionA, null))
|
if (ReferenceEquals(versionA, null))
|
||||||
return ReferenceEquals(versionB, null);
|
return ReferenceEquals(versionB, null);
|
||||||
@ -169,7 +196,7 @@ namespace Katteker
|
|||||||
/// <param name="versionB">The version to compare against.</param>
|
/// <param name="versionB">The version to compare against.</param>
|
||||||
/// <returns>If versionA < versionB <c>< 0</c>, if versionA > versionB <c>> 0</c>,
|
/// <returns>If versionA < versionB <c>< 0</c>, if versionA > versionB <c>> 0</c>,
|
||||||
/// if versionA is equal to versionB <c>0</c>.</returns>
|
/// if versionA is equal to versionB <c>0</c>.</returns>
|
||||||
public static int Compare(SemanticVersion versionA, SemanticVersion versionB)
|
public static int Compare(SemVersion versionA, SemVersion versionB)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(versionA, null))
|
if (ReferenceEquals(versionA, null))
|
||||||
return ReferenceEquals(versionB, null) ? 0 : -1;
|
return ReferenceEquals(versionB, null) ? 0 : -1;
|
||||||
@ -185,15 +212,15 @@ namespace Katteker
|
|||||||
/// <param name="prerelease">The prerelease text.</param>
|
/// <param name="prerelease">The prerelease text.</param>
|
||||||
/// <param name="build">The build text.</param>
|
/// <param name="build">The build text.</param>
|
||||||
/// <returns>The new version object.</returns>
|
/// <returns>The new version object.</returns>
|
||||||
public SemanticVersion Change(int? major = null, int? minor = null, int? patch = null,
|
public SemVersion Change(int? major = null, int? minor = null, int? patch = null,
|
||||||
string prerelease = null, string build = null)
|
string prerelease = null, string build = null)
|
||||||
{
|
{
|
||||||
return new SemanticVersion(
|
return new SemVersion(
|
||||||
major ?? Major,
|
major ?? this.Major,
|
||||||
minor ?? Minor,
|
minor ?? this.Minor,
|
||||||
patch ?? Patch,
|
patch ?? this.Patch,
|
||||||
prerelease ?? Prerelease,
|
prerelease ?? this.Prerelease,
|
||||||
build ?? Build);
|
build ?? this.Build);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -245,9 +272,9 @@ namespace Katteker
|
|||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
var version = "" + Major + "." + Minor + "." + Patch;
|
var version = "" + Major + "." + Minor + "." + Patch;
|
||||||
if (!string.IsNullOrEmpty(Prerelease))
|
if (!String.IsNullOrEmpty(Prerelease))
|
||||||
version += "-" + Prerelease;
|
version += "-" + Prerelease;
|
||||||
if (!string.IsNullOrEmpty(Build))
|
if (!String.IsNullOrEmpty(Build))
|
||||||
version += "+" + Build;
|
version += "+" + Build;
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
@ -267,7 +294,7 @@ namespace Katteker
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public int CompareTo(object obj)
|
public int CompareTo(object obj)
|
||||||
{
|
{
|
||||||
return CompareTo((SemanticVersion)obj);
|
return CompareTo((SemVersion)obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -283,16 +310,16 @@ namespace Katteker
|
|||||||
/// Zero This instance occurs in the same position in the sort order as <paramref name="other" />. i
|
/// Zero This instance occurs in the same position in the sort order as <paramref name="other" />. i
|
||||||
/// Greater than zero This instance follows <paramref name="other" /> in the sort order.
|
/// Greater than zero This instance follows <paramref name="other" /> in the sort order.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public int CompareTo(SemanticVersion other)
|
public int CompareTo(SemVersion other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(other, null))
|
if (ReferenceEquals(other, null))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
var r = CompareByPrecedence(other);
|
var r = this.CompareByPrecedence(other);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = CompareComponent(Build, other.Build);
|
r = CompareComponent(this.Build, other.Build);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +328,7 @@ namespace Katteker
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="other">The semantic version.</param>
|
/// <param name="other">The semantic version.</param>
|
||||||
/// <returns><c>true</c> if the version precedence matches.</returns>
|
/// <returns><c>true</c> if the version precedence matches.</returns>
|
||||||
public bool PrecedenceMatches(SemanticVersion other)
|
public bool PrecedenceMatches(SemVersion other)
|
||||||
{
|
{
|
||||||
return CompareByPrecedence(other) == 0;
|
return CompareByPrecedence(other) == 0;
|
||||||
}
|
}
|
||||||
@ -317,28 +344,28 @@ namespace Katteker
|
|||||||
/// Zero This instance has the same precedence as <paramref name="other" />. i
|
/// Zero This instance has the same precedence as <paramref name="other" />. i
|
||||||
/// Greater than zero This instance has creater precedence as <paramref name="other" />.
|
/// Greater than zero This instance has creater precedence as <paramref name="other" />.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public int CompareByPrecedence(SemanticVersion other)
|
public int CompareByPrecedence(SemVersion other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(other, null))
|
if (ReferenceEquals(other, null))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
var r = Major.CompareTo(other.Major);
|
var r = this.Major.CompareTo(other.Major);
|
||||||
if (r != 0) return r;
|
if (r != 0) return r;
|
||||||
|
|
||||||
r = Minor.CompareTo(other.Minor);
|
r = this.Minor.CompareTo(other.Minor);
|
||||||
if (r != 0) return r;
|
if (r != 0) return r;
|
||||||
|
|
||||||
r = Patch.CompareTo(other.Patch);
|
r = this.Patch.CompareTo(other.Patch);
|
||||||
if (r != 0) return r;
|
if (r != 0) return r;
|
||||||
|
|
||||||
r = CompareComponent(Prerelease, other.Prerelease, true);
|
r = CompareComponent(this.Prerelease, other.Prerelease, true);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CompareComponent(string a, string b, bool lower = false)
|
static int CompareComponent(string a, string b, bool lower = false)
|
||||||
{
|
{
|
||||||
var aEmpty = string.IsNullOrEmpty(a);
|
var aEmpty = String.IsNullOrEmpty(a);
|
||||||
var bEmpty = string.IsNullOrEmpty(b);
|
var bEmpty = String.IsNullOrEmpty(b);
|
||||||
if (aEmpty && bEmpty)
|
if (aEmpty && bEmpty)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -351,13 +378,13 @@ namespace Katteker
|
|||||||
var bComps = b.Split('.');
|
var bComps = b.Split('.');
|
||||||
|
|
||||||
var minLen = Math.Min(aComps.Length, bComps.Length);
|
var minLen = Math.Min(aComps.Length, bComps.Length);
|
||||||
for (var i = 0; i < minLen; i++)
|
for (int i = 0; i < minLen; i++)
|
||||||
{
|
{
|
||||||
var ac = aComps[i];
|
var ac = aComps[i];
|
||||||
var bc = bComps[i];
|
var bc = bComps[i];
|
||||||
int anum, bnum;
|
int anum, bnum;
|
||||||
var isanum = int.TryParse(ac, out anum);
|
var isanum = Int32.TryParse(ac, out anum);
|
||||||
var isbnum = int.TryParse(bc, out bnum);
|
var isbnum = Int32.TryParse(bc, out bnum);
|
||||||
int r;
|
int r;
|
||||||
if (isanum && isbnum)
|
if (isanum && isbnum)
|
||||||
{
|
{
|
||||||
@ -370,7 +397,7 @@ namespace Katteker
|
|||||||
return -1;
|
return -1;
|
||||||
if (isbnum)
|
if (isbnum)
|
||||||
return 1;
|
return 1;
|
||||||
r = string.CompareOrdinal(ac, bc);
|
r = String.CompareOrdinal(ac, bc);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -394,13 +421,13 @@ namespace Katteker
|
|||||||
if (ReferenceEquals(this, obj))
|
if (ReferenceEquals(this, obj))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var other = (SemanticVersion)obj;
|
var other = (SemVersion)obj;
|
||||||
|
|
||||||
return Major == other.Major &&
|
return this.Major == other.Major &&
|
||||||
Minor == other.Minor &&
|
this.Minor == other.Minor &&
|
||||||
Patch == other.Patch &&
|
this.Patch == other.Patch &&
|
||||||
string.Equals(Prerelease, other.Prerelease, StringComparison.Ordinal) &&
|
string.Equals(this.Prerelease, other.Prerelease, StringComparison.Ordinal) &&
|
||||||
string.Equals(Build, other.Build, StringComparison.Ordinal);
|
string.Equals(this.Build, other.Build, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -413,11 +440,11 @@ namespace Katteker
|
|||||||
{
|
{
|
||||||
unchecked
|
unchecked
|
||||||
{
|
{
|
||||||
var result = Major.GetHashCode();
|
int result = this.Major.GetHashCode();
|
||||||
result = result * 31 + Minor.GetHashCode();
|
result = result * 31 + this.Minor.GetHashCode();
|
||||||
result = result * 31 + Patch.GetHashCode();
|
result = result * 31 + this.Patch.GetHashCode();
|
||||||
result = result * 31 + Prerelease.GetHashCode();
|
result = result * 31 + this.Prerelease.GetHashCode();
|
||||||
result = result * 31 + Build.GetHashCode();
|
result = result * 31 + this.Build.GetHashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,19 +453,19 @@ namespace Katteker
|
|||||||
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
|
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
|
||||||
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||||
{
|
{
|
||||||
if (info == null) throw new ArgumentNullException(nameof(info));
|
if (info == null) throw new ArgumentNullException("info");
|
||||||
info.AddValue("SemanticVersion", ToString());
|
info.AddValue("SemVersion", ToString());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implicit conversion from string to SemanticVersion.
|
/// Implicit conversion from string to SemVersion.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="version">The semantic version.</param>
|
/// <param name="version">The semantic version.</param>
|
||||||
/// <returns>The SemanticVersion object.</returns>
|
/// <returns>The SemVersion object.</returns>
|
||||||
public static implicit operator SemanticVersion(string version)
|
public static implicit operator SemVersion(string version)
|
||||||
{
|
{
|
||||||
return Parse(version);
|
return SemVersion.Parse(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -447,9 +474,9 @@ namespace Katteker
|
|||||||
/// <param name="left">The left value.</param>
|
/// <param name="left">The left value.</param>
|
||||||
/// <param name="right">The right value.</param>
|
/// <param name="right">The right value.</param>
|
||||||
/// <returns>If left is equal to right <c>true</c>, else <c>false</c>.</returns>
|
/// <returns>If left is equal to right <c>true</c>, else <c>false</c>.</returns>
|
||||||
public static bool operator ==(SemanticVersion left, SemanticVersion right)
|
public static bool operator ==(SemVersion left, SemVersion right)
|
||||||
{
|
{
|
||||||
return Equals(left, right);
|
return SemVersion.Equals(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -458,9 +485,9 @@ namespace Katteker
|
|||||||
/// <param name="left">The left value.</param>
|
/// <param name="left">The left value.</param>
|
||||||
/// <param name="right">The right value.</param>
|
/// <param name="right">The right value.</param>
|
||||||
/// <returns>If left is not equal to right <c>true</c>, else <c>false</c>.</returns>
|
/// <returns>If left is not equal to right <c>true</c>, else <c>false</c>.</returns>
|
||||||
public static bool operator !=(SemanticVersion left, SemanticVersion right)
|
public static bool operator !=(SemVersion left, SemVersion right)
|
||||||
{
|
{
|
||||||
return !Equals(left, right);
|
return !SemVersion.Equals(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -469,9 +496,9 @@ namespace Katteker
|
|||||||
/// <param name="left">The left value.</param>
|
/// <param name="left">The left value.</param>
|
||||||
/// <param name="right">The right value.</param>
|
/// <param name="right">The right value.</param>
|
||||||
/// <returns>If left is greater than right <c>true</c>, else <c>false</c>.</returns>
|
/// <returns>If left is greater than right <c>true</c>, else <c>false</c>.</returns>
|
||||||
public static bool operator >(SemanticVersion left, SemanticVersion right)
|
public static bool operator >(SemVersion left, SemVersion right)
|
||||||
{
|
{
|
||||||
return Compare(left, right) > 0;
|
return SemVersion.Compare(left, right) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -480,7 +507,7 @@ namespace Katteker
|
|||||||
/// <param name="left">The left value.</param>
|
/// <param name="left">The left value.</param>
|
||||||
/// <param name="right">The right value.</param>
|
/// <param name="right">The right value.</param>
|
||||||
/// <returns>If left is greater than or equal to right <c>true</c>, else <c>false</c>.</returns>
|
/// <returns>If left is greater than or equal to right <c>true</c>, else <c>false</c>.</returns>
|
||||||
public static bool operator >=(SemanticVersion left, SemanticVersion right)
|
public static bool operator >=(SemVersion left, SemVersion right)
|
||||||
{
|
{
|
||||||
return left == right || left > right;
|
return left == right || left > right;
|
||||||
}
|
}
|
||||||
@ -491,9 +518,9 @@ namespace Katteker
|
|||||||
/// <param name="left">The left value.</param>
|
/// <param name="left">The left value.</param>
|
||||||
/// <param name="right">The right value.</param>
|
/// <param name="right">The right value.</param>
|
||||||
/// <returns>If left is less than right <c>true</c>, else <c>false</c>.</returns>
|
/// <returns>If left is less than right <c>true</c>, else <c>false</c>.</returns>
|
||||||
public static bool operator <(SemanticVersion left, SemanticVersion right)
|
public static bool operator <(SemVersion left, SemVersion right)
|
||||||
{
|
{
|
||||||
return Compare(left, right) < 0;
|
return SemVersion.Compare(left, right) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -502,10 +529,9 @@ namespace Katteker
|
|||||||
/// <param name="left">The left value.</param>
|
/// <param name="left">The left value.</param>
|
||||||
/// <param name="right">The right value.</param>
|
/// <param name="right">The right value.</param>
|
||||||
/// <returns>If left is less than or equal to right <c>true</c>, else <c>false</c>.</returns>
|
/// <returns>If left is less than or equal to right <c>true</c>, else <c>false</c>.</returns>
|
||||||
public static bool operator <=(SemanticVersion left, SemanticVersion right)
|
public static bool operator <=(SemVersion left, SemVersion right)
|
||||||
{
|
{
|
||||||
return left == right || left < right;
|
return left == right || left < right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
|
|
||||||
}
|
}
|
@ -20,7 +20,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// File of the releases.
|
/// File of the releases.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string RELEASE = "RELEASE";
|
public const string Release = "RELEASE";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the
|
/// Name of the
|
||||||
|
@ -39,10 +39,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ChangelogHelper.cs" />
|
<Compile Include="ChangelogHelper.cs" />
|
||||||
|
<Compile Include="Common\SemVersion.cs" />
|
||||||
<Compile Include="Constants.cs" />
|
<Compile Include="Constants.cs" />
|
||||||
<Compile Include="KattekerConfig.cs" />
|
<Compile Include="KattekerConfig.cs" />
|
||||||
<Compile Include="MarkdownSharp.cs" />
|
<Compile Include="Common\MarkdownSharp.cs" />
|
||||||
<Compile Include="SemanticVersion.cs" />
|
|
||||||
<Compile Include="UpdateInfo.cs" />
|
<Compile Include="UpdateInfo.cs" />
|
||||||
<Compile Include="UpdateManager.cs" />
|
<Compile Include="UpdateManager.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using Semver;
|
||||||
|
|
||||||
namespace Katteker
|
namespace Katteker
|
||||||
{
|
{
|
||||||
public class ReleaseEntry : IComparable<ReleaseEntry>, IComparable
|
public class ReleaseEntry : IComparable<ReleaseEntry>, IComparable
|
||||||
{
|
{
|
||||||
public const string FilenameRegex = @"(^.*)-((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?).*-(full|delta)";
|
private const string FilenameRegex = @"(^.*)-((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?).*-(full|delta)";
|
||||||
|
|
||||||
private const char Seperator = '|';
|
private const char Seperator = '|';
|
||||||
|
|
||||||
public ReleaseEntry(string filename, SemanticVersion version, long fileSize, bool isDelta, string sha1)
|
public ReleaseEntry(string filename, SemVersion version, long fileSize, bool isDelta, string sha1)
|
||||||
{
|
{
|
||||||
Filename = filename;
|
Filename = filename;
|
||||||
Version = version;
|
Version = version;
|
||||||
@ -29,17 +30,17 @@ namespace Katteker
|
|||||||
var fileSegments = Regex.Match(Filename, FilenameRegex);
|
var fileSegments = Regex.Match(Filename, FilenameRegex);
|
||||||
if (fileSegments.Groups.Count < 3) throw new ArgumentOutOfRangeException("Filename is not compilant.");
|
if (fileSegments.Groups.Count < 3) throw new ArgumentOutOfRangeException("Filename is not compilant.");
|
||||||
ApplicationName = fileSegments.Groups[1].Value;
|
ApplicationName = fileSegments.Groups[1].Value;
|
||||||
Version = SemanticVersion.Parse(fileSegments.Groups[2].Value);
|
Version = SemVersion.Parse(fileSegments.Groups[2].Value);
|
||||||
IsDelta = fileSegments.Groups[3].Value != "full";
|
IsDelta = fileSegments.Groups[3].Value != "full";
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReleaseEntry(string applicationName, SemanticVersion version)
|
public ReleaseEntry(string applicationName, SemVersion version)
|
||||||
{
|
{
|
||||||
ApplicationName = applicationName;
|
ApplicationName = applicationName;
|
||||||
Version = version;
|
Version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SemanticVersion Version { get; }
|
public SemVersion Version { get; }
|
||||||
public string SHA1 { get; }
|
public string SHA1 { get; }
|
||||||
public string Filename { get; }
|
public string Filename { get; }
|
||||||
public long Filesize { get; }
|
public long Filesize { get; }
|
||||||
@ -53,8 +54,8 @@ namespace Katteker
|
|||||||
public int CompareTo(ReleaseEntry other)
|
public int CompareTo(ReleaseEntry other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(this, other)) return 0;
|
if (ReferenceEquals(this, other)) return 0;
|
||||||
if (ReferenceEquals(null, other)) return 1;
|
if (other is null) return 1;
|
||||||
var versionComparison = Comparer<SemanticVersion>.Default.Compare(Version, other.Version);
|
var versionComparison = Comparer<SemVersion>.Default.Compare(Version, other.Version);
|
||||||
if (versionComparison != 0) return versionComparison;
|
if (versionComparison != 0) return versionComparison;
|
||||||
return string.Compare(Filename, other.Filename, StringComparison.Ordinal);
|
return string.Compare(Filename, other.Filename, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Semver;
|
||||||
|
|
||||||
namespace Katteker
|
namespace Katteker
|
||||||
{
|
{
|
||||||
@ -9,16 +10,16 @@ namespace Katteker
|
|||||||
{
|
{
|
||||||
private readonly string _filePath;
|
private readonly string _filePath;
|
||||||
|
|
||||||
private SortedList<SemanticVersion, ReleaseEntry> ReleaseEntries { get; }
|
private SortedList<SemVersion, ReleaseEntry> ReleaseEntries { get; }
|
||||||
|
|
||||||
private Releases()
|
private Releases()
|
||||||
{
|
{
|
||||||
ReleaseEntries = new SortedList<SemanticVersion, ReleaseEntry>();
|
ReleaseEntries = new SortedList<SemVersion, ReleaseEntry>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Releases(string path) : this()
|
public Releases(string path) : this()
|
||||||
{
|
{
|
||||||
_filePath = Path.Combine(path, Constants.RELEASE);
|
_filePath = Path.Combine(path, Constants.Release);
|
||||||
if (!File.Exists(_filePath)) return;
|
if (!File.Exists(_filePath)) return;
|
||||||
AddRange(File.ReadAllLines(_filePath));
|
AddRange(File.ReadAllLines(_filePath));
|
||||||
}
|
}
|
||||||
@ -48,7 +49,7 @@ namespace Katteker
|
|||||||
/// <param name="setupFilePath">Path to setup-file</param>
|
/// <param name="setupFilePath">Path to setup-file</param>
|
||||||
/// <param name="version">Version of setup-file</param>
|
/// <param name="version">Version of setup-file</param>
|
||||||
/// <returns>Returns true if newest version.</returns>
|
/// <returns>Returns true if newest version.</returns>
|
||||||
public ReleaseEntry Add(string setupFilePath, SemanticVersion version)
|
public ReleaseEntry Add(string setupFilePath, SemVersion version)
|
||||||
{
|
{
|
||||||
var sha1 = Utility.ComputeFileHash(setupFilePath);
|
var sha1 = Utility.ComputeFileHash(setupFilePath);
|
||||||
var setupFile = new FileInfo(setupFilePath);
|
var setupFile = new FileInfo(setupFilePath);
|
||||||
|
@ -4,18 +4,12 @@ namespace Katteker
|
|||||||
{
|
{
|
||||||
public class UpdateInfo
|
public class UpdateInfo
|
||||||
{
|
{
|
||||||
private readonly Releases _releases;
|
public ReleaseEntry CurrentlyInstalledVersion { get; }
|
||||||
public ReleaseEntry CurrentlyInstalledVersion { get; protected set; }
|
|
||||||
|
|
||||||
public ReleaseEntry FutureReleaseEntry { get; protected set; }
|
|
||||||
|
|
||||||
public List<ReleaseEntry> ReleasesToApply { get; protected set; } = new List<ReleaseEntry>();
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<ReleaseEntry> ReleasesToApply { get; } = new List<ReleaseEntry>();
|
||||||
|
|
||||||
public UpdateInfo(string applicationName, Releases releases)
|
public UpdateInfo(string applicationName, Releases releases)
|
||||||
{
|
{
|
||||||
_releases = releases;
|
|
||||||
CurrentlyInstalledVersion = new ReleaseEntry(applicationName, VersionExtension.GetCurrentVersion);
|
CurrentlyInstalledVersion = new ReleaseEntry(applicationName, VersionExtension.GetCurrentVersion);
|
||||||
foreach (var release in releases)
|
foreach (var release in releases)
|
||||||
{
|
{
|
||||||
|
@ -123,7 +123,7 @@ namespace Katteker
|
|||||||
private static async Task<Releases> DownloadIndexAsync(string urlOrPath)
|
private static async Task<Releases> DownloadIndexAsync(string urlOrPath)
|
||||||
{
|
{
|
||||||
var url = urlOrPath.TrimEnd('/');
|
var url = urlOrPath.TrimEnd('/');
|
||||||
url += "/" + Constants.RELEASE;
|
url += "/" + Constants.Release;
|
||||||
var content = await new WebClient().DownloadStringTaskAsync(url).ConfigureAwait(false);
|
var content = await new WebClient().DownloadStringTaskAsync(url).ConfigureAwait(false);
|
||||||
var lines = content.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
|
var lines = content.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
return new Releases(lines);
|
return new Releases(lines);
|
||||||
|
@ -5,6 +5,9 @@ using System.Security.Cryptography;
|
|||||||
|
|
||||||
namespace Katteker
|
namespace Katteker
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utilities.
|
||||||
|
/// </summary>
|
||||||
public static class Utility
|
public static class Utility
|
||||||
{
|
{
|
||||||
internal static string GetLocalAppDataDirectory()
|
internal static string GetLocalAppDataDirectory()
|
||||||
@ -17,12 +20,23 @@ namespace Katteker
|
|||||||
return Assembly.GetEntryAssembly().GetName().Name;
|
return Assembly.GetEntryAssembly().GetName().Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is true if the url is a web-address. False otherwise.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="urlOrPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static bool IsWebUrl(string urlOrPath)
|
public static bool IsWebUrl(string urlOrPath)
|
||||||
{
|
{
|
||||||
var uri = new Uri(urlOrPath);
|
var uri = new Uri(urlOrPath);
|
||||||
return uri.Scheme == "http" || uri.Scheme == "https";
|
return uri.Scheme == "http" || uri.Scheme == "https";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute file hash with SHA1.
|
||||||
|
/// If the file is greater than 5 MB, the hash will only computed with the first 5 MB.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static string ComputeFileHash(string filename)
|
public static string ComputeFileHash(string filename)
|
||||||
{
|
{
|
||||||
string sha1;
|
string sha1;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Semver;
|
||||||
|
|
||||||
namespace Katteker
|
namespace Katteker
|
||||||
{
|
{
|
||||||
@ -11,20 +12,25 @@ namespace Katteker
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the current Version of Application.
|
/// Get the current Version of Application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static SemanticVersion GetCurrentVersion
|
public static SemVersion GetCurrentVersion
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var assemblyVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(3);
|
var assemblyVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(3);
|
||||||
var getCurrentVersion = SemanticVersion.Parse(assemblyVersion);
|
var getCurrentVersion = SemVersion.Parse(assemblyVersion);
|
||||||
var informalVersion = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
var informalVersion = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
||||||
if (informalVersion != null && SemanticVersion.TryParse(informalVersion, out var semVersion))
|
if (informalVersion != null && SemVersion.TryParse(informalVersion, out var semVersion))
|
||||||
return semVersion;
|
return semVersion;
|
||||||
return getCurrentVersion;
|
return getCurrentVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Version ToSystemVersion(this SemanticVersion value) => new Version(value.Major, value.Minor, value.Patch, 0);
|
/// <summary>
|
||||||
|
/// Convert to cenventional System.Version instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Version ToSystemVersion(this SemVersion value) => new Version(value.Major, value.Minor, value.Patch, 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the current Version of Application.
|
/// Get the current Version of Application.
|
||||||
|
12
README.md
12
README.md
@ -1,20 +1,16 @@
|
|||||||
Katteker
|
SquirrelKiller (aka Wombat)
|
||||||
=============
|
=============
|
||||||
Aktuell:
|
|
||||||
|
|
||||||
|
Ziele:
|
||||||
-------------
|
-------------
|
||||||
|
- Automatische Updates, auch für nicht verwaltete Software.
|
||||||
|
- Popup unten rechts mit Informationen über Update.
|
||||||
- Paket erstellt mit NSIS.
|
- Paket erstellt mit NSIS.
|
||||||
- schnellere Verteilung.
|
- schnellere Verteilung.
|
||||||
- Schnellere Paketerstellung ohne Umwege.
|
- Schnellere Paketerstellung ohne Umwege.
|
||||||
- AppStub übernimmt die Resourcen der Executable. (Icon, Name, Version, Copyright, Beschreibung, etc)
|
- AppStub übernimmt die Resourcen der Executable. (Icon, Name, Version, Copyright, Beschreibung, etc)
|
||||||
[ResourceLib C# File Resource Management Library](https://github.com/dblock/resourcelib)
|
[ResourceLib C# File Resource Management Library](https://github.com/dblock/resourcelib)
|
||||||
|
|
||||||
Zukunft:
|
|
||||||
-------------
|
|
||||||
- Automatische Updates, auch für nicht verwaltete Software.
|
|
||||||
- Popup unten rechts mit Informationen über Update.
|
|
||||||
|
|
||||||
Creator:
|
Creator:
|
||||||
-------------
|
-------------
|
||||||
- Informationen der Anwendung auslesen
|
- Informationen der Anwendung auslesen
|
||||||
|
Loading…
x
Reference in New Issue
Block a user