Initial commit
This commit is contained in:
6
AppStub/App.config
Normal file
6
AppStub/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
53
AppStub/AppStub.csproj
Normal file
53
AppStub/AppStub.csproj
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E746AE0F-BEEA-4C18-9ED8-2E708ED00A5B}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>AppStub</RootNamespace>
|
||||
<AssemblyName>AppStub</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Katteker\SemanticVersion.cs">
|
||||
<Link>SemanticVersion.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
78
AppStub/Program.cs
Normal file
78
AppStub/Program.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using Katteker;
|
||||
|
||||
namespace AppStub
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
[STAThread]
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
try
|
||||
{
|
||||
var commandline = string.Join(" ", args);
|
||||
var location = new FileInfo(Assembly.GetExecutingAssembly().Location);
|
||||
var directory = location.Directory;
|
||||
if (directory == null) return;
|
||||
var files = directory.EnumerateFiles(location.Name, SearchOption.AllDirectories)
|
||||
.Where(x => x.Directory?.Name.StartsWith("app-") == true);
|
||||
|
||||
var entries = new SortedList<SemanticVersion, FileInfo>();
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
var version = SemanticVersion.TryParse(file.Directory?.Name.Replace("app-", ""), out var value)
|
||||
? value
|
||||
: new SemanticVersion(0);
|
||||
entries.Add(version, file);
|
||||
}
|
||||
|
||||
var latestVersion = entries.LastOrDefault().Value;
|
||||
if (latestVersion == null) throw new FileNotFoundException();
|
||||
DeleteOldVersionDirectories(entries.Where(x => x.Value != latestVersion));
|
||||
using (var process = new Process())
|
||||
{
|
||||
process.StartInfo =
|
||||
new ProcessStartInfo(latestVersion.FullName)
|
||||
{
|
||||
Arguments = commandline,
|
||||
WorkingDirectory = latestVersion.DirectoryName ?? Assembly.GetExecutingAssembly().Location,
|
||||
UseShellExecute = false
|
||||
};
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeleteOldVersionDirectories(IEnumerable<KeyValuePair<SemanticVersion, FileInfo>> dirEntries)
|
||||
{
|
||||
#if !DEBUG
|
||||
foreach (var directoryInfo in dirEntries)
|
||||
{
|
||||
try
|
||||
{
|
||||
directoryInfo.Value.Directory?.Delete(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// silently ignore
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
35
AppStub/Properties/AssemblyInfo.cs
Normal file
35
AppStub/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die einer Assembly zugeordnet sind.
|
||||
[assembly: AssemblyTitle("AppStub")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AppStub")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
|
||||
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("e746ae0f-beea-4c18-9ed8-2e708ed00a5b")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
268
AppStub/SemanticVersion.cs
Normal file
268
AppStub/SemanticVersion.cs
Normal file
@ -0,0 +1,268 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user