Skip to content

Commit

Permalink
Merge pull request #164 from SubnauticaModding/FixVersionTrimming
Browse files Browse the repository at this point in the history
Version strings now all implicity treated as having 4 groups with trailing zeros
  • Loading branch information
toebeann authored Aug 4, 2020
2 parents fcc49f5 + fef7091 commit 7ef0a21
Show file tree
Hide file tree
Showing 28 changed files with 235 additions and 60 deletions.
Binary file modified Build/InstallerExtensions.dll
Binary file not shown.
Binary file modified Build/QModInstaller.dll
Binary file not shown.
57 changes: 57 additions & 0 deletions Build/QModInstaller.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified Build/QModManager.QMMHarmonyShimmer.dll
Binary file not shown.
Binary file modified Build/QModManager.QMMLoader.dll
Binary file not shown.
Binary file modified Build/QModManager.QModPluginGenerator.dll
Binary file not shown.
Binary file modified Build/QModManager.UnityAudioFixer.dll
Binary file not shown.
Binary file modified Build/QModManager.exe
Binary file not shown.
Binary file modified Build/QModManager_Setup.exe
Binary file not shown.
Binary file added Build/VortexPackage.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion Data/latest-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.0.0.0
4.0.1.0
4 changes: 2 additions & 2 deletions Executable/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@

[assembly: ComVisible(false)]

[assembly: AssemblyVersion("4.0.0.0")]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyVersion("4.0.1.0")]
[assembly: AssemblyFileVersion("4.0.1.0")]
4 changes: 2 additions & 2 deletions Installer/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@

[assembly: Guid("8c6c9a0b-80c4-43d2-89f2-749e6f09fdda")]

[assembly: AssemblyVersion("4.0.0.0")]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyVersion("4.0.1.0")]
[assembly: AssemblyFileVersion("4.0.1.0")]
2 changes: 1 addition & 1 deletion Installer/QModsInstallerScript.iss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#endif

