summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SMAPI.Toolkit/SemanticVersionComparer.cs32
-rw-r--r--src/SMAPI.Web/Framework/ModSiteManager.cs73
2 files changed, 83 insertions, 22 deletions
diff --git a/src/SMAPI.Toolkit/SemanticVersionComparer.cs b/src/SMAPI.Toolkit/SemanticVersionComparer.cs
new file mode 100644
index 00000000..9f6b57a2
--- /dev/null
+++ b/src/SMAPI.Toolkit/SemanticVersionComparer.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+
+namespace StardewModdingAPI.Toolkit
+{
+ /// <summary>A comparer for semantic versions based on the <see cref="SemanticVersion.CompareTo(ISemanticVersion)"/> field.</summary>
+ public class SemanticVersionComparer : IComparer<ISemanticVersion>
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>A singleton instance of the comparer.</summary>
+ public static SemanticVersionComparer Instance { get; } = new SemanticVersionComparer();
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <inheritdoc />
+ public int Compare(ISemanticVersion x, ISemanticVersion y)
+ {
+ if (object.ReferenceEquals(x, y))
+ return 0;
+
+ if (x is null)
+ return -1;
+ if (y is null)
+ return 1;
+
+ return x.CompareTo(y);
+ }
+ }
+}
diff --git a/src/SMAPI.Web/Framework/ModSiteManager.cs b/src/SMAPI.Web/Framework/ModSiteManager.cs
index 68b4c6ac..8f21d2f5 100644
--- a/src/SMAPI.Web/Framework/ModSiteManager.cs
+++ b/src/SMAPI.Web/Framework/ModSiteManager.cs
@@ -110,41 +110,70 @@ namespace StardewModdingAPI.Web.Framework
main = null;
preview = null;
- ISemanticVersion ParseVersion(string raw)
+ // parse all versions from the mod page
+ IEnumerable<(string name, string description, ISemanticVersion version)> GetAllVersions()
{
- raw = this.NormalizeVersion(raw);
- return this.GetMappedVersion(raw, mapRemoteVersions, allowNonStandardVersions);
+ if (mod != null)
+ {
+ ISemanticVersion ParseAndMapVersion(string raw)
+ {
+ raw = this.NormalizeVersion(raw);
+ return this.GetMappedVersion(raw, mapRemoteVersions, allowNonStandardVersions);
+ }
+
+ // get mod version
+ ISemanticVersion modVersion = ParseAndMapVersion(mod.Version);
+ if (modVersion != null)
+ yield return (name: null, description: null, version: ParseAndMapVersion(mod.Version));
+
+ // get file versions
+ foreach (IModDownload download in mod.Downloads)
+ {
+ ISemanticVersion cur = ParseAndMapVersion(download.Version);
+ if (cur != null)
+ yield return (download.Name, download.Description, cur);
+ }
+ }
}
+ var versions = GetAllVersions()
+ .OrderByDescending(p => p.version, SemanticVersionComparer.Instance)
+ .ToArray();
- if (mod != null)
+ // get main + preview versions
+ void TryGetVersions(out ISemanticVersion mainVersion, out ISemanticVersion previewVersion, Func<(string name, string description, ISemanticVersion version), bool> filter = null)
{
- // get mod version
- if (subkey == null)
- main = ParseVersion(mod.Version);
+ mainVersion = null;
+ previewVersion = null;
- // get file versions
- foreach (IModDownload download in mod.Downloads)
+ // get latest main + preview version
+ foreach (var entry in versions)
{
- // check for subkey if specified
- if (subkey != null && download.Name?.Contains(subkey, StringComparison.OrdinalIgnoreCase) != true && download.Description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) != true)
+ if (filter?.Invoke(entry) == false)
continue;
- // parse version
- ISemanticVersion cur = ParseVersion(download.Version);
- if (cur == null)
- continue;
+ if (entry.version.IsPrerelease())
+ previewVersion ??= entry.version;
+ else
+ mainVersion ??= entry.version;
- // track highest versions
- if (main == null || cur.IsNewerThan(main))
- main = cur;
- if (cur.IsPrerelease() && (preview == null || cur.IsNewerThan(preview)))
- preview = cur;
+ if (mainVersion != null)
+ break; // any other values will be older
}
- if (preview != null && !preview.IsNewerThan(main))
- preview = null;
+ // normalize values
+ if (previewVersion is not null)
+ {
+ mainVersion ??= previewVersion; // if every version is prerelease, latest one is the main version
+ if (!previewVersion.IsNewerThan(mainVersion))
+ previewVersion = null;
+ }
}
+ if (subkey is not null)
+ TryGetVersions(out main, out preview, entry => entry.name?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true || entry.description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true);
+ if (main is null)
+ TryGetVersions(out main, out preview);
+
return main != null;
}