Replaced SemanticVersion.cs with the unmodified SemVersion.cs from original author.

This commit is contained in:
Holger Börchers 2018-03-23 21:34:14 +01:00
parent 09d362eac1
commit 64a2c35c0c
20 changed files with 2022 additions and 944 deletions

View File

@ -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" />

View File

@ -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)

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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));
} }
} }
} }

View File

@ -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;
}
}
}

View File

@ -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; }

View 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");
}
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommonMark.NET" version="0.15.1" targetFramework="net45" />
</packages>

File diff suppressed because it is too large Load Diff

View File

@ -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 &lt; versionB <c>&lt; 0</c>, if versionA &gt; versionB <c>&gt; 0</c>, /// <returns>If versionA &lt; versionB <c>&lt; 0</c>, if versionA &gt; versionB <c>&gt; 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
} }

View File

@ -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

View File

@ -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" />

View File

@ -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);
} }

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -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