#define Name "QModManager" ; The name of the game will be added after it
#define Version "4.0.0"
#define Version "4.0.1"
#define Author "QModManager"
#define URL "https://github.com/QModManager/QModManager"
#define SupportURL "https://discord.gg/UpWuWwq"
Expand Down
4 changes: 2 additions & 2 deletions QMMHarmonyShimmer/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("4.0.0.0")]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyVersion("4.0.1.0")]
[assembly: AssemblyFileVersion("4.0.1.0")]
[assembly: NeutralResourcesLanguage("en")]
4 changes: 2 additions & 2 deletions QMMLoader/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("4.0.0.0")]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyVersion("4.0.1.0")]
[assembly: AssemblyFileVersion("4.0.1.0")]
[assembly: NeutralResourcesLanguage("en")]
23 changes: 17 additions & 6 deletions QModManager/API/RequiredQMod.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
namespace QModManager.API
{
using System;
using QModManager.Utility;

/// <summary>
/// Identifies a required mod and an optional minimum version.
/// </summary>
public class RequiredQMod
{
internal RequiredQMod(string id)
internal static IVersionParser VersionParserService { get; set; } = new VersionParser();

private RequiredQMod(string id, bool requiresMinVersion, Version version)
{
this.Id = id;
this.RequiresMinimumVersion = false;
this.MinimumVersion = new Version();
this.RequiresMinimumVersion = requiresMinVersion;
this.MinimumVersion = version;
}

internal RequiredQMod(string id)
: this(id, false, VersionParserService.NoVersionParsed)
{
}

internal RequiredQMod(string id, Version minimumVersion)
: this(id, !VersionParserService.IsAllZeroVersion(minimumVersion), minimumVersion)
{
}

internal RequiredQMod(string id, string minimumVersion)
: this(id, !string.IsNullOrEmpty(minimumVersion), VersionParserService.GetVersion(minimumVersion))
{
this.Id = id;
this.RequiresMinimumVersion = true;
this.MinimumVersion = minimumVersion;
}

/// <summary>
Expand Down
22 changes: 6 additions & 16 deletions QModManager/Patching/ManifestValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

internal class ManifestValidator : IManifestValidator
{
internal static readonly Regex VersionRegex = new Regex(@"(((\d+)\.?)+)");
internal static IVersionParser VersionParserService { get; set; } = new VersionParser();

internal static readonly Dictionary<string, ModStatus> ProhibitedModIDs = new Dictionary<string, ModStatus>()
{
Expand Down Expand Up @@ -70,8 +70,7 @@ public void ValidateManifest(QMod mod)

try
{
if (Version.TryParse(mod.Version, out Version version))
mod.ParsedVersion = version;
mod.ParsedVersion = VersionParserService.GetVersion(mod.Version);
}
catch (Exception vEx)
{
Expand Down Expand Up @@ -135,20 +134,11 @@ public void CheckRequiredMods(QMod mod)
foreach (KeyValuePair<string, string> item in mod.VersionDependencies)
{
string id = item.Key;
string cleanVersion = VersionRegex.Matches(item.Value)?[0]?.Value;
string versionString = item.Value;

if (string.IsNullOrEmpty(cleanVersion))
{
requiredMods[id] = new RequiredQMod(id);
}
else if (Version.TryParse(cleanVersion, out Version version))
{
requiredMods[id] = new RequiredQMod(id, version);
}
else if (!requiredMods.ContainsKey(id))
{
requiredMods[id] = new RequiredQMod(id);
}
Version version = VersionParserService.GetVersion(versionString);

requiredMods[id] = new RequiredQMod(id, version);

mod.RequiredDependencies.Add(id);
}
Expand Down
4 changes: 2 additions & 2 deletions QModManager/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

[assembly: ComVisible(false)]

[assembly: AssemblyVersion("4.0.0.0")]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyVersion("4.0.1.0")]
[assembly: AssemblyFileVersion("4.0.1.0")]

[assembly: InternalsVisibleTo("QMMTests")]
[assembly: InternalsVisibleTo("QModManager")]
Expand Down
1 change: 1 addition & 0 deletions QModManager/QModManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
<Compile Include="Utility\NetworkUtilities.cs" />
<Compile Include="Utility\ReflectionHelper.cs" />
<Compile Include="Checks\VersionCheck.cs" />
<Compile Include="Utility\VersionParser.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Expand Down
90 changes: 90 additions & 0 deletions QModManager/Utility/VersionParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
namespace QModManager.Utility
{
using System;
using System.Text.RegularExpressions;

/// <summary>
/// Defines a service for parsing version strings.
/// </summary>
public interface IVersionParser
{
/// <summary>
/// The default version zero used when no version could be parsed.
/// </summary>
Version NoVersionParsed { get; }

/// <summary>
/// Returns a new <see cref="Version"/> based on the provided string value, with all 4 groups populated.
/// </summary>
/// <param name="versionString">The version string to parse.</param>
/// <returns>A new <see cref="Version"/> with all empty groups populated with 0.</returns>
Version GetVersion(string versionString);

/// <summary>
/// Checks if the provided version is all zeros.
/// </summary>
/// <param name="version">The version to check.</param>
/// <returns>True if this matches version 0.0.0.0</returns>
bool IsAllZeroVersion(Version version);
}

/// <summary>
/// A service that handles parsing <see cref="string"/> values into <see cref="Version"/> objects.
/// </summary>
public class VersionParser : IVersionParser
{
private static readonly Version VersionZeroSingleton = new Version(0, 0, 0, 0);

/// <summary>
/// The regex used to sanitize incoming version strings.
/// ^(((\d+)\.?){0,3}\d+)$
/// </summary>
public static readonly Regex VersionRegex = new Regex(@"^(((\d+)\.?){0,3}\d+)$");

/// <summary>
/// The default version zero used when no version could be parsed.
/// </summary>
public Version NoVersionParsed => new Version(0, 0, 0, 0);

/// <summary>
/// Returns a new <see cref="Version"/> based on the provided string value, with all 4 groups populated.
/// </summary>
/// <param name="versionString">The version string to parse. This must match <seealso cref="VersionRegex"/>.</param>
/// <returns>A new <see cref="Version"/> with all empty groups populated with 0.</returns>
/// <example>
/// "2.8" will be parsed as "2.8.0.0"
/// </example>
public Version GetVersion(string versionString)
{
if (!VersionRegex.IsMatch(versionString))
{
return NoVersionParsed;
}

versionString = VersionRegex.Matches(versionString)?[0]?.Value;

int groups = versionString.Split('.').Length;
while (groups++ < 4)
{
versionString += ".0";
}

if (Version.TryParse(versionString, out Version parsedVersion))
{
return parsedVersion;
}

return NoVersionParsed;
}

/// <summary>
/// Checks if the provided version is all zeros.
/// </summary>
/// <param name="version">The version to check.</param>
/// <returns>True if this matches version 0.0.0.0</returns>
public bool IsAllZeroVersion(Version version)
{
return version == VersionZeroSingleton;
}
}
}
4 changes: 2 additions & 2 deletions QModPluginEmulator/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("4.0.0.0")]
[assembly: AssemblyFileVersion("4.0.0.0")]
[assembly: AssemblyVersion("4.0.1.0")]
[assembly: AssemblyFileVersion("4.0.1.0")]
[assembly: NeutralResourcesLanguage("en")]

[assembly: InternalsVisibleTo("QModManager.QMMLoader")]
24 changes: 7 additions & 17 deletions QModPluginEmulator/QModPluginGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Mono.Cecil;
using QModManager.API;
using QModManager.Patching;
using QModManager.Utility;
using System;
using System.Collections.Generic;
using System.IO;
Expand All @@ -25,6 +26,8 @@ public static class QModPluginGenerator
internal static Dictionary<string, PluginInfo> QModPluginInfos;
internal static List<PluginInfo> InitialisedQModPlugins;

internal static IVersionParser VersionParserService { get; set; } = new VersionParser();

[Obsolete("Should not be used!", true)]
public static void Finish()
{
Expand Down Expand Up @@ -100,22 +103,9 @@ public static void TypeLoaderFindPluginTypesPostfix(ref Dictionary<string, List<

foreach (var versionDependency in mod.VersionDependencies)
{
var cleanVersion = ManifestValidator.VersionRegex.Matches(versionDependency.Value)?[0]?.Value;
if (string.IsNullOrEmpty(cleanVersion))
{
traverseablePluginInfo.Property<IEnumerable<BepInDependency>>(nameof(PluginInfo.Dependencies)).Value
= pluginInfo.Dependencies.AddItem(new BepInDependency(versionDependency.Key, new Version().ToString()));
}
else if (Version.TryParse(cleanVersion, out Version version))
{
traverseablePluginInfo.Property<IEnumerable<BepInDependency>>(nameof(PluginInfo.Dependencies)).Value
= pluginInfo.Dependencies.AddItem(new BepInDependency(versionDependency.Key, version.ToString()));
}
else
{
traverseablePluginInfo.Property<IEnumerable<BepInDependency>>(nameof(PluginInfo.Dependencies)).Value
= pluginInfo.Dependencies.AddItem(new BepInDependency(versionDependency.Key, new Version().ToString()));
}
var version = VersionParserService.GetVersion(versionDependency.Value);
traverseablePluginInfo.Property<IEnumerable<BepInDependency>>(nameof(PluginInfo.Dependencies)).Value
= pluginInfo.Dependencies.AddItem(new BepInDependency(versionDependency.Key, version.ToString()));
}
foreach (var id in mod.LoadAfter)
{
Expand All @@ -125,7 +115,7 @@ public static void TypeLoaderFindPluginTypesPostfix(ref Dictionary<string, List<

traverseablePluginInfo.Property<IEnumerable<BepInProcess>>(nameof(PluginInfo.Processes)).Value = new BepInProcess[0];
traverseablePluginInfo.Property<IEnumerable<BepInIncompatibility>>(nameof(PluginInfo.Incompatibilities)).Value = new BepInIncompatibility[0];
traverseablePluginInfo.Property<BepInPlugin>(nameof(PluginInfo.Metadata)).Value = new BepInPlugin(mod.Id, mod.DisplayName, mod.Version);
traverseablePluginInfo.Property<BepInPlugin>(nameof(PluginInfo.Metadata)).Value = new BepInPlugin(mod.Id, mod.DisplayName, mod.ParsedVersion.ToString());
traverseablePluginInfo.Property<string>("TypeName").Value = typeof(QModPlugin).FullName;
traverseablePluginInfo.Property<Version>("TargettedBepInExVersion").Value
= Assembly.GetExecutingAssembly().GetReferencedAssemblies().FirstOrDefault(x => x.Name == "BepInEx").Version;
Expand Down
6 changes: 3 additions & 3 deletions Unit Tests/ManifestValidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void CheckRequiredMods_WhenRequiresVersion_GetExpectedRequiredMod()

Assert.AreEqual(1, versionDependentMod.RequiredMods.Count());

RequiredQMod expected = new RequiredQMod(requiredMod, new Version(requiredVersionString));
RequiredQMod expected = new RequiredQMod(requiredMod, requiredVersionString);
RequiredQMod actual = versionDependentMod.RequiredMods.First();

Assert.AreEqual(requiredMod, actual.Id);
Expand Down Expand Up @@ -96,7 +96,7 @@ public void CheckRequiredMods_WhenRequirementsRedundant_GetExpectedRequiredMod()
// Only a single entry is added to RequiredMods.
Assert.AreEqual(1, versionDependentMod.RequiredMods.Count());

RequiredQMod expected = new RequiredQMod(requiredMod, new Version(requiredVersionString));
RequiredQMod expected = new RequiredQMod(requiredMod, requiredVersionString);
RequiredQMod actual = versionDependentMod.RequiredMods.First();

Assert.AreEqual(requiredMod, actual.Id);
Expand Down Expand Up @@ -133,7 +133,7 @@ public void CheckRequiredMods_WhenRequirementsMixed_GetExpectedRequiredMods()
Assert.AreEqual(expectedA.RequiresMinimumVersion, actualA.RequiresMinimumVersion);
Assert.AreEqual(expectedA.MinimumVersion, actualA.MinimumVersion);

RequiredQMod expectedB = new RequiredQMod(requiredModB, new Version(requiredVersionBString));
RequiredQMod expectedB = new RequiredQMod(requiredModB, requiredVersionBString);
RequiredQMod actualB = versionDependentMod.RequiredMods.ElementAt(1);

Assert.AreEqual(requiredModB, actualB.Id);
Expand Down
Loading

0 comments on commit 7ef0a21

Please sign in to comment.