Skip to content

Commit 5f7658e

Browse files
committed
Move to custom semver versioning for MO2. (#154)
1 parent 6465d3e commit 5f7658e

11 files changed

Lines changed: 562 additions & 45 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
edit
2+
.vscode
23
CMakeLists.txt.user
34
/msbuild.log
45
/*std*.log

include/uibase/exceptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <stdexcept>
55

6+
#include <QObject>
67
#include <QString>
78

89
#include "dllimport.h"

include/uibase/imoinfo.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3535
#include "imodlist.h"
3636
#include "iprofile.h"
3737
#include "versioninfo.h"
38+
#include "versioning.h"
3839

3940
namespace MOBase
4041
{
@@ -121,7 +122,12 @@ class QDLLEXPORT IOrganizer : public QObject
121122
/**
122123
* @return the running version of Mod Organizer
123124
*/
124-
virtual VersionInfo appVersion() const = 0;
125+
[[deprecated]] virtual VersionInfo appVersion() const = 0;
126+
127+
/**
128+
* @return the running version of Mod Organizer
129+
*/
130+
virtual Version version() const = 0;
125131

126132
/**
127133
* @brief create a new mod with the specified name

include/uibase/versioning.h

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#pragma once
2+
3+
#include <compare>
4+
#include <string>
5+
#include <variant>
6+
#include <vector>
7+
8+
#include <QFlags>
9+
#include <QString>
10+
11+
#include "dllimport.h"
12+
#include "exceptions.h"
13+
14+
namespace MOBase
15+
{
16+
17+
class InvalidVersionException : public Exception
18+
{
19+
public:
20+
using Exception::Exception;
21+
};
22+
23+
// class representing a Version object
24+
//
25+
// valid versions are an "extension" of SemVer (see https://semver.org/) with the
26+
// following tweaks:
27+
// - version can have a sub-patch, i.e., x.y.z.p, which are normally not allowed by
28+
// SemVer
29+
// - non-integer pre-release identifiers are limited to dev, alpha (a), beta (b) and rc,
30+
// and dev is lower than alpha (according to SemVer, the pre-release should be
31+
// ordered alphabetically)
32+
// - the '-' between version and pre-release can be made optional, and also the '.'
33+
// between pre-releases segment
34+
//
35+
// the extension from SemVer are only meant to be used by MO2 and USVFS versioning,
36+
// plugins and extensions should follow SemVer standard (and not use dev), this is
37+
// mainly
38+
// - for back-compatibility purposes, because USVFS versioning contains sub-patches and
39+
// there are old MO2 releases with sub-patch
40+
// - because MO2 is not going to become MO3, so having an extra level make sense
41+
//
42+
// unlike VersionInfo, this class is immutable and only hold valid versions
43+
//
44+
class QDLLEXPORT Version
45+
{
46+
public:
47+
enum class ParseMode
48+
{
49+
// official semver parsing with pre-release limited to dev, alpha/a, beta/b and rc
50+
//
51+
SemVer,
52+
53+
// MO2 parsing, e.g., 2.5.1rc1 - this either parse a string with no pre-release
54+
// information (e.g. 2.5.1) or with a single pre-release + a version (e.g., 2.5.1a1
55+
// or 2.5.2rc1)
56+
//
57+
// this mode can parse sub-patch (SemVer mode cannot)
58+
//
59+
MO2
60+
};
61+
62+
enum class FormatMode
63+
{
64+
// show subpatch even if subpatch is 0
65+
//
66+
ForceSubPatch = 0b0001,
67+
68+
// do not add separators between version and pre-release (-) or between pre-release
69+
// segments (.)
70+
//
71+
NoSeparator = 0b0010,
72+
73+
// uses short form for alpha and beta (a/b instead of alpha/beta)
74+
//
75+
ShortAlphaBeta = 0b0100,
76+
77+
// do not add metadata even if present
78+
//
79+
NoMetadata = 0b1000
80+
};
81+
Q_DECLARE_FLAGS(FormatModes, FormatMode);
82+
83+
// condensed format, no separator, short alpha/beta and no metadata
84+
//
85+
static constexpr auto FormatCondensed = FormatModes{
86+
FormatMode::NoSeparator, FormatMode::ShortAlphaBeta, FormatMode::NoMetadata};
87+
88+
enum class ReleaseType
89+
{
90+
Development, // -dev
91+
Alpha, // -alpha, -a
92+
Beta, // -beta, -b
93+
ReleaseCandidate, // -rc
94+
};
95+
using enum ReleaseType;
96+
97+
public: // parsing
98+
// parse version from the given string, throw InvalidVersionException if the string
99+
// cannot be parsed
100+
//
101+
static Version parse(QString const& value, ParseMode mode = ParseMode::SemVer);
102+
103+
public: // constructors
104+
Version(int major, int minor, int patch, QString metadata = {});
105+
Version(int major, int minor, int patch, int subpatch, QString metadata = {});
106+
107+
Version(int major, int minor, int patch, ReleaseType type, QString metadata = {});
108+
Version(int major, int minor, int patch, int subpatch, ReleaseType type,
109+
QString metadata = {});
110+
111+
Version(int major, int minor, int patch, ReleaseType type, int prerelease,
112+
QString metadata = {});
113+
Version(int major, int minor, int patch, int subpatch, ReleaseType type,
114+
int prerelease, QString metadata = {});
115+
116+
Version(int major, int minor, int patch, int subpatch,
117+
std::vector<std::variant<int, ReleaseType>> prereleases,
118+
QString metadata = {});
119+
120+
public: // special member functions
121+
Version(const Version&) = default;
122+
Version(Version&&) = default;
123+
124+
Version& operator=(const Version&) = default;
125+
Version& operator=(Version&&) = default;
126+
127+
public:
128+
// check if this version corresponds to a pre-release version (dev, alpha, beta, etc.)
129+
//
130+
bool isPreRelease() const { return !m_PreReleases.empty(); }
131+
132+
// retrieve major, minor, patch and sub-patch of this version
133+
//
134+
int major() const { return m_Major; }
135+
int minor() const { return m_Minor; }
136+
int patch() const { return m_Patch; }
137+
int subpatch() const { return m_SubPatch; }
138+
139+
// retrieve pre-releases information for this version
140+
//
141+
const auto& preReleases() const { return m_PreReleases; }
142+
143+
// retrieve build metadata, if any, otherwise return an empty string
144+
//
145+
const auto& buildMetadata() const { return m_BuildMetadata; }
146+
147+
// convert this version to a string
148+
//
149+
QString string(const FormatModes& modes = {}) const;
150+
151+
private:
152+
// major.minor.patch
153+
int m_Major, m_Minor, m_Patch, m_SubPatch;
154+
155+
// pre-release information
156+
std::vector<std::variant<int, ReleaseType>> m_PreReleases;
157+
158+
// metadata
159+
QString m_BuildMetadata;
160+
};
161+
162+
QDLLEXPORT std::strong_ordering operator<=>(const Version& lhs, const Version& rhs);
163+
164+
inline bool operator==(const Version& lhs, const Version& rhs)
165+
{
166+
return (lhs <=> rhs) == 0;
167+
}
168+
169+
Q_DECLARE_OPERATORS_FOR_FLAGS(Version::FormatModes);
170+
171+
} // namespace MOBase
172+
173+
template <class CharT>
174+
struct std::formatter<MOBase::Version, CharT> : std::formatter<QString, CharT>
175+
{
176+
template <class FmtContext>
177+
FmtContext::iterator format(const MOBase::Version& v, FmtContext& ctx) const
178+
{
179+
return std::formatter<QString, CharT>::format(v.string(), ctx);
180+
}
181+
};

src/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ set(root_headers
3030
../include/uibase/steamutility.h
3131
../include/uibase/strings.h
3232
../include/uibase/utility.h
33+
../include/uibase/versioning.h
3334
../include/uibase/versioninfo.h
3435
)
3536
set(interface_headers
@@ -115,14 +116,14 @@ mo2_target_sources(uibase
115116
nxmurl.cpp
116117
pch.cpp
117118
pluginrequirements.cpp
118-
pluginsetting.cpp
119119
registry.cpp
120120
report.cpp
121121
safewritefile.cpp
122122
scopeguard.cpp
123123
steamutility.cpp
124124
strings.cpp
125125
utility.cpp
126+
versioning.cpp
126127
versioninfo.cpp
127128
)
128129

@@ -133,7 +134,6 @@ mo2_target_sources(uibase
133134
ifiletree.cpp
134135
imodrepositorybridge.cpp
135136
imoinfo.cpp
136-
iplugininstaller.cpp
137137
)
138138

139139
mo2_target_sources(uibase

src/iplugininstaller.cpp

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/pluginsetting.cpp

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)