Skip to content

Commit

Permalink
LimSemVer: Implement release_type and bump methods
Browse files Browse the repository at this point in the history
  • Loading branch information
tbhaxor committed Aug 28, 2023
1 parent 1d19c1e commit b64143c
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 5 deletions.
1 change: 1 addition & 0 deletions Tests/LibSemVer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set(TEST_SOURCES
TestFromStringView.cpp
TestSemVer.cpp
)

foreach(source IN LISTS TEST_SOURCES)
Expand Down
8 changes: 4 additions & 4 deletions Tests/LibSemVer/TestFromStringView.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/*
* Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
* Copyright (c) 2021, Gurkirat Singh <tbhaxor@proton.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include "AK/StringView.h"
#include "LibSemVer/Semver.h"
#include "LibTest/TestCase.h"
#include <AK/StringView.h>
#include <AK/Tuple.h>
#include <AK/Vector.h>
#include <LibSemVer/Semver.h>
#include <LibTest/TestCase.h>

TEST_CASE(parsing)
{
Expand Down
113 changes: 113 additions & 0 deletions Tests/LibSemVer/TestSemVer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2021, Gurkirat Singh <tbhaxor@proton.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <AK/StringView.h>
#include <AK/Tuple.h>
#include <AK/Vector.h>
#include <LibSemVer/Semver.h>
#include <LibTest/TestCase.h>

TEST_CASE(to_string)
{
Vector<StringView> versions {
"1.0.4"sv,
"1.2.3"sv,
"10.20.30"sv,
"1.1.2-prerelease+meta"sv,
"1.1.2+meta"sv,
"1.1.2+meta-valid"sv,
"1.0.0-alpha"sv,
"1.0.0-beta"sv,
"1.0.0-alpha.beta"sv,
"1.0.0-alpha.beta.1"sv,
"1.0.0-alpha.1"sv,
"1.0.0-alpha0.valid"sv,
"1.0.0-alpha.0valid"sv,
"1.0.0-rc.1+build.1"sv,
"2.0.0-rc.1+build.123"sv,
"1.2.3-beta"sv,
"10.2.3-DEV-SNAPSHOT"sv,
"1.2.3-SNAPSHOT-123"sv,
"1.0.0"sv,
"2.0.0"sv,
"1.1.7"sv,
"2.0.0+build.1848"sv,
"2.0.1-alpha.1227"sv,
"1.0.0-alpha+beta"sv,
"1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay"sv,
"1.2.3----RC-SNAPSHOT.12.9.1--.12+788"sv,
"1.2.3----R-S.12.9.1--.12+meta"sv,
"1.2.3----RC-SNAPSHOT.12.9.1--.12"sv,
"1.0.0+0.build.1-rc.10000aaa-kk-0.1"sv,
"1.0.0-0A.is.legal"sv,
};

for (auto const& version : versions) {
EXPECT_EQ(version, MUST(SemVer::from_string_view(version)).to_string());
}
}

TEST_CASE(bump)
{
auto version = MUST(SemVer::from_string_view("1.1.2-prerelease+meta"sv));

auto major_bump = version.bump(SemVer::BumpType::Major);
auto minor_bump = version.bump(SemVer::BumpType::Minor);
auto patch_bump = version.bump(SemVer::BumpType::Patch);

EXPECT_EQ(major_bump.m_major, version.m_major + 1);
EXPECT_EQ(minor_bump.m_minor, version.m_minor + 1);
EXPECT_EQ(patch_bump.m_patch, version.m_patch + 1);

EXPECT_EQ(major_bump.suffix(), version.suffix());

auto bump_clear_prerelease = version.bump(SemVer::BumpType::Major, SemVer::BumpOpts::ClearPreRelease);
auto bump_clear_buildmetadata = version.bump(SemVer::BumpType::Major, SemVer::BumpOpts::ClearBuildMeta);

EXPECT_EQ(bump_clear_prerelease.suffix(), "+meta"sv);
EXPECT_EQ(bump_clear_buildmetadata.suffix(), "-prerelease"sv);
}

TEST_CASE(release_type)
{
Vector<Tuple<StringView, SemVer::ReleaseType>> test_cases {
// no suffix
Tuple { "1.2.3"sv, SemVer::ReleaseType::Stable },
// alpha or beta
Tuple { "1.2.3-alpha"sv, SemVer::ReleaseType::Alpha },
Tuple { "1.2.3-beta"sv, SemVer::ReleaseType::Beta },
// alpha and beta order doesn't matter
Tuple { "1.2.3-alpha.beta"sv, SemVer::ReleaseType::AlphaBeta },
Tuple { "1.2.3-beta.alpha"sv, SemVer::ReleaseType::AlphaBeta },
// prerelease
Tuple { "1.2.3-prerelease"sv, SemVer::ReleaseType::PreRelease },
// release candidate
Tuple { "1.2.3-rc"sv, SemVer::ReleaseType::ReleaseCandidate },
// alpha/beta has high priority
Tuple { "1.2.3-prerelease.alpha"sv, SemVer::ReleaseType::Alpha },
Tuple { "1.2.3-alpha.prerelease"sv, SemVer::ReleaseType::Alpha },
Tuple { "1.2.3-prerelease.beta"sv, SemVer::ReleaseType::Beta },
Tuple { "1.2.3-beta.prerelease"sv, SemVer::ReleaseType::Beta },
Tuple { "1.2.3-beta.prerelease.alpha"sv, SemVer::ReleaseType::AlphaBeta },
Tuple { "1.2.3-alpha.prerelease.beta"sv, SemVer::ReleaseType::AlphaBeta },
Tuple { "1.2.3-rc.alpha"sv, SemVer::ReleaseType::Alpha },
Tuple { "1.2.3-alpha.rc"sv, SemVer::ReleaseType::Alpha },
Tuple { "1.2.3-rc.beta"sv, SemVer::ReleaseType::Beta },
Tuple { "1.2.3-beta.rc"sv, SemVer::ReleaseType::Beta },
Tuple { "1.2.3-beta.rc.alpha"sv, SemVer::ReleaseType::AlphaBeta },
Tuple { "1.2.3-alpha.rc.beta"sv, SemVer::ReleaseType::AlphaBeta },
// prerelease has high priority than release candidate
Tuple { "1.2.3-prerelease.rc"sv, SemVer::ReleaseType::PreRelease },
Tuple { "1.2.3-rc.prerelease"sv, SemVer::ReleaseType::PreRelease },
// fallback to stable version
Tuple { "1.2.3-is.also.legal"sv, SemVer::ReleaseType::Stable },
};

for (auto const& test_case : test_cases.span()) {
auto version = MUST(SemVer::from_string_view(test_case.get<StringView>()));
EXPECT_EQ(version.release_type(), test_case.get<SemVer::ReleaseType>());
}
}
60 changes: 59 additions & 1 deletion Userland/Libraries/LibSemVer/SemVer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,64 @@ String SemVer::to_string() const
return MUST(String::formatted("{}.{}.{}{}", m_major, m_minor, m_patch, suffix()));
}

ReleaseType SemVer::release_type() const
{
auto prerel_identifiers = MUST(MUST(m_prerelease.to_lowercase()).split('.'));
auto is_alpha = prerel_identifiers.contains_slow("alpha"_string);
auto is_beta = prerel_identifiers.contains_slow("beta"_string);

if (is_alpha && is_beta) {
return ReleaseType::AlphaBeta;
}

if (is_alpha) {
return ReleaseType::Alpha;
}

if (is_beta) {
return ReleaseType::Beta;
}

if (prerel_identifiers.contains_slow("prerelease"_string)) {
return ReleaseType::PreRelease;
}

// strict release candidate check
if (prerel_identifiers.contains_slow("rc"_string)) {
return ReleaseType::ReleaseCandidate;
}

return ReleaseType::Stable;
}

SemVer SemVer::bump(BumpType type, BumpOpts opt) const
{
String prerelease;
String buildmetadata;

switch (opt) {
case BumpOpts::KeepSuffix:
prerelease = m_prerelease;
buildmetadata = m_buildmetadata;
break;
case BumpOpts::ClearBuildMeta:
prerelease = m_prerelease;
break;
case BumpOpts::ClearPreRelease:
buildmetadata = m_buildmetadata;
break;
}

switch (type) {
case BumpType::Major:
return SemVer(m_major + 1, m_minor, m_patch, prerelease, buildmetadata);
case BumpType::Minor:
return SemVer(m_major, m_minor + 1, m_patch, prerelease, buildmetadata);
case BumpType::Patch:
return SemVer(m_major, m_minor, m_patch + 1, prerelease, buildmetadata);
}
}

ErrorOr<SemVer> from_string_view(StringView const& version)
{
using namespace regex;
Expand Down Expand Up @@ -57,7 +115,7 @@ ErrorOr<SemVer> from_string_view(StringView const& version)

lexer.consume();

version_part = lexer.consume_while<ConsumePredicate<char>>([](auto const& ch) {
version_part = lexer.consume_while<Function<bool(char)>>([](char ch) {
return ch >= '0' && ch <= '9';
})
.to_uint<u64>();
Expand Down

0 comments on commit b64143c

Please sign in to comment.