From 0b9d3e1726eae1a0fb6fb0d17f8179281b1e045e Mon Sep 17 00:00:00 2001 From: Ken Matsui <26405363+ken-matsui@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:15:31 -0500 Subject: [PATCH] chore: use namespace rs --- include/Algos.hpp | 6 +- include/Builder/BuildGraph.hpp | 40 +- include/Builder/Compiler.hpp | 13 +- include/Builder/DepGraph.hpp | 5 +- include/Command.hpp | 8 +- include/Dependency.hpp | 6 +- include/Manifest.hpp | 24 +- include/Semver.hpp | 28 +- include/VersionReq.hpp | 6 +- lib/Algos.cc | 44 +- lib/Builder/BuildGraph.cc | 142 +++--- lib/Builder/Compiler.cc | 47 +- lib/Builder/DepGraph.cc | 11 +- lib/Command.cc | 39 +- lib/Dependency.cc | 20 +- lib/Manifest.cc | 764 +++++++++++++++++---------------- lib/Semver.cc | 472 ++++++++++---------- lib/VersionReq.cc | 610 +++++++++++++------------- rs-cpp/include/rs/result.hpp | 25 +- rs-cpp/include/rs/tests.hpp | 8 +- src/Builder/Builder.cc | 68 +-- src/Builder/Builder.hpp | 10 +- src/Builder/Project.cc | 62 ++- src/Builder/Project.hpp | 8 +- src/Cli.cc | 144 +++---- src/Cli.hpp | 22 +- src/Cmd/Add.cc | 38 +- src/Cmd/Build.cc | 17 +- src/Cmd/Clean.cc | 15 +- src/Cmd/Fmt.cc | 24 +- src/Cmd/Help.cc | 4 +- src/Cmd/Init.cc | 18 +- src/Cmd/Lint.cc | 26 +- src/Cmd/New.cc | 43 +- src/Cmd/New.hpp | 7 +- src/Cmd/Remove.cc | 12 +- src/Cmd/Run.cc | 22 +- src/Cmd/Search.cc | 19 +- src/Cmd/Test.cc | 16 +- src/Cmd/Tidy.cc | 24 +- src/Cmd/Version.cc | 11 +- src/Driver.cc | 4 +- src/Driver.hpp | 2 +- tests/helpers.hpp | 12 +- 44 files changed, 1488 insertions(+), 1458 deletions(-) diff --git a/include/Algos.hpp b/include/Algos.hpp index 955036551..85303ff70 100644 --- a/include/Algos.hpp +++ b/include/Algos.hpp @@ -17,9 +17,9 @@ std::string toMacroName(std::string_view name) noexcept; std::string replaceAll(std::string str, std::string_view from, std::string_view to) noexcept; -Result execCmd(const Command& cmd) noexcept; -Result getCmdOutput(const Command& cmd, - std::size_t retry = 3) noexcept; +rs::Result execCmd(const Command& cmd) noexcept; +rs::Result getCmdOutput(const Command& cmd, + std::size_t retry = 3) noexcept; bool commandExists(std::string_view cmd) noexcept; constexpr char toLower(char c) noexcept { diff --git a/include/Builder/BuildGraph.hpp b/include/Builder/BuildGraph.hpp index 1a4957f26..35079384f 100644 --- a/include/Builder/BuildGraph.hpp +++ b/include/Builder/BuildGraph.hpp @@ -34,8 +34,8 @@ class BuildGraph { TestKind kind = TestKind::Unit; }; - static Result create(const Manifest& manifest, - const BuildProfile& buildProfile); + static rs::Result create(const Manifest& manifest, + const BuildProfile& buildProfile); const fs::path& outBasePath() const { return outBasePath_; } const Manifest& manifest() const { return project.manifest; } @@ -46,16 +46,16 @@ class BuildGraph { const std::string& libraryName() const { return libName; } const std::vector& testTargets() const { return testTargets_; } - Result installDeps(bool includeDevDeps); + rs::Result installDeps(bool includeDevDeps); void enableCoverage(); - Result plan(bool logAnalysis = true); - Result writeBuildFilesIfNeeded() const; - Result generateCompdb() const; + rs::Result plan(bool logAnalysis = true); + rs::Result writeBuildFilesIfNeeded() const; + rs::Result generateCompdb() const; - Result needsBuild(const std::vector& targets) const; + rs::Result needsBuild(const std::vector& targets) const; Command ninjaCommand(bool dryRun = false) const; - Result buildTargets(const std::vector& targets, - std::string_view displayName) const; + rs::Result buildTargets(const std::vector& targets, + std::string_view displayName) const; private: struct CompileUnit { @@ -84,22 +84,22 @@ class BuildGraph { const std::unordered_set& dependencies, bool isTest); - Result runMM(const std::string& sourceFile, - bool isTest = false) const; - Result containsTestCode(const std::string& sourceFile) const; + rs::Result runMM(const std::string& sourceFile, + bool isTest = false) const; + rs::Result containsTestCode(const std::string& sourceFile) const; - Result processSrc(const fs::path& sourceFilePath, - const SourceRoot& root, - std::unordered_set& buildObjTargets, - tbb::spin_mutex* mtx = nullptr); - Result> + rs::Result processSrc(const fs::path& sourceFilePath, + const SourceRoot& root, + std::unordered_set& buildObjTargets, + tbb::spin_mutex* mtx = nullptr); + rs::Result> processSources(const std::vector& sourceFilePaths, const SourceRoot& root); - Result> + rs::Result> processUnittestSrc(const fs::path& sourceFilePath, tbb::spin_mutex* mtx = nullptr); - Result> + rs::Result> processIntegrationTestSrc(const fs::path& sourceFilePath, tbb::spin_mutex* mtx = nullptr); @@ -108,7 +108,7 @@ class BuildGraph { const std::unordered_set& objTargetDeps, const std::unordered_set& buildObjTargets) const; - Result configure(); + rs::Result configure(); void writeBuildFiles() const; fs::path outBasePath_; diff --git a/include/Builder/Compiler.hpp b/include/Builder/Compiler.hpp index 48d846fc6..9c8cb735f 100644 --- a/include/Builder/Compiler.hpp +++ b/include/Builder/Compiler.hpp @@ -44,7 +44,8 @@ struct CFlags { : macros(std::move(macros)), includeDirs(std::move(includeDirs)), others(std::move(others)) {} - static Result parsePkgConfig(std::string_view pkgConfigVer) noexcept; + static rs::Result + parsePkgConfig(std::string_view pkgConfigVer) noexcept; void merge(const CFlags& other) noexcept; }; @@ -71,7 +72,8 @@ struct LdFlags { LdFlags(std::vector libDirs, std::vector libs, std::vector others) noexcept; - static Result parsePkgConfig(std::string_view pkgConfigVer) noexcept; + static rs::Result + parsePkgConfig(std::string_view pkgConfigVer) noexcept; void merge(const LdFlags& other) noexcept; }; @@ -84,8 +86,9 @@ struct CompilerOpts { CompilerOpts(CFlags cFlags, LdFlags ldFlags) noexcept : cFlags(std::move(cFlags)), ldFlags(std::move(ldFlags)) {} - static Result parsePkgConfig(const VersionReq& pkgVerReq, - std::string_view pkgName) noexcept; + static rs::Result + parsePkgConfig(const VersionReq& pkgVerReq, + std::string_view pkgName) noexcept; void merge(const CompilerOpts& other) noexcept; }; @@ -95,7 +98,7 @@ class Compiler { const std::string cxx; static Compiler init(std::string cxx) noexcept; - static Result init() noexcept; + static rs::Result init() noexcept; Command makeCompileCmd(const CompilerOpts& opts, const std::string& sourceFile, diff --git a/include/Builder/DepGraph.hpp b/include/Builder/DepGraph.hpp index a2588bbaf..a6526c7ec 100644 --- a/include/Builder/DepGraph.hpp +++ b/include/Builder/DepGraph.hpp @@ -17,8 +17,9 @@ class DepGraph { public: explicit DepGraph(fs::path rootPath) : rootPath(std::move(rootPath)) {} - Result resolve(); - Result computeBuildGraph(const BuildProfile& buildProfile) const; + rs::Result resolve(); + rs::Result + computeBuildGraph(const BuildProfile& buildProfile) const; private: fs::path rootPath; diff --git a/include/Command.hpp b/include/Command.hpp index e7792f4af..b16371b5a 100644 --- a/include/Command.hpp +++ b/include/Command.hpp @@ -52,8 +52,8 @@ class Child { friend struct Command; public: - Result wait() const noexcept; - Result waitWithOutput() const noexcept; + rs::Result wait() const noexcept; + rs::Result waitWithOutput() const noexcept; }; struct Command { @@ -110,8 +110,8 @@ struct Command { std::string toString() const; - Result spawn() const noexcept; - Result output() const noexcept; + rs::Result spawn() const noexcept; + rs::Result output() const noexcept; }; } // namespace cabin diff --git a/include/Dependency.hpp b/include/Dependency.hpp index ddddbc174..10afe3175 100644 --- a/include/Dependency.hpp +++ b/include/Dependency.hpp @@ -16,7 +16,7 @@ struct GitDependency { const std::string url; const std::optional target; - Result install() const; + rs::Result install() const; GitDependency(std::string name, std::string url, std::optional target) @@ -27,7 +27,7 @@ struct PathDependency { const std::string name; const std::string path; - Result install() const; + rs::Result install() const; PathDependency(std::string name, std::string path) : name(std::move(name)), path(std::move(path)) {} @@ -37,7 +37,7 @@ struct SystemDependency { const std::string name; const VersionReq versionReq; - Result install() const; + rs::Result install() const; SystemDependency(std::string name, VersionReq versionReq) : name(std::move(name)), versionReq(std::move(versionReq)) {} diff --git a/include/Manifest.hpp b/include/Manifest.hpp index f5f6a52f7..1d2f2424b 100644 --- a/include/Manifest.hpp +++ b/include/Manifest.hpp @@ -38,7 +38,7 @@ struct Edition { const Year edition; const std::string str; - static Result tryFromString(std::string str) noexcept; + static rs::Result tryFromString(std::string str) noexcept; bool operator==(const Edition& otherEdition) const { return edition == otherEdition.edition; @@ -62,7 +62,7 @@ struct Package { const Edition edition; const Version version; - static Result tryFromToml(const toml::value& val) noexcept; + static rs::Result tryFromToml(const toml::value& val) noexcept; private: Package(std::string name, Edition edition, Version version) noexcept @@ -93,7 +93,7 @@ struct Profile { struct Cpplint { const std::vector filters; - static Result tryFromToml(const toml::value& val) noexcept; + static rs::Result tryFromToml(const toml::value& val) noexcept; private: explicit Cpplint(std::vector filters) noexcept @@ -103,7 +103,7 @@ struct Cpplint { struct Lint { const Cpplint cpplint; - static Result tryFromToml(const toml::value& val) noexcept; + static rs::Result tryFromToml(const toml::value& val) noexcept; private: explicit Lint(Cpplint cpplint) noexcept : cpplint(std::move(cpplint)) {} @@ -120,16 +120,16 @@ class Manifest { const std::unordered_map profiles; const Lint lint; - static Result tryParse(fs::path path = fs::current_path() - / FILE_NAME, - bool findParents = true) noexcept; - static Result tryFromToml(const toml::value& data, - fs::path path = "unknown") noexcept; + static rs::Result tryParse(fs::path path = fs::current_path() + / FILE_NAME, + bool findParents = true) noexcept; + static rs::Result tryFromToml(const toml::value& data, + fs::path path = "unknown") noexcept; - static Result + static rs::Result findPath(fs::path candidateDir = fs::current_path()) noexcept; - Result> installDeps(bool includeDevDeps) const; + rs::Result> installDeps(bool includeDevDeps) const; private: Manifest(fs::path path, Package package, std::vector dependencies, @@ -142,7 +142,7 @@ class Manifest { profiles(std::move(profiles)), lint(std::move(lint)) {} }; -Result validatePackageName(std::string_view name) noexcept; +rs::Result validatePackageName(std::string_view name) noexcept; } // namespace cabin diff --git a/include/Semver.hpp b/include/Semver.hpp index 5329d194d..bdd793f0d 100644 --- a/include/Semver.hpp +++ b/include/Semver.hpp @@ -49,7 +49,7 @@ struct VersionToken { struct Prerelease { std::vector ident; - static Result parse(std::string_view str) noexcept; + static rs::Result parse(std::string_view str) noexcept; bool empty() const noexcept; std::string toString() const noexcept; }; @@ -63,7 +63,7 @@ bool operator>=(const Prerelease& lhs, const Prerelease& rhs) noexcept; struct BuildMetadata { std::vector ident; - static Result parse(std::string_view str) noexcept; + static rs::Result parse(std::string_view str) noexcept; bool empty() const noexcept; std::string toString() const noexcept; }; @@ -75,7 +75,7 @@ struct Version { Prerelease pre; BuildMetadata build; - static Result parse(std::string_view str) noexcept; + static rs::Result parse(std::string_view str) noexcept; std::string toString() const noexcept; uint64_t toNum() const noexcept; }; @@ -99,10 +99,10 @@ struct VersionLexer { constexpr bool isEof() const noexcept { return pos >= s.size(); } constexpr void step() noexcept { ++pos; } VersionToken consumeIdent() noexcept; - Result consumeNum() noexcept; - Result consumeNumOrIdent() noexcept; - Result next() noexcept; - Result peek() noexcept; + rs::Result consumeNum() noexcept; + rs::Result consumeNumOrIdent() noexcept; + rs::Result next() noexcept; + rs::Result peek() noexcept; constexpr char curChar() const noexcept { return isEof() ? '\0' : s[pos]; } }; @@ -112,11 +112,11 @@ struct VersionParser { constexpr explicit VersionParser(const std::string_view str) noexcept : lexer(str) {} - Result parse() noexcept; - Result parseNum() noexcept; - Result parseDot() noexcept; - Result parsePre() noexcept; - Result parseNumOrIdent() noexcept; - Result parseBuild() noexcept; - Result parseIdent() noexcept; + rs::Result parse() noexcept; + rs::Result parseNum() noexcept; + rs::Result parseDot() noexcept; + rs::Result parsePre() noexcept; + rs::Result parseNumOrIdent() noexcept; + rs::Result parseBuild() noexcept; + rs::Result parseIdent() noexcept; }; diff --git a/include/VersionReq.hpp b/include/VersionReq.hpp index f0758497d..460301293 100644 --- a/include/VersionReq.hpp +++ b/include/VersionReq.hpp @@ -77,7 +77,7 @@ struct Comparator { std::optional patch; Prerelease pre; - static Result parse(std::string_view str) noexcept; + static rs::Result parse(std::string_view str) noexcept; void from(const OptVersion& ver) noexcept; std::string toString() const noexcept; std::string toPkgConfigString() const noexcept; @@ -89,8 +89,8 @@ struct VersionReq { Comparator left; std::optional right; - static Result parse(std::string_view str) noexcept; - static Result tryParse(std::string_view str) noexcept; + static rs::Result parse(std::string_view str) noexcept; + static rs::Result tryParse(std::string_view str) noexcept; bool satisfiedBy(const Version& ver) const noexcept; std::string toString() const noexcept; std::string toPkgConfigString(std::string_view name) const noexcept; diff --git a/lib/Algos.cc b/lib/Algos.cc index 780dd58bc..5644e7834 100644 --- a/lib/Algos.cc +++ b/lib/Algos.cc @@ -44,22 +44,22 @@ std::string replaceAll(std::string str, const std::string_view from, return str; } -Result execCmd(const Command& cmd) noexcept { +rs::Result execCmd(const Command& cmd) noexcept { spdlog::debug("Running `{}`", cmd.toString()); - return Try(cmd.spawn()).wait(); + return rs_try(cmd.spawn()).wait(); } -Result getCmdOutput(const Command& cmd, - const std::size_t retry) noexcept { +rs::Result getCmdOutput(const Command& cmd, + const std::size_t retry) noexcept { spdlog::trace("Running `{}`", cmd.toString()); ExitStatus exitStatus; std::string stdErr; int waitTime = 1; for (std::size_t i = 0; i < retry; ++i) { - const auto cmdOut = Try(cmd.output()); + const auto cmdOut = rs_try(cmd.output()); if (cmdOut.exitStatus.success()) { - return Ok(cmdOut.stdOut); + return rs::Ok(cmdOut.stdOut); } exitStatus = cmdOut.exitStatus; stdErr = cmdOut.stdErr; @@ -69,10 +69,10 @@ Result getCmdOutput(const Command& cmd, waitTime *= 2; } - return Result( - Err(anyhow::anyhow("Command `{}` {}", cmd.toString(), exitStatus))) + return rs::Result( + rs::Err(rs::anyhow("Command `{}` {}", cmd.toString(), exitStatus))) .with_context( - [stdErr = std::move(stdErr)] { return anyhow::anyhow(stdErr); }); + [stdErr = std::move(stdErr)] { return rs::anyhow(stdErr); }); } bool commandExists(const std::string_view cmd) noexcept { @@ -93,8 +93,6 @@ bool commandExists(const std::string_view cmd) noexcept { # include # include -namespace tests { - using namespace cabin; // NOLINT(build/namespaces,google-build-using-namespace) using std::string_view_literals::operator""sv; @@ -116,17 +114,17 @@ static void testToLower() { static_assert(toLower(' ') == ' '); static_assert(toLower('~') == '~'); - pass(); + rs::pass(); } static void testLevDistance() { // Test bytelength agnosticity for (char c = 0; c < std::numeric_limits::max(); ++c) { const std::string str(1, c); - assertEq(levDistance(str, str), 0UL); + rs::assertEq(levDistance(str, str), 0UL); } - pass(); + rs::pass(); } static void testLevDistance2() { @@ -151,7 +149,7 @@ static void testLevDistance2() { static_assert(levDistance("aab", "aac") == 1UL); static_assert(levDistance("aaab", "aaac") == 1UL); - pass(); + rs::pass(); } // ref: @@ -178,7 +176,7 @@ static void testFindSimilarStr() { static_assert( !findSimilarStr("special_compiler_directive", candidates).has_value()); - pass(); + rs::pass(); } static void testFindSimilarStr2() { @@ -189,17 +187,15 @@ static void testFindSimilarStr2() { constexpr std::array candidates2{ "AAAA" }; static_assert(findSimilarStr("aaaa", candidates2) == "AAAA"sv); - pass(); + rs::pass(); } -} // namespace tests - int main() { - tests::testToLower(); - tests::testLevDistance(); - tests::testLevDistance2(); - tests::testFindSimilarStr(); - tests::testFindSimilarStr2(); + testToLower(); + testLevDistance(); + testLevDistance2(); + testFindSimilarStr(); + testFindSimilarStr2(); } #endif diff --git a/lib/Builder/BuildGraph.cc b/lib/Builder/BuildGraph.cc index e0256eb6e..dd8ed4847 100644 --- a/lib/Builder/BuildGraph.cc +++ b/lib/Builder/BuildGraph.cc @@ -106,8 +106,8 @@ BuildGraph::BuildGraph(BuildProfile buildProfileIn, std::string libNameIn, compiler(std::move(compilerIn)), buildProfile_(std::move(buildProfileIn)), libName(std::move(libNameIn)), ninjaPlan(outBasePath_) {} -Result BuildGraph::create(const Manifest& manifest, - const BuildProfile& buildProfile) { +rs::Result BuildGraph::create(const Manifest& manifest, + const BuildProfile& buildProfile) { std::string libName; if (manifest.package.name.starts_with("lib")) { libName = fmt::format("{}.a", manifest.package.name); @@ -115,9 +115,9 @@ Result BuildGraph::create(const Manifest& manifest, libName = fmt::format("lib{}.a", manifest.package.name); } - Project project = Try(Project::init(buildProfile, manifest)); - return Ok(BuildGraph(buildProfile, std::move(libName), std::move(project), - Try(Compiler::init()))); + Project project = rs_try(Project::init(buildProfile, manifest)); + return rs::Ok(BuildGraph(buildProfile, std::move(libName), std::move(project), + rs_try(Compiler::init()))); } bool BuildGraph::isUpToDate(const std::string_view fileName) const { @@ -229,8 +229,8 @@ void BuildGraph::writeBuildFiles() const { ninjaPlan.writeFiles(toolchain); } -Result BuildGraph::runMM(const std::string& sourceFile, - const bool isTest) const { +rs::Result BuildGraph::runMM(const std::string& sourceFile, + const bool isTest) const { Command command = compiler.makeMMCmd(project.compilerOpts, sourceFile); if (isTest) { command.addArg("-DCABIN_TEST"); @@ -239,7 +239,8 @@ Result BuildGraph::runMM(const std::string& sourceFile, return getCmdOutput(command); } -Result BuildGraph::containsTestCode(const std::string& sourceFile) const { +rs::Result +BuildGraph::containsTestCode(const std::string& sourceFile) const { std::ifstream ifs(sourceFile); std::string line; while (std::getline(ifs, line)) { @@ -249,37 +250,37 @@ Result BuildGraph::containsTestCode(const std::string& sourceFile) const { Command command = compiler.makePreprocessCmd(project.compilerOpts, sourceFile); - const std::string src = Try(getCmdOutput(command)); + const std::string src = rs_try(getCmdOutput(command)); command.addArg("-DCABIN_TEST"); - const std::string testSrc = Try(getCmdOutput(command)); + const std::string testSrc = rs_try(getCmdOutput(command)); const bool containsTest = src != testSrc; if (containsTest) { spdlog::trace("Found test code: {}", sourceFile); } - return Ok(containsTest); + return rs::Ok(containsTest); } - return Ok(false); + return rs::Ok(false); } -Result +rs::Result BuildGraph::processSrc(const fs::path& sourceFilePath, const SourceRoot& root, std::unordered_set& buildObjTargets, tbb::spin_mutex* mtx) { std::string objTarget; const std::unordered_set objTargetDeps = - parseMMOutput(Try(runMM(sourceFilePath)), objTarget); + parseMMOutput(rs_try(runMM(sourceFilePath)), objTarget); std::error_code ec; const fs::path targetBaseDir = fs::relative(sourceFilePath.parent_path(), root.directory, ec); - Ensure(!ec, "failed to compute relative path for {}", sourceFilePath); + rs_ensure(!ec, "failed to compute relative path for {}", sourceFilePath); if (!targetBaseDir.empty()) { const auto first = targetBaseDir.begin(); - Ensure(first == targetBaseDir.end() || *first != "..", - "source file `{}` must reside under `{}`", sourceFilePath, - root.directory); + rs_ensure(first == targetBaseDir.end() || *first != "..", + "source file `{}` must reside under `{}`", sourceFilePath, + root.directory); } fs::path buildTargetBaseDir = project.buildOutPath; if (!root.objectSubdir.empty()) { @@ -302,10 +303,10 @@ BuildGraph::processSrc(const fs::path& sourceFilePath, const SourceRoot& root, if (mtx) { mtx->unlock(); } - return Ok(); + return rs::Ok(); } -Result> +rs::Result> BuildGraph::processSources(const std::vector& sourceFilePaths, const SourceRoot& root) { std::unordered_set buildObjTargets; @@ -325,26 +326,26 @@ BuildGraph::processSources(const std::vector& sourceFilePaths, } }); if (!results.empty()) { - Bail("{}", fmt::join(results, "\n")); + rs_bail("{}", fmt::join(results, "\n")); } } else { for (const fs::path& sourceFilePath : sourceFilePaths) { - Try(processSrc(sourceFilePath, root, buildObjTargets)); + rs_try(processSrc(sourceFilePath, root, buildObjTargets)); } } - return Ok(buildObjTargets); + return rs::Ok(buildObjTargets); } -Result> +rs::Result> BuildGraph::processUnittestSrc(const fs::path& sourceFilePath, tbb::spin_mutex* mtx) { - if (!Try(containsTestCode(sourceFilePath))) { - return Ok(std::optional()); + if (!rs_try(containsTestCode(sourceFilePath))) { + return rs::Ok(std::optional()); } std::string objTarget; const std::unordered_set objTargetDeps = - parseMMOutput(Try(runMM(sourceFilePath, /*isTest=*/true)), objTarget); + parseMMOutput(rs_try(runMM(sourceFilePath, /*isTest=*/true)), objTarget); fs::path relBase = fs::path("unit"); @@ -406,8 +407,8 @@ BuildGraph::processUnittestSrc(const fs::path& sourceFilePath, std::error_code relRootEc; const fs::path relRootParent = fs::relative(sourceFilePath.parent_path(), project.rootPath, relRootEc); - Ensure(!relRootEc, "failed to compute relative path for {}", - sourceFilePath); + rs_ensure(!relRootEc, "failed to compute relative path for {}", + sourceFilePath); if (relRootParent != "." && !relRootParent.empty()) { relBase /= relRootParent; } @@ -460,15 +461,15 @@ BuildGraph::processUnittestSrc(const fs::path& sourceFilePath, fs::relative(sourceFilePath, project.rootPath).generic_string(); testTarget.kind = TestKind::Unit; - return Ok(std::optional(std::move(testTarget))); + return rs::Ok(std::optional(std::move(testTarget))); } -Result> +rs::Result> BuildGraph::processIntegrationTestSrc(const fs::path& sourceFilePath, tbb::spin_mutex* mtx) { std::string objTarget; const std::unordered_set objTargetDeps = - parseMMOutput(Try(runMM(sourceFilePath, /*isTest=*/true)), objTarget); + parseMMOutput(rs_try(runMM(sourceFilePath, /*isTest=*/true)), objTarget); const fs::path targetBaseDir = fs::relative(sourceFilePath.parent_path(), project.rootPath / "tests"); @@ -512,7 +513,7 @@ BuildGraph::processIntegrationTestSrc(const fs::path& sourceFilePath, fs::relative(sourceFilePath, project.rootPath).generic_string(); testTarget.kind = TestKind::Integration; - return Ok(std::optional(std::move(testTarget))); + return rs::Ok(std::optional(std::move(testTarget))); } void BuildGraph::collectBinDepObjs( @@ -546,14 +547,14 @@ void BuildGraph::collectBinDepObjs( } } -Result BuildGraph::installDeps(const bool includeDevDeps) { +rs::Result BuildGraph::installDeps(const bool includeDevDeps) { const std::vector depsCompOpts = - Try(project.manifest.installDeps(includeDevDeps)); + rs_try(project.manifest.installDeps(includeDevDeps)); for (const CompilerOpts& depOpts : depsCompOpts) { project.compilerOpts.merge(depOpts); } - return Ok(); + return rs::Ok(); } void BuildGraph::enableCoverage() { @@ -561,7 +562,7 @@ void BuildGraph::enableCoverage() { project.compilerOpts.ldFlags.others.emplace_back("--coverage"); } -Result BuildGraph::configure() { +rs::Result BuildGraph::configure() { const fs::path srcDir = project.rootPath / "src"; const bool hasSrcDir = fs::exists(srcDir); const fs::path libDir = project.rootPath / "lib"; @@ -587,7 +588,7 @@ Result BuildGraph::configure() { continue; } if (!mainSource.empty()) { - Bail("multiple main sources were found"); + rs_bail("multiple main sources were found"); } mainSource = path; hasBinaryTarget_ = true; @@ -632,16 +633,16 @@ Result BuildGraph::configure() { hasLibraryTarget_ = !publicSourceFilePaths.empty(); if (!hasBinaryTarget_ && !hasLibraryTarget_) { - Bail("expected either `src/main{}` or at least one source file under " - "`lib/` matching {}", - SOURCE_FILE_EXTS, SOURCE_FILE_EXTS); + rs_bail("expected either `src/main{}` or at least one source file under " + "`lib/` matching {}", + SOURCE_FILE_EXTS, SOURCE_FILE_EXTS); } const SourceRoot srcRoot(srcDir); const SourceRoot libRoot(libDir, fs::path("lib")); const std::unordered_set srcObjTargets = - Try(processSources(sourceFilePaths, srcRoot)); + rs_try(processSources(sourceFilePaths, srcRoot)); srcObjectTargets = srcObjTargets; std::erase_if(srcObjectTargets, [](const std::string& obj) { return obj == "main.o" || obj.ends_with("/main.o"); @@ -649,7 +650,7 @@ Result BuildGraph::configure() { std::unordered_set libObjTargets; if (!publicSourceFilePaths.empty()) { - libObjTargets = Try(processSources(publicSourceFilePaths, libRoot)); + libObjTargets = rs_try(processSources(publicSourceFilePaths, libRoot)); } std::unordered_set buildObjTargets = srcObjTargets; @@ -659,8 +660,8 @@ Result BuildGraph::configure() { const fs::path mainObjPath = project.buildOutPath / "main.o"; const std::string mainObj = fs::relative(mainObjPath, outBasePath_).generic_string(); - Ensure(compileUnits.contains(mainObj), - "internal error: missing compile unit for {}", mainObj); + rs_ensure(compileUnits.contains(mainObj), + "internal error: missing compile unit for {}", mainObj); std::unordered_set deps = { mainObj }; collectBinDepObjs(deps, "", compileUnits.at(mainObj).dependencies, @@ -704,8 +705,8 @@ Result BuildGraph::configure() { libraryInputs.push_back(obj); } - Ensure(!libraryInputs.empty(), - "internal error: expected objects for library target"); + rs_ensure(!libraryInputs.empty(), + "internal error: expected objects for library target"); std::ranges::sort(libraryInputs); NinjaEdge archiveEdge; @@ -721,14 +722,14 @@ Result BuildGraph::configure() { std::vector discoveredTests; discoveredTests.reserve(sourceFilePaths.size()); for (const fs::path& sourceFilePath : sourceFilePaths) { - if (auto maybeTarget = Try(processUnittestSrc(sourceFilePath)); + if (auto maybeTarget = rs_try(processUnittestSrc(sourceFilePath)); maybeTarget.has_value()) { discoveredTests.push_back(std::move(maybeTarget.value())); } } for (const fs::path& sourceFilePath : publicSourceFilePaths) { - if (auto maybeTarget = Try(processUnittestSrc(sourceFilePath)); + if (auto maybeTarget = rs_try(processUnittestSrc(sourceFilePath)); maybeTarget.has_value()) { discoveredTests.push_back(std::move(maybeTarget.value())); } @@ -739,7 +740,8 @@ Result BuildGraph::configure() { const std::vector integrationSources = listSourceFilePaths(integrationTestDir); for (const fs::path& sourceFilePath : integrationSources) { - if (auto maybeTarget = Try(processIntegrationTestSrc(sourceFilePath)); + if (auto maybeTarget = + rs_try(processIntegrationTestSrc(sourceFilePath)); maybeTarget.has_value()) { discoveredTests.push_back(std::move(maybeTarget.value())); } @@ -763,18 +765,18 @@ Result BuildGraph::configure() { ninjaPlan.setTestTargets({}); } - return Ok(); + return rs::Ok(); } -Result BuildGraph::writeBuildFilesIfNeeded() const { +rs::Result BuildGraph::writeBuildFilesIfNeeded() const { if (isUpToDate("build.ninja")) { - return Ok(); + return rs::Ok(); } writeBuildFiles(); - return Ok(); + return rs::Ok(); } -Result BuildGraph::generateCompdb() const { +rs::Result BuildGraph::generateCompdb() const { const fs::path& outDir = outBasePath_; const fs::path cabinOutRoot = outDir.parent_path(); @@ -806,17 +808,17 @@ Result BuildGraph::generateCompdb() const { compdbCmd.addArg("-C").addArg(buildDir.string()); compdbCmd.addArg("-t").addArg("compdb"); compdbCmd.addArg("cxx_compile"); - const CommandOutput output = Try(compdbCmd.output()); - Ensure(output.exitStatus.success(), "ninja -t compdb {}", - output.exitStatus); + const CommandOutput output = rs_try(compdbCmd.output()); + rs_ensure(output.exitStatus.success(), "ninja -t compdb {}", + output.exitStatus); nlohmann::json json; try { json = nlohmann::json::parse(output.stdOut); } catch (const nlohmann::json::parse_error& e) { - Bail("failed to parse ninja -t compdb output: {}", e.what()); + rs_bail("failed to parse ninja -t compdb output: {}", e.what()); } - Ensure(json.is_array(), "invalid compdb output"); + rs_ensure(json.is_array(), "invalid compdb output"); for (auto& entry : json) { const auto directory = entry.value("directory", std::string_view{}); const auto file = entry.value("file", std::string_view{}); @@ -836,10 +838,10 @@ Result BuildGraph::generateCompdb() const { std::ofstream aggregateFile(cabinOutRoot / "compile_commands.json"); aggregateFile << combined.dump(2) << '\n'; - return Ok(); + return rs::Ok(); } -Result BuildGraph::plan(const bool logAnalysis) { +rs::Result BuildGraph::plan(const bool logAnalysis) { if (logAnalysis) { Diag::info("Analyzing", "project dependencies..."); } @@ -847,13 +849,13 @@ Result BuildGraph::plan(const bool logAnalysis) { const bool buildProj = !isUpToDate("build.ninja"); spdlog::debug("build.ninja is {}up to date", buildProj ? "NOT " : ""); - Try(configure()); + rs_try(configure()); if (buildProj) { writeBuildFiles(); } - Try(generateCompdb()); + rs_try(generateCompdb()); - return Ok(); + return rs::Ok(); } // NOLINTNEXTLINE(readability-convert-member-functions-to-static) @@ -871,7 +873,7 @@ Command BuildGraph::ninjaCommand(const bool forDryRun) const { return ninja; } -Result +rs::Result BuildGraph::needsBuild(const std::vector& targets) const { Command dryRunCmd = ninjaCommand(true); dryRunCmd.addArg("-C").addArg(outBasePath_.string()).addArg("-n"); @@ -879,13 +881,13 @@ BuildGraph::needsBuild(const std::vector& targets) const { dryRunCmd.addArg(target); } - const CommandOutput dryRun = Try(dryRunCmd.output()); + const CommandOutput dryRun = rs_try(dryRunCmd.output()); static constexpr std::string_view noWorkMsg = "ninja: no work to do."; const bool hasNoWork = dryRun.stdOut.contains(noWorkMsg); - return Ok(!hasNoWork || !dryRun.exitStatus.success()); + return rs::Ok(!hasNoWork || !dryRun.exitStatus.success()); } -Result +rs::Result BuildGraph::buildTargets(const std::vector& targets, const std::string_view displayName) const { Command buildCmd = ninjaCommand(false); @@ -894,7 +896,7 @@ BuildGraph::buildTargets(const std::vector& targets, buildCmd.addArg(target); } - if (Try(needsBuild(targets))) { + if (rs_try(needsBuild(targets))) { Diag::info("Compiling", "{} v{} ({})", displayName, project.manifest.package.version.toString(), project.manifest.path.parent_path().string()); diff --git a/lib/Builder/Compiler.cc b/lib/Builder/Compiler.cc index e116c0f6f..7855ec04f 100644 --- a/lib/Builder/Compiler.cc +++ b/lib/Builder/Compiler.cc @@ -143,11 +143,11 @@ static std::optional envArchiverOverride() { // be treated as a single flag). The current code just splits the output by // space. -Result +rs::Result CFlags::parsePkgConfig(const std::string_view pkgConfigVer) noexcept { const Command pkgConfigCmd = Command("pkg-config").addArg("--cflags").addArg(pkgConfigVer); - std::string output = Try(getCmdOutput(pkgConfigCmd)); + std::string output = rs_try(getCmdOutput(pkgConfigCmd)); output.pop_back(); // remove '\n' std::vector macros; // -D= @@ -187,7 +187,7 @@ CFlags::parsePkgConfig(const std::string_view pkgConfigVer) noexcept { parseCFlag(flag); } - return Ok(CFlags( // + return rs::Ok(CFlags( // std::move(macros), std::move(includeDirs), std::move(others))); } @@ -198,11 +198,11 @@ void CFlags::merge(const CFlags& other) noexcept { others.insert(others.end(), other.others.begin(), other.others.end()); } -Result +rs::Result LdFlags::parsePkgConfig(const std::string_view pkgConfigVer) noexcept { const Command pkgConfigCmd = Command("pkg-config").addArg("--libs").addArg(pkgConfigVer); - std::string output = Try(getCmdOutput(pkgConfigCmd)); + std::string output = rs_try(getCmdOutput(pkgConfigCmd)); output.pop_back(); // remove '\n' std::vector libDirs; // -L @@ -236,7 +236,8 @@ LdFlags::parsePkgConfig(const std::string_view pkgConfigVer) noexcept { parseLdFlag(flag); } - return Ok(LdFlags(std::move(libDirs), std::move(libs), std::move(others))); + return rs::Ok( + LdFlags(std::move(libDirs), std::move(libs), std::move(others))); } LdFlags::LdFlags(std::vector libDirs, std::vector libs, @@ -271,13 +272,13 @@ void LdFlags::merge(const LdFlags& other) noexcept { libs.insert(libs.end(), dedupLibs.begin(), dedupLibs.end()); } -Result +rs::Result CompilerOpts::parsePkgConfig(const VersionReq& pkgVerReq, const std::string_view pkgName) noexcept { const std::string pkgConfigVer = pkgVerReq.toPkgConfigString(pkgName); - CFlags cFlags = Try(CFlags::parsePkgConfig(pkgConfigVer)); - LdFlags ldFlags = Try(LdFlags::parsePkgConfig(pkgConfigVer)); - return Ok(CompilerOpts(std::move(cFlags), std::move(ldFlags))); + CFlags cFlags = rs_try(CFlags::parsePkgConfig(pkgConfigVer)); + LdFlags ldFlags = rs_try(LdFlags::parsePkgConfig(pkgConfigVer)); + return rs::Ok(CompilerOpts(std::move(cFlags), std::move(ldFlags))); } void CompilerOpts::merge(const CompilerOpts& other) noexcept { @@ -289,20 +290,20 @@ Compiler Compiler::init(std::string cxx) noexcept { return Compiler(std::move(cxx)); } -Result Compiler::init() noexcept { +rs::Result Compiler::init() noexcept { if (const char* cxxP = std::getenv("CXX")) { - return Ok(Compiler::init(std::string(cxxP))); + return rs::Ok(Compiler::init(std::string(cxxP))); } static constexpr std::array candidates{ "c++", "g++", "clang++" }; for (const std::string_view candidate : candidates) { if (commandExists(candidate)) { - return Ok(Compiler::init(std::string(candidate))); + return rs::Ok(Compiler::init(std::string(candidate))); } } - return Err(anyhow::anyhow("failed to locate a C++ compiler, set $CXX")); + return rs::Err(rs::anyhow("failed to locate a C++ compiler, set $CXX")); } Command Compiler::makeCompileCmd(const CompilerOpts& opts, @@ -371,15 +372,13 @@ std::string Compiler::detectArchiver(const bool useLTO) const { # include -namespace tests { - using namespace cabin; // NOLINT(build/namespaces,google-build-using-namespace) static void testMakeToolNameForCompiler() { auto expectValue = [](const std::optional& value, const std::string& expected) { - assertTrue(value.has_value()); - assertEq(*value, expected); + rs::assertTrue(value.has_value()); + rs::assertEq(*value, expected); }; expectValue(makeToolNameForCompiler("clang++", "clang++", "llvm-ar"), @@ -393,14 +392,14 @@ static void testMakeToolNameForCompiler() { makeToolNameForCompiler("x86_64-w64-mingw32-g++-13", "g++", "gcc-ar"), "x86_64-w64-mingw32-gcc-ar-13"); - assertFalse(makeToolNameForCompiler("clang++", "g++", "gcc-ar").has_value()); - assertFalse(makeToolNameForCompiler("foo", "clang++", "llvm-ar").has_value()); + rs::assertFalse( + makeToolNameForCompiler("clang++", "g++", "gcc-ar").has_value()); + rs::assertFalse( + makeToolNameForCompiler("foo", "clang++", "llvm-ar").has_value()); - pass(); + rs::pass(); } -} // namespace tests - -int main() { tests::testMakeToolNameForCompiler(); } +int main() { testMakeToolNameForCompiler(); } #endif diff --git a/lib/Builder/DepGraph.cc b/lib/Builder/DepGraph.cc index 984d0ac60..11282758b 100644 --- a/lib/Builder/DepGraph.cc +++ b/lib/Builder/DepGraph.cc @@ -4,14 +4,15 @@ namespace cabin { -Result DepGraph::resolve() { - rootManifest.emplace(Try(Manifest::tryParse(rootPath / Manifest::FILE_NAME))); - return Ok(); +rs::Result DepGraph::resolve() { + rootManifest.emplace( + rs_try(Manifest::tryParse(rootPath / Manifest::FILE_NAME))); + return rs::Ok(); } -Result +rs::Result DepGraph::computeBuildGraph(const BuildProfile& buildProfile) const { - Ensure(rootManifest.has_value(), "dependency graph not resolved"); + rs_ensure(rootManifest.has_value(), "dependency graph not resolved"); return BuildGraph::create(*rootManifest, buildProfile); } diff --git a/lib/Command.cc b/lib/Command.cc index 431685cfa..8ba78b375 100644 --- a/lib/Command.cc +++ b/lib/Command.cc @@ -49,7 +49,7 @@ std::string ExitStatus::toString() const { return "unknown status"; } -Result Child::wait() const noexcept { +rs::Result Child::wait() const noexcept { int status{}; if (waitpid(pid, &status, 0) == -1) { if (stdOutFd != -1) { @@ -58,7 +58,7 @@ Result Child::wait() const noexcept { if (stdErrFd != -1) { close(stdErrFd); } - Bail("waitpid() failed"); + rs_bail("waitpid() failed"); } if (stdOutFd != -1) { @@ -68,10 +68,10 @@ Result Child::wait() const noexcept { close(stdErrFd); } - return Ok(ExitStatus{ status }); + return rs::Ok(ExitStatus{ status }); } -Result Child::waitWithOutput() const noexcept { +rs::Result Child::waitWithOutput() const noexcept { std::string stdOutOutput; std::string stdErrOutput; @@ -102,7 +102,7 @@ Result Child::waitWithOutput() const noexcept { if (stdErrFd != -1) { close(stdErrFd); } - Bail("select() failed"); + rs_bail("select() failed"); } // Read from stdout if available @@ -116,7 +116,7 @@ Result Child::waitWithOutput() const noexcept { if (stdErrFd != -1) { close(stdErrFd); } - Bail("read() failed on stdout"); + rs_bail("read() failed on stdout"); } else if (count == 0) { stdOutEOF = true; close(stdOutFd); @@ -136,7 +136,7 @@ Result Child::waitWithOutput() const noexcept { if (stdErrFd != -1) { close(stdErrFd); } - Bail("read() failed on stderr"); + rs_bail("read() failed on stderr"); } else if (count == 0) { stdErrEOF = true; close(stdErrFd); @@ -148,33 +148,33 @@ Result Child::waitWithOutput() const noexcept { int status{}; if (waitpid(pid, &status, 0) == -1) { - Bail("waitpid() failed"); + rs_bail("waitpid() failed"); } - return Ok(CommandOutput{ .exitStatus = ExitStatus{ status }, - .stdOut = stdOutOutput, - .stdErr = stdErrOutput }); + return rs::Ok(CommandOutput{ .exitStatus = ExitStatus{ status }, + .stdOut = stdOutOutput, + .stdErr = stdErrOutput }); } -Result Command::spawn() const noexcept { +rs::Result Command::spawn() const noexcept { std::array stdOutPipe{}; std::array stdErrPipe{}; // Set up stdout pipe if needed if (stdOutConfig == IOConfig::Piped) { if (pipe(stdOutPipe.data()) == -1) { - Bail("pipe() failed for stdout"); + rs_bail("pipe() failed for stdout"); } } // Set up stderr pipe if needed if (stdErrConfig == IOConfig::Piped) { if (pipe(stdErrPipe.data()) == -1) { - Bail("pipe() failed for stderr"); + rs_bail("pipe() failed for stderr"); } } const pid_t pid = fork(); if (pid == -1) { - Bail("fork() failed"); + rs_bail("fork() failed"); } else if (pid == 0) { // Child process @@ -252,16 +252,17 @@ Result Command::spawn() const noexcept { } // Return the Child object with appropriate file descriptors - return Ok(Child{ pid, stdOutConfig == IOConfig::Piped ? stdOutPipe[0] : -1, - stdErrConfig == IOConfig::Piped ? stdErrPipe[0] : -1 }); + return rs::Ok( + Child{ pid, stdOutConfig == IOConfig::Piped ? stdOutPipe[0] : -1, + stdErrConfig == IOConfig::Piped ? stdErrPipe[0] : -1 }); } } -Result Command::output() const noexcept { +rs::Result Command::output() const noexcept { Command cmd = *this; cmd.setStdOutConfig(IOConfig::Piped); cmd.setStdErrConfig(IOConfig::Piped); - return Try(cmd.spawn()).waitWithOutput(); + return rs_try(cmd.spawn()).waitWithOutput(); } std::string Command::toString() const { diff --git a/lib/Dependency.cc b/lib/Dependency.cc index e191c82d6..d129ab3d5 100644 --- a/lib/Dependency.cc +++ b/lib/Dependency.cc @@ -25,7 +25,7 @@ static const fs::path CACHE_DIR(getXdgCacheHome() / "cabin"); static const fs::path GIT_DIR(CACHE_DIR / "git"); static const fs::path GIT_SRC_DIR(GIT_DIR / "src"); -Result GitDependency::install() const { +rs::Result GitDependency::install() const { fs::path installDir = GIT_SRC_DIR / name; if (target.has_value()) { installDir += '-' + target.value(); @@ -59,17 +59,17 @@ Result GitDependency::install() const { include = installDir; } - return Ok(CompilerOpts(CFlags({}, { IncludeDir{ include } }, {}), - // Currently, no libs are supported. - LdFlags())); + return rs::Ok(CompilerOpts(CFlags({}, { IncludeDir{ include } }, {}), + // Currently, no libs are supported. + LdFlags())); } -Result PathDependency::install() const { +rs::Result PathDependency::install() const { const fs::path installDir = fs::weakly_canonical(path); if (fs::exists(installDir) && !fs::is_empty(installDir)) { spdlog::debug("{} is already installed", name); } else { - Bail("{} can't be accessible as directory", installDir.string()); + rs_bail("{} can't be accessible as directory", installDir.string()); } const fs::path includeDir = installDir / "include"; @@ -82,12 +82,12 @@ Result PathDependency::install() const { include = installDir; } - return Ok(CompilerOpts(CFlags({}, { IncludeDir{ include } }, {}), - // Currently, no libs are supported. - LdFlags())); + return rs::Ok(CompilerOpts(CFlags({}, { IncludeDir{ include } }, {}), + // Currently, no libs are supported. + LdFlags())); } -Result SystemDependency::install() const { +rs::Result SystemDependency::install() const { return CompilerOpts::parsePkgConfig(versionReq, name); } diff --git a/lib/Manifest.cc b/lib/Manifest.cc index 37eec9b26..16f2e4bbb 100644 --- a/lib/Manifest.cc +++ b/lib/Manifest.cc @@ -28,7 +28,7 @@ namespace toml { template // NOLINTNEXTLINE(readability-identifier-naming,cppcoreguidelines-macro-usage) -inline Result try_find(const toml::value& v, const U&... u) noexcept { +inline rs::Result try_find(const toml::value& v, const U&... u) noexcept { using std::string_view_literals::operator""sv; if (cabin::shouldColorStderr()) { @@ -38,7 +38,7 @@ inline Result try_find(const toml::value& v, const U&... u) noexcept { } try { - return Ok(toml::find(v, u...)); + return rs::Ok(toml::find(v, u...)); } catch (const std::exception& e) { std::string what = e.what(); @@ -55,7 +55,7 @@ inline Result try_find(const toml::value& v, const U&... u) noexcept { if (what.back() == '\n') { what.pop_back(); // remove the last '\n' since Diag::error adds one. } - return Err(anyhow::anyhow(what)); + return rs::Err(rs::anyhow(what)); } } @@ -102,13 +102,13 @@ static fs::path canonicalizePathDep(const fs::path& baseDir, return depRoot; } -static Result +static rs::Result installDependencies(const Manifest& manifest, bool includeDevDeps, std::unordered_map& seenDeps, std::unordered_set& visited, std::vector& installed); -static Result +static rs::Result installPathDependency(const Manifest& manifest, const PathDependency& pathDep, bool includeDevDeps, std::unordered_map& seenDeps, @@ -117,10 +117,10 @@ installPathDependency(const Manifest& manifest, const PathDependency& pathDep, const fs::path basePath = manifest.path.parent_path(); const fs::path depRoot = canonicalizePathDep(basePath, pathDep.path); - Ensure(fs::exists(depRoot) && fs::is_directory(depRoot), - "{} can't be accessible as directory", depRoot.string()); + rs_ensure(fs::exists(depRoot) && fs::is_directory(depRoot), + "{} can't be accessible as directory", depRoot.string()); if (!visited.insert(depRoot).second) { - return Ok(); + return rs::Ok(); } CompilerOpts pathOpts; @@ -128,19 +128,20 @@ installPathDependency(const Manifest& manifest, const PathDependency& pathDep, /*isSystem=*/false); const fs::path depManifestPath = depRoot / Manifest::FILE_NAME; - Ensure(fs::exists(depManifestPath), "missing `{}` in path dependency {}", - Manifest::FILE_NAME, depRoot.string()); - const Manifest depManifest = Try(Manifest::tryParse(depManifestPath, false)); + rs_ensure(fs::exists(depManifestPath), "missing `{}` in path dependency {}", + Manifest::FILE_NAME, depRoot.string()); + const Manifest depManifest = + rs_try(Manifest::tryParse(depManifestPath, false)); std::vector nestedDeps; - Try(installDependencies(depManifest, includeDevDeps, seenDeps, visited, - nestedDeps)); + rs_try(installDependencies(depManifest, includeDevDeps, seenDeps, visited, + nestedDeps)); for (const CompilerOpts& opts : nestedDeps) { pathOpts.merge(opts); } installed.emplace_back(std::move(pathOpts)); - return Ok(); + return rs::Ok(); } static DepKey makeDepKey(const Manifest& manifest, const Dependency& dep) { @@ -184,97 +185,99 @@ static const std::string& depName(const Dependency& dep) { dep); } -static Result rememberDep(const Manifest& manifest, const Dependency& dep, - std::unordered_map& seen) { +static rs::Result +rememberDep(const Manifest& manifest, const Dependency& dep, + std::unordered_map& seen) { const DepKey key = makeDepKey(manifest, dep); const std::string& name = depName(dep); const auto [it, inserted] = seen.emplace(name, key); if (inserted) { - return Ok(); + return rs::Ok(); } if (it->second == key) { - return Ok(); + return rs::Ok(); } - Bail("dependency `{}` conflicts across manifests", name); + rs_bail("dependency `{}` conflicts across manifests", name); } -static Result +static rs::Result installDependencies(const Manifest& manifest, const bool includeDevDeps, std::unordered_map& seenDeps, std::unordered_set& visited, std::vector& installed) { - const auto installOne = [&](const Dependency& dep) -> Result { - Try(rememberDep(manifest, dep, seenDeps)); - return std::visit(Overloaded{ - [&](const GitDependency& gitDep) -> Result { - installed.emplace_back(Try(gitDep.install())); - return Ok(); - }, - [&](const SystemDependency& sysDep) -> Result { - installed.emplace_back(Try(sysDep.install())); - return Ok(); - }, - [&](const PathDependency& pathDep) -> Result { - return installPathDependency( - manifest, pathDep, includeDevDeps, seenDeps, - visited, installed); - }, - }, - dep); + const auto installOne = [&](const Dependency& dep) -> rs::Result { + rs_try(rememberDep(manifest, dep, seenDeps)); + return std::visit( + Overloaded{ + [&](const GitDependency& gitDep) -> rs::Result { + installed.emplace_back(rs_try(gitDep.install())); + return rs::Ok(); + }, + [&](const SystemDependency& sysDep) -> rs::Result { + installed.emplace_back(rs_try(sysDep.install())); + return rs::Ok(); + }, + [&](const PathDependency& pathDep) -> rs::Result { + return installPathDependency(manifest, pathDep, includeDevDeps, + seenDeps, visited, installed); + }, + }, + dep); }; for (const auto& dep : manifest.dependencies) { - Try(installOne(dep)); + rs_try(installOne(dep)); } if (includeDevDeps && manifest.path == Manifest::tryParse().unwrap().path) { for (const auto& dep : manifest.devDependencies) { - Try(installOne(dep)); + rs_try(installOne(dep)); } } - return Ok(); + return rs::Ok(); } -Result Edition::tryFromString(std::string str) noexcept { +rs::Result Edition::tryFromString(std::string str) noexcept { if (str == "98") { - return Ok(Edition(Edition::Cpp98, std::move(str))); + return rs::Ok(Edition(Edition::Cpp98, std::move(str))); } else if (str == "03") { - return Ok(Edition(Edition::Cpp03, std::move(str))); + return rs::Ok(Edition(Edition::Cpp03, std::move(str))); } else if (str == "0x" || str == "11") { - return Ok(Edition(Edition::Cpp11, std::move(str))); + return rs::Ok(Edition(Edition::Cpp11, std::move(str))); } else if (str == "1y" || str == "14") { - return Ok(Edition(Edition::Cpp14, std::move(str))); + return rs::Ok(Edition(Edition::Cpp14, std::move(str))); } else if (str == "1z" || str == "17") { - return Ok(Edition(Edition::Cpp17, std::move(str))); + return rs::Ok(Edition(Edition::Cpp17, std::move(str))); } else if (str == "2a" || str == "20") { - return Ok(Edition(Edition::Cpp20, std::move(str))); + return rs::Ok(Edition(Edition::Cpp20, std::move(str))); } else if (str == "2b" || str == "23") { - return Ok(Edition(Edition::Cpp23, std::move(str))); + return rs::Ok(Edition(Edition::Cpp23, std::move(str))); } else if (str == "2c") { - return Ok(Edition(Edition::Cpp26, std::move(str))); + return rs::Ok(Edition(Edition::Cpp26, std::move(str))); } - Bail("invalid edition"); + rs_bail("invalid edition"); } -Result Package::tryFromToml(const toml::value& val) noexcept { - auto name = Try(toml::try_find(val, "package", "name")); - auto edition = Try(Edition::tryFromString( - Try(toml::try_find(val, "package", "edition")))); - auto version = Try(Version::parse( - Try(toml::try_find(val, "package", "version")))); - return Ok(Package(std::move(name), std::move(edition), std::move(version))); +rs::Result Package::tryFromToml(const toml::value& val) noexcept { + auto name = rs_try(toml::try_find(val, "package", "name")); + auto edition = rs_try(Edition::tryFromString( + rs_try(toml::try_find(val, "package", "edition")))); + auto version = rs_try(Version::parse( + rs_try(toml::try_find(val, "package", "version")))); + return rs::Ok( + Package(std::move(name), std::move(edition), std::move(version))); } -static Result +static rs::Result validateOptLevel(const std::uint8_t optLevel) noexcept { // TODO: use toml::format_error for better diagnostics. - Ensure(optLevel <= 3, "opt-level must be between 0 and 3"); - return Ok(optLevel); + rs_ensure(optLevel <= 3, "opt-level must be between 0 and 3"); + return rs::Ok(optLevel); } -static Result validateFlag(const char* type, - const std::string_view flag) noexcept { - Ensure(!flag.empty() && flag[0] == '-', "{} must start with `-`", type); +static rs::Result validateFlag(const char* type, + const std::string_view flag) noexcept { + rs_ensure(!flag.empty() && flag[0] == '-', "{} must start with `-`", type); static const std::unordered_set allowed{ '-', '_', '=', '+', ':', '.', ',' // `-fsanitize=address,undefined` @@ -284,25 +287,26 @@ static Result validateFlag(const char* type, }; for (const char c : flag) { if (allowedOnce.contains(c)) { - Ensure(!allowedOnce[c], "{} must only contain {} once", type, - allowedOnce | std::views::keys); + rs_ensure(!allowedOnce[c], "{} must only contain {} once", type, + allowedOnce | std::views::keys); allowedOnce[c] = true; continue; } - Ensure(std::isalnum(c) || allowed.contains(c), - "{} must only contain {} or alphanumeric characters", type, allowed); + rs_ensure(std::isalnum(c) || allowed.contains(c), + "{} must only contain {} or alphanumeric characters", type, + allowed); } - return Ok(); + return rs::Ok(); } -static Result> +static rs::Result> validateFlags(const char* type, const std::vector& flags) noexcept { for (const std::string& flag : flags) { - Try(validateFlag(type, flag)); + rs_try(validateFlag(type, flag)); } - return Ok(flags); + return rs::Ok(flags); } struct BaseProfile { @@ -320,11 +324,12 @@ struct BaseProfile { debug(debug), optLevel(optLevel) {} }; -static Result parseBaseProfile(const toml::value& val) noexcept { - auto cxxflags = Try( +static rs::Result +parseBaseProfile(const toml::value& val) noexcept { + auto cxxflags = rs_try( validateFlags("cxxflags", toml::find_or_default>( val, "profile", "cxxflags"))); - auto ldflags = Try( + auto ldflags = rs_try( validateFlags("ldflags", toml::find_or_default>( val, "profile", "ldflags"))); const bool lto = toml::try_find(val, "profile", "lto").unwrap_or(false); @@ -333,51 +338,51 @@ static Result parseBaseProfile(const toml::value& val) noexcept { const mitama::maybe optLevel = toml::try_find(val, "profile", "opt-level").ok(); - return Ok(BaseProfile(std::move(cxxflags), std::move(ldflags), lto, debug, - optLevel)); + return rs::Ok(BaseProfile(std::move(cxxflags), std::move(ldflags), lto, debug, + optLevel)); } -static Result +static rs::Result parseDevProfile(const toml::value& val, const BaseProfile& baseProfile) noexcept { static constexpr const char* key = "dev"; - auto cxxflags = Try(validateFlags( + auto cxxflags = rs_try(validateFlags( "cxxflags", toml::find_or>( val, "profile", key, "cxxflags", baseProfile.cxxflags))); - auto ldflags = Try(validateFlags( + auto ldflags = rs_try(validateFlags( "ldflags", toml::find_or>( val, "profile", key, "ldflags", baseProfile.ldflags))); const auto lto = toml::find_or(val, "profile", key, "lto", baseProfile.lto); const auto debug = toml::find_or(val, "profile", key, "debug", baseProfile.debug.unwrap_or(true)); - const auto optLevel = Try(validateOptLevel(toml::find_or( + const auto optLevel = rs_try(validateOptLevel(toml::find_or( val, "profile", key, "opt-level", baseProfile.optLevel.unwrap_or(0)))); - return Ok( + return rs::Ok( Profile(std::move(cxxflags), std::move(ldflags), lto, debug, optLevel)); } -static Result +static rs::Result parseReleaseProfile(const toml::value& val, const BaseProfile& baseProfile) noexcept { static constexpr const char* key = "release"; - auto cxxflags = Try(validateFlags( + auto cxxflags = rs_try(validateFlags( "cxxflags", toml::find_or>( val, "profile", key, "cxxflags", baseProfile.cxxflags))); - auto ldflags = Try(validateFlags( + auto ldflags = rs_try(validateFlags( "ldflags", toml::find_or>( val, "profile", key, "ldflags", baseProfile.ldflags))); const auto lto = toml::find_or(val, "profile", key, "lto", baseProfile.lto); const auto debug = toml::find_or(val, "profile", key, "debug", baseProfile.debug.unwrap_or(false)); - const auto optLevel = Try(validateOptLevel(toml::find_or( + const auto optLevel = rs_try(validateOptLevel(toml::find_or( val, "profile", key, "opt-level", baseProfile.optLevel.unwrap_or(3)))); - return Ok( + return rs::Ok( Profile(std::move(cxxflags), std::move(ldflags), lto, debug, optLevel)); } @@ -386,13 +391,14 @@ enum class InheritMode : uint8_t { Overwrite, }; -static Result parseInheritMode(std::string_view mode) noexcept { +static rs::Result +parseInheritMode(std::string_view mode) noexcept { if (mode == "append") { - return Ok(InheritMode::Append); + return rs::Ok(InheritMode::Append); } else if (mode == "overwrite") { - return Ok(InheritMode::Overwrite); + return rs::Ok(InheritMode::Overwrite); } else { - Bail("invalid inherit-mode: `{}`", mode); + rs_bail("invalid inherit-mode: `{}`", mode); } } @@ -416,68 +422,69 @@ inheritFlags(const InheritMode inheritMode, } // Inherits from `dev`. -static Result parseTestProfile(const toml::value& val, - const Profile& devProfile) noexcept { +static rs::Result +parseTestProfile(const toml::value& val, const Profile& devProfile) noexcept { static constexpr const char* key = "test"; const InheritMode inheritMode = - Try(parseInheritMode(toml::find_or( + rs_try(parseInheritMode(toml::find_or( val, "profile", key, "inherit-mode", "append"))); std::vector cxxflags = inheritFlags( inheritMode, devProfile.cxxflags, - Try(validateFlags("cxxflags", - toml::find_or_default>( - val, "profile", key, "cxxflags")))); + rs_try(validateFlags("cxxflags", + toml::find_or_default>( + val, "profile", key, "cxxflags")))); std::vector ldflags = inheritFlags( inheritMode, devProfile.ldflags, - Try(validateFlags("ldflags", - toml::find_or_default>( - val, "profile", key, "ldflags")))); + rs_try(validateFlags("ldflags", + toml::find_or_default>( + val, "profile", key, "ldflags")))); const auto lto = toml::find_or(val, "profile", key, "lto", devProfile.lto); const auto debug = toml::find_or(val, "profile", key, "debug", devProfile.debug); - const auto optLevel = Try(validateOptLevel(toml::find_or( + const auto optLevel = rs_try(validateOptLevel(toml::find_or( val, "profile", key, "opt-level", devProfile.optLevel))); - return Ok( + return rs::Ok( Profile(std::move(cxxflags), std::move(ldflags), lto, debug, optLevel)); } -static Result> +static rs::Result> parseProfiles(const toml::value& val) noexcept { std::unordered_map profiles; - const BaseProfile baseProfile = Try(parseBaseProfile(val)); - Profile devProfile = Try(parseDevProfile(val, baseProfile)); - profiles.emplace(BuildProfile::Test, Try(parseTestProfile(val, devProfile))); + const BaseProfile baseProfile = rs_try(parseBaseProfile(val)); + Profile devProfile = rs_try(parseDevProfile(val, baseProfile)); + profiles.emplace(BuildProfile::Test, + rs_try(parseTestProfile(val, devProfile))); profiles.emplace(BuildProfile::Dev, std::move(devProfile)); profiles.emplace(BuildProfile::Release, - Try(parseReleaseProfile(val, baseProfile))); - return Ok(profiles); + rs_try(parseReleaseProfile(val, baseProfile))); + return rs::Ok(profiles); } -Result Cpplint::tryFromToml(const toml::value& val) noexcept { +rs::Result Cpplint::tryFromToml(const toml::value& val) noexcept { auto filters = toml::find_or_default>( val, "lint", "cpplint", "filters"); - return Ok(Cpplint(std::move(filters))); + return rs::Ok(Cpplint(std::move(filters))); } -Result Lint::tryFromToml(const toml::value& val) noexcept { - auto cpplint = Try(Cpplint::tryFromToml(val)); - return Ok(Lint(std::move(cpplint))); +rs::Result Lint::tryFromToml(const toml::value& val) noexcept { + auto cpplint = rs_try(Cpplint::tryFromToml(val)); + return rs::Ok(Lint(std::move(cpplint))); } -static Result validateDepName(const std::string_view name) noexcept { - Ensure(!name.empty(), "dependency name must not be empty"); - Ensure(std::isalnum(name.front()), - "dependency name must start with an alphanumeric character"); - Ensure(std::isalnum(name.back()) || name.back() == '+', - "dependency name must end with an alphanumeric character or `+`"); +static rs::Result validateDepName(const std::string_view name) noexcept { + rs_ensure(!name.empty(), "dependency name must not be empty"); + rs_ensure(std::isalnum(name.front()), + "dependency name must start with an alphanumeric character"); + rs_ensure(std::isalnum(name.back()) || name.back() == '+', + "dependency name must end with an alphanumeric character or `+`"); for (const char c : name) { if (!std::isalnum(c) && !ALLOWED_CHARS.contains(c)) { - Bail("dependency name must be alphanumeric, `-`, `_`, `/`, " - "`.`, or `+`"); + rs_bail("dependency name must be alphanumeric, `-`, `_`, `/`, " + "`.`, or `+`"); } } @@ -488,8 +495,8 @@ static Result validateDepName(const std::string_view name) noexcept { } if (!std::isalnum(name[i]) && name[i] == name[i - 1]) { - Bail("dependency name must not contain consecutive non-alphanumeric " - "characters"); + rs_bail("dependency name must not contain consecutive non-alphanumeric " + "characters"); } } for (std::size_t i = 1; i < name.size() - 1; ++i) { @@ -498,7 +505,7 @@ static Result validateDepName(const std::string_view name) noexcept { } if (!std::isdigit(name[i - 1]) || !std::isdigit(name[i + 1])) { - Bail("dependency name must contain `.` wrapped by digits"); + rs_bail("dependency name must contain `.` wrapped by digits"); } } @@ -507,22 +514,22 @@ static Result validateDepName(const std::string_view name) noexcept { ++charsFreq[c]; } - Ensure(charsFreq['/'] <= 1, - "dependency name must not contain more than one `/`"); - Ensure(charsFreq['+'] == 0 || charsFreq['+'] == 2, - "dependency name must contain zero or two `+`"); + rs_ensure(charsFreq['/'] <= 1, + "dependency name must not contain more than one `/`"); + rs_ensure(charsFreq['+'] == 0 || charsFreq['+'] == 2, + "dependency name must contain zero or two `+`"); if (charsFreq['+'] == 2) { if (name.find('+') + 1 != name.rfind('+')) { - Bail("`+` in the dependency name must be consecutive"); + rs_bail("`+` in the dependency name must be consecutive"); } } - return Ok(); + return rs::Ok(); } -static Result parseGitDep(const std::string& name, - const toml::table& info) noexcept { - Try(validateDepName(name)); +static rs::Result parseGitDep(const std::string& name, + const toml::table& info) noexcept { + rs_try(validateDepName(name)); std::string gitUrlStr; std::optional target = std::nullopt; @@ -541,33 +548,33 @@ static Result parseGitDep(const std::string& name, } } } - return Ok(GitDependency(name, gitUrlStr, std::move(target))); + return rs::Ok(GitDependency(name, gitUrlStr, std::move(target))); } -static Result parsePathDep(const std::string& name, - const toml::table& info) noexcept { - Try(validateDepName(name)); +static rs::Result +parsePathDep(const std::string& name, const toml::table& info) noexcept { + rs_try(validateDepName(name)); const auto& path = info.at("path"); - Ensure(path.is_string(), "path dependency must be a string"); - return Ok(PathDependency(name, path.as_string())); + rs_ensure(path.is_string(), "path dependency must be a string"); + return rs::Ok(PathDependency(name, path.as_string())); } -static Result +static rs::Result parseSystemDep(const std::string& name, const toml::table& info) noexcept { - Try(validateDepName(name)); + rs_try(validateDepName(name)); const auto& version = info.at("version"); - Ensure(version.is_string(), "system dependency version must be a string"); + rs_ensure(version.is_string(), "system dependency version must be a string"); const std::string versionReq = version.as_string(); - return Ok(SystemDependency(name, Try(VersionReq::parse(versionReq)))); + return rs::Ok(SystemDependency(name, rs_try(VersionReq::parse(versionReq)))); } -static Result> +static rs::Result> parseDependencies(const toml::value& val, const char* key) noexcept { const auto tomlDeps = toml::try_find(val, key); if (tomlDeps.is_err()) { spdlog::debug("[{}] not found or not a table", key); - return Ok(std::vector{}); + return rs::Ok(std::vector{}); } std::vector deps; @@ -575,54 +582,55 @@ parseDependencies(const toml::value& val, const char* key) noexcept { if (dep.second.is_table()) { const auto& info = dep.second.as_table(); if (info.contains("git")) { - deps.emplace_back(Try(parseGitDep(dep.first, info))); + deps.emplace_back(rs_try(parseGitDep(dep.first, info))); continue; } else if (info.contains("system") && info.at("system").as_boolean()) { - deps.emplace_back(Try(parseSystemDep(dep.first, info))); + deps.emplace_back(rs_try(parseSystemDep(dep.first, info))); continue; } else if (info.contains("path")) { - deps.emplace_back(Try(parsePathDep(dep.first, info))); + deps.emplace_back(rs_try(parsePathDep(dep.first, info))); continue; } } - Bail("Only Git dependency, path dependency, and system dependency are " - "supported for now: {}", - dep.first); + rs_bail("Only Git dependency, path dependency, and system dependency are " + "supported for now: {}", + dep.first); } - return Ok(deps); + return rs::Ok(deps); } -Result Manifest::tryParse(fs::path path, - const bool findParents) noexcept { +rs::Result Manifest::tryParse(fs::path path, + const bool findParents) noexcept { if (findParents) { - path = Try(findPath(path.parent_path())); + path = rs_try(findPath(path.parent_path())); } return tryFromToml(toml::parse(path), path); } -Result Manifest::tryFromToml(const toml::value& data, - fs::path path) noexcept { - auto package = Try(Package::tryFromToml(data)); +rs::Result Manifest::tryFromToml(const toml::value& data, + fs::path path) noexcept { + auto package = rs_try(Package::tryFromToml(data)); std::vector dependencies = - Try(parseDependencies(data, "dependencies")); + rs_try(parseDependencies(data, "dependencies")); std::vector devDependencies = - Try(parseDependencies(data, "dev-dependencies")); - std::unordered_map profiles = Try(parseProfiles(data)); - auto lint = Try(Lint::tryFromToml(data)); - - return Ok(Manifest(std::move(path), std::move(package), - std::move(dependencies), std::move(devDependencies), - std::move(profiles), std::move(lint))); + rs_try(parseDependencies(data, "dev-dependencies")); + std::unordered_map profiles = + rs_try(parseProfiles(data)); + auto lint = rs_try(Lint::tryFromToml(data)); + + return rs::Ok(Manifest(std::move(path), std::move(package), + std::move(dependencies), std::move(devDependencies), + std::move(profiles), std::move(lint))); } -Result Manifest::findPath(fs::path candidateDir) noexcept { +rs::Result Manifest::findPath(fs::path candidateDir) noexcept { const fs::path origCandDir = candidateDir; while (true) { const fs::path configPath = candidateDir / FILE_NAME; spdlog::trace("Finding manifest: {}", configPath.string()); if (fs::exists(configPath)) { - return Ok(configPath); + return rs::Ok(configPath); } const fs::path parentPath = candidateDir.parent_path(); @@ -634,40 +642,43 @@ Result Manifest::findPath(fs::path candidateDir) noexcept { } } - Bail("{} not find in `{}` and its parents", FILE_NAME, origCandDir.string()); + rs_bail("{} not find in `{}` and its parents", FILE_NAME, + origCandDir.string()); } -Result> +rs::Result> Manifest::installDeps(const bool includeDevDeps) const { std::unordered_map seenDeps; std::unordered_set visited; std::vector installed; - Try(installDependencies(*this, includeDevDeps, seenDeps, visited, installed)); - return Ok(installed); + rs_try( + installDependencies(*this, includeDevDeps, seenDeps, visited, installed)); + return rs::Ok(installed); } // Returns an error message if the package name is invalid. -Result validatePackageName(const std::string_view name) noexcept { - Ensure(!name.empty(), "package name must not be empty"); - Ensure(name.size() > 1, "package name must be more than one character"); +rs::Result validatePackageName(const std::string_view name) noexcept { + rs_ensure(!name.empty(), "package name must not be empty"); + rs_ensure(name.size() > 1, "package name must be more than one character"); for (const char c : name) { if (!std::islower(c) && !std::isdigit(c) && c != '-' && c != '_') { - Bail("package name must only contain lowercase letters, numbers, dashes, " - "and underscores"); + rs_bail( + "package name must only contain lowercase letters, numbers, dashes, " + "and underscores"); } } - Ensure(std::isalpha(name[0]), "package name must start with a letter"); - Ensure(std::isalnum(name[name.size() - 1]), - "package name must end with a letter or digit"); + rs_ensure(std::isalpha(name[0]), "package name must start with a letter"); + rs_ensure(std::isalnum(name[name.size() - 1]), + "package name must end with a letter or digit"); static const std::unordered_set keywords = { #include "Keywords.def" }; - Ensure(!keywords.contains(name), "package name must not be a C++ keyword"); + rs_ensure(!keywords.contains(name), "package name must not be a C++ keyword"); - return Ok(); + return rs::Ok(); } } // namespace cabin @@ -679,8 +690,6 @@ Result validatePackageName(const std::string_view name) noexcept { # include # include -namespace tests { - // NOLINTBEGIN using namespace cabin; using namespace toml::literals::toml_literals; @@ -689,7 +698,8 @@ using namespace toml::literals::toml_literals; inline static void assertEditionEq( const Edition::Year left, const Edition::Year right, const std::source_location& loc = std::source_location::current()) { - assertEq(static_cast(left), static_cast(right), "", loc); + rs::assertEq(static_cast(left), static_cast(right), "", + loc); } inline static void assertEditionEq( const Edition& left, const Edition::Year right, @@ -713,108 +723,109 @@ static void testEditionTryFromString() { // Valid editions assertEditionEq(Edition::tryFromString("2c").unwrap(), Edition::Cpp26); // Invalid editions - assertEq(Edition::tryFromString("").unwrap_err()->what(), "invalid edition"); - assertEq(Edition::tryFromString("abc").unwrap_err()->what(), - "invalid edition"); - assertEq(Edition::tryFromString("99").unwrap_err()->what(), - "invalid edition"); - assertEq(Edition::tryFromString("21").unwrap_err()->what(), - "invalid edition"); - - pass(); + rs::assertEq(Edition::tryFromString("").unwrap_err()->what(), + "invalid edition"); + rs::assertEq(Edition::tryFromString("abc").unwrap_err()->what(), + "invalid edition"); + rs::assertEq(Edition::tryFromString("99").unwrap_err()->what(), + "invalid edition"); + rs::assertEq(Edition::tryFromString("21").unwrap_err()->what(), + "invalid edition"); + + rs::pass(); } static void testEditionComparison() { - assertTrue(Edition::tryFromString("98").unwrap() - <= Edition::tryFromString("03").unwrap()); - assertTrue(Edition::tryFromString("03").unwrap() - <= Edition::tryFromString("11").unwrap()); - assertTrue(Edition::tryFromString("11").unwrap() - <= Edition::tryFromString("14").unwrap()); - assertTrue(Edition::tryFromString("14").unwrap() - <= Edition::tryFromString("17").unwrap()); - assertTrue(Edition::tryFromString("17").unwrap() - <= Edition::tryFromString("20").unwrap()); - assertTrue(Edition::tryFromString("20").unwrap() - <= Edition::tryFromString("23").unwrap()); - assertTrue(Edition::tryFromString("23").unwrap() - <= Edition::tryFromString("2c").unwrap()); - - assertTrue(Edition::tryFromString("98").unwrap() - < Edition::tryFromString("03").unwrap()); - assertTrue(Edition::tryFromString("03").unwrap() - < Edition::tryFromString("11").unwrap()); - assertTrue(Edition::tryFromString("11").unwrap() - < Edition::tryFromString("14").unwrap()); - assertTrue(Edition::tryFromString("14").unwrap() - < Edition::tryFromString("17").unwrap()); - assertTrue(Edition::tryFromString("17").unwrap() - < Edition::tryFromString("20").unwrap()); - assertTrue(Edition::tryFromString("20").unwrap() - < Edition::tryFromString("23").unwrap()); - assertTrue(Edition::tryFromString("23").unwrap() - < Edition::tryFromString("2c").unwrap()); - - assertTrue(Edition::tryFromString("11").unwrap() - == Edition::tryFromString("0x").unwrap()); - assertTrue(Edition::tryFromString("14").unwrap() - == Edition::tryFromString("1y").unwrap()); - assertTrue(Edition::tryFromString("17").unwrap() - == Edition::tryFromString("1z").unwrap()); - assertTrue(Edition::tryFromString("20").unwrap() - == Edition::tryFromString("2a").unwrap()); - assertTrue(Edition::tryFromString("23").unwrap() - == Edition::tryFromString("2b").unwrap()); - - assertTrue(Edition::tryFromString("11").unwrap() - != Edition::tryFromString("03").unwrap()); - assertTrue(Edition::tryFromString("14").unwrap() - != Edition::tryFromString("11").unwrap()); - assertTrue(Edition::tryFromString("17").unwrap() - != Edition::tryFromString("14").unwrap()); - assertTrue(Edition::tryFromString("20").unwrap() - != Edition::tryFromString("17").unwrap()); - assertTrue(Edition::tryFromString("23").unwrap() - != Edition::tryFromString("20").unwrap()); - - assertTrue(Edition::tryFromString("2c").unwrap() - > Edition::tryFromString("23").unwrap()); - assertTrue(Edition::tryFromString("23").unwrap() - > Edition::tryFromString("20").unwrap()); - assertTrue(Edition::tryFromString("20").unwrap() - > Edition::tryFromString("17").unwrap()); - assertTrue(Edition::tryFromString("17").unwrap() - > Edition::tryFromString("14").unwrap()); - assertTrue(Edition::tryFromString("14").unwrap() - > Edition::tryFromString("11").unwrap()); - assertTrue(Edition::tryFromString("11").unwrap() - > Edition::tryFromString("03").unwrap()); - assertTrue(Edition::tryFromString("03").unwrap() - > Edition::tryFromString("98").unwrap()); - - assertTrue(Edition::tryFromString("2c").unwrap() - >= Edition::tryFromString("23").unwrap()); - assertTrue(Edition::tryFromString("23").unwrap() - >= Edition::tryFromString("20").unwrap()); - assertTrue(Edition::tryFromString("20").unwrap() - >= Edition::tryFromString("17").unwrap()); - assertTrue(Edition::tryFromString("17").unwrap() - >= Edition::tryFromString("14").unwrap()); - assertTrue(Edition::tryFromString("14").unwrap() - >= Edition::tryFromString("11").unwrap()); - assertTrue(Edition::tryFromString("11").unwrap() - >= Edition::tryFromString("03").unwrap()); - assertTrue(Edition::tryFromString("03").unwrap() - >= Edition::tryFromString("98").unwrap()); - - assertTrue(Edition::tryFromString("17").unwrap() <= Edition::Cpp17); - assertTrue(Edition::tryFromString("17").unwrap() < Edition::Cpp20); - assertTrue(Edition::tryFromString("20").unwrap() == Edition::Cpp20); - assertTrue(Edition::tryFromString("20").unwrap() != Edition::Cpp23); - assertTrue(Edition::tryFromString("23").unwrap() > Edition::Cpp20); - assertTrue(Edition::tryFromString("20").unwrap() >= Edition::Cpp20); - - pass(); + rs::assertTrue(Edition::tryFromString("98").unwrap() + <= Edition::tryFromString("03").unwrap()); + rs::assertTrue(Edition::tryFromString("03").unwrap() + <= Edition::tryFromString("11").unwrap()); + rs::assertTrue(Edition::tryFromString("11").unwrap() + <= Edition::tryFromString("14").unwrap()); + rs::assertTrue(Edition::tryFromString("14").unwrap() + <= Edition::tryFromString("17").unwrap()); + rs::assertTrue(Edition::tryFromString("17").unwrap() + <= Edition::tryFromString("20").unwrap()); + rs::assertTrue(Edition::tryFromString("20").unwrap() + <= Edition::tryFromString("23").unwrap()); + rs::assertTrue(Edition::tryFromString("23").unwrap() + <= Edition::tryFromString("2c").unwrap()); + + rs::assertTrue(Edition::tryFromString("98").unwrap() + < Edition::tryFromString("03").unwrap()); + rs::assertTrue(Edition::tryFromString("03").unwrap() + < Edition::tryFromString("11").unwrap()); + rs::assertTrue(Edition::tryFromString("11").unwrap() + < Edition::tryFromString("14").unwrap()); + rs::assertTrue(Edition::tryFromString("14").unwrap() + < Edition::tryFromString("17").unwrap()); + rs::assertTrue(Edition::tryFromString("17").unwrap() + < Edition::tryFromString("20").unwrap()); + rs::assertTrue(Edition::tryFromString("20").unwrap() + < Edition::tryFromString("23").unwrap()); + rs::assertTrue(Edition::tryFromString("23").unwrap() + < Edition::tryFromString("2c").unwrap()); + + rs::assertTrue(Edition::tryFromString("11").unwrap() + == Edition::tryFromString("0x").unwrap()); + rs::assertTrue(Edition::tryFromString("14").unwrap() + == Edition::tryFromString("1y").unwrap()); + rs::assertTrue(Edition::tryFromString("17").unwrap() + == Edition::tryFromString("1z").unwrap()); + rs::assertTrue(Edition::tryFromString("20").unwrap() + == Edition::tryFromString("2a").unwrap()); + rs::assertTrue(Edition::tryFromString("23").unwrap() + == Edition::tryFromString("2b").unwrap()); + + rs::assertTrue(Edition::tryFromString("11").unwrap() + != Edition::tryFromString("03").unwrap()); + rs::assertTrue(Edition::tryFromString("14").unwrap() + != Edition::tryFromString("11").unwrap()); + rs::assertTrue(Edition::tryFromString("17").unwrap() + != Edition::tryFromString("14").unwrap()); + rs::assertTrue(Edition::tryFromString("20").unwrap() + != Edition::tryFromString("17").unwrap()); + rs::assertTrue(Edition::tryFromString("23").unwrap() + != Edition::tryFromString("20").unwrap()); + + rs::assertTrue(Edition::tryFromString("2c").unwrap() + > Edition::tryFromString("23").unwrap()); + rs::assertTrue(Edition::tryFromString("23").unwrap() + > Edition::tryFromString("20").unwrap()); + rs::assertTrue(Edition::tryFromString("20").unwrap() + > Edition::tryFromString("17").unwrap()); + rs::assertTrue(Edition::tryFromString("17").unwrap() + > Edition::tryFromString("14").unwrap()); + rs::assertTrue(Edition::tryFromString("14").unwrap() + > Edition::tryFromString("11").unwrap()); + rs::assertTrue(Edition::tryFromString("11").unwrap() + > Edition::tryFromString("03").unwrap()); + rs::assertTrue(Edition::tryFromString("03").unwrap() + > Edition::tryFromString("98").unwrap()); + + rs::assertTrue(Edition::tryFromString("2c").unwrap() + >= Edition::tryFromString("23").unwrap()); + rs::assertTrue(Edition::tryFromString("23").unwrap() + >= Edition::tryFromString("20").unwrap()); + rs::assertTrue(Edition::tryFromString("20").unwrap() + >= Edition::tryFromString("17").unwrap()); + rs::assertTrue(Edition::tryFromString("17").unwrap() + >= Edition::tryFromString("14").unwrap()); + rs::assertTrue(Edition::tryFromString("14").unwrap() + >= Edition::tryFromString("11").unwrap()); + rs::assertTrue(Edition::tryFromString("11").unwrap() + >= Edition::tryFromString("03").unwrap()); + rs::assertTrue(Edition::tryFromString("03").unwrap() + >= Edition::tryFromString("98").unwrap()); + + rs::assertTrue(Edition::tryFromString("17").unwrap() <= Edition::Cpp17); + rs::assertTrue(Edition::tryFromString("17").unwrap() < Edition::Cpp20); + rs::assertTrue(Edition::tryFromString("20").unwrap() == Edition::Cpp20); + rs::assertTrue(Edition::tryFromString("20").unwrap() != Edition::Cpp23); + rs::assertTrue(Edition::tryFromString("23").unwrap() > Edition::Cpp20); + rs::assertTrue(Edition::tryFromString("20").unwrap() >= Edition::Cpp20); + + rs::pass(); } static void testPackageTryFromToml() { @@ -828,9 +839,9 @@ static void testPackageTryFromToml() { )"_toml; auto pkg = Package::tryFromToml(val).unwrap(); - assertEq(pkg.name, "test-pkg"); - assertEq(pkg.edition.str, "20"); - assertEq(pkg.version.toString(), "1.2.3"); + rs::assertEq(pkg.name, "test-pkg"); + rs::assertEq(pkg.edition.str, "20"); + rs::assertEq(pkg.version.toString(), "1.2.3"); } // Missing fields @@ -839,8 +850,8 @@ static void testPackageTryFromToml() { [package] )"_toml; - assertEq(Package::tryFromToml(val).unwrap_err()->what(), - R"(toml::value::at: key "name" not found + rs::assertEq(Package::tryFromToml(val).unwrap_err()->what(), + R"(toml::value::at: key "name" not found --> TOML literal encoded in a C++ code | 2 | [package] @@ -852,8 +863,8 @@ static void testPackageTryFromToml() { name = "test-pkg" )"_toml; - assertEq(Package::tryFromToml(val).unwrap_err()->what(), - R"(toml::value::at: key "edition" not found + rs::assertEq(Package::tryFromToml(val).unwrap_err()->what(), + R"(toml::value::at: key "edition" not found --> TOML literal encoded in a C++ code | 2 | [package] @@ -866,8 +877,8 @@ static void testPackageTryFromToml() { edition = "20" )"_toml; - assertEq(Package::tryFromToml(val).unwrap_err()->what(), - R"(toml::value::at: key "version" not found + rs::assertEq(Package::tryFromToml(val).unwrap_err()->what(), + R"(toml::value::at: key "version" not found --> TOML literal encoded in a C++ code | 2 | [package] @@ -883,7 +894,8 @@ static void testPackageTryFromToml() { version = "1.2.3" )"_toml; - assertEq(Package::tryFromToml(val).unwrap_err()->what(), "invalid edition"); + rs::assertEq(Package::tryFromToml(val).unwrap_err()->what(), + "invalid edition"); } { const toml::value val = R"( @@ -893,13 +905,13 @@ static void testPackageTryFromToml() { version = "invalid" )"_toml; - assertEq(Package::tryFromToml(val).unwrap_err()->what(), - R"(invalid semver: + rs::assertEq(Package::tryFromToml(val).unwrap_err()->what(), + R"(invalid semver: invalid ^^^^^^^ expected number)"); } - pass(); + rs::pass(); } static void testParseProfiles() { @@ -914,19 +926,19 @@ static void testParseProfiles() { const toml::value empty = ""_toml; const auto profiles = parseProfiles(empty).unwrap(); - assertEq(profiles.size(), 3UL); - assertEq(profiles.at(BuildProfile::Dev), devProfileDefault); - assertEq(profiles.at(BuildProfile::Release), relProfileDefault); - assertEq(profiles.at(BuildProfile::Test), devProfileDefault); + rs::assertEq(profiles.size(), 3UL); + rs::assertEq(profiles.at(BuildProfile::Dev), devProfileDefault); + rs::assertEq(profiles.at(BuildProfile::Release), relProfileDefault); + rs::assertEq(profiles.at(BuildProfile::Test), devProfileDefault); } { const toml::value profOnly = "[profile]"_toml; const auto profiles = parseProfiles(profOnly).unwrap(); - assertEq(profiles.size(), 3UL); - assertEq(profiles.at(BuildProfile::Dev), devProfileDefault); - assertEq(profiles.at(BuildProfile::Release), relProfileDefault); - assertEq(profiles.at(BuildProfile::Test), devProfileDefault); + rs::assertEq(profiles.size(), 3UL); + rs::assertEq(profiles.at(BuildProfile::Dev), devProfileDefault); + rs::assertEq(profiles.at(BuildProfile::Release), relProfileDefault); + rs::assertEq(profiles.at(BuildProfile::Test), devProfileDefault); } { const toml::value baseOnly = R"( @@ -944,10 +956,10 @@ static void testParseProfiles() { /*optLevel=*/2); const auto profiles = parseProfiles(baseOnly).unwrap(); - assertEq(profiles.size(), 3UL); - assertEq(profiles.at(BuildProfile::Dev), expected); - assertEq(profiles.at(BuildProfile::Release), expected); - assertEq(profiles.at(BuildProfile::Test), expected); + rs::assertEq(profiles.size(), 3UL); + rs::assertEq(profiles.at(BuildProfile::Dev), expected); + rs::assertEq(profiles.at(BuildProfile::Release), expected); + rs::assertEq(profiles.at(BuildProfile::Test), expected); } { const toml::value overwrite = R"( @@ -962,10 +974,10 @@ static void testParseProfiles() { )"_toml; const auto profiles = parseProfiles(overwrite).unwrap(); - assertEq(profiles.size(), 3UL); - assertEq(profiles.at(BuildProfile::Dev), devProfileDefault); - assertEq(profiles.at(BuildProfile::Release), relProfileDefault); - assertEq(profiles.at(BuildProfile::Test), devProfileDefault); + rs::assertEq(profiles.size(), 3UL); + rs::assertEq(profiles.at(BuildProfile::Dev), devProfileDefault); + rs::assertEq(profiles.at(BuildProfile::Release), relProfileDefault); + rs::assertEq(profiles.at(BuildProfile::Test), devProfileDefault); } { const toml::value overwrite = R"( @@ -994,10 +1006,10 @@ static void testParseProfiles() { /*optLevel=*/3); const auto profiles = parseProfiles(overwrite).unwrap(); - assertEq(profiles.size(), 3UL); - assertEq(profiles.at(BuildProfile::Dev), devExpected); - assertEq(profiles.at(BuildProfile::Release), relExpected); - assertEq(profiles.at(BuildProfile::Test), testExpected); + rs::assertEq(profiles.size(), 3UL); + rs::assertEq(profiles.at(BuildProfile::Dev), devExpected); + rs::assertEq(profiles.at(BuildProfile::Release), relExpected); + rs::assertEq(profiles.at(BuildProfile::Test), testExpected); } { const toml::value append = R"( @@ -1018,10 +1030,10 @@ static void testParseProfiles() { /*optLevel=*/0); const auto profiles = parseProfiles(append).unwrap(); - assertEq(profiles.size(), 3UL); - assertEq(profiles.at(BuildProfile::Dev), devExpected); - assertEq(profiles.at(BuildProfile::Release), relProfileDefault); - assertEq(profiles.at(BuildProfile::Test), testExpected); + rs::assertEq(profiles.size(), 3UL); + rs::assertEq(profiles.at(BuildProfile::Dev), devExpected); + rs::assertEq(profiles.at(BuildProfile::Release), relProfileDefault); + rs::assertEq(profiles.at(BuildProfile::Test), testExpected); } { const toml::value overwrite = R"( @@ -1043,10 +1055,10 @@ static void testParseProfiles() { /*optLevel=*/0); const auto profiles = parseProfiles(overwrite).unwrap(); - assertEq(profiles.size(), 3UL); - assertEq(profiles.at(BuildProfile::Dev), devExpected); - assertEq(profiles.at(BuildProfile::Release), relProfileDefault); - assertEq(profiles.at(BuildProfile::Test), testExpected); + rs::assertEq(profiles.size(), 3UL); + rs::assertEq(profiles.at(BuildProfile::Dev), devExpected); + rs::assertEq(profiles.at(BuildProfile::Release), relProfileDefault); + rs::assertEq(profiles.at(BuildProfile::Test), testExpected); } { const toml::value incorrect = R"( @@ -1054,8 +1066,8 @@ static void testParseProfiles() { inherit-mode = "UNKNOWN" )"_toml; - assertEq(parseProfiles(incorrect).unwrap_err()->what(), - "invalid inherit-mode: `UNKNOWN`"); + rs::assertEq(parseProfiles(incorrect).unwrap_err()->what(), + "invalid inherit-mode: `UNKNOWN`"); } } @@ -1071,94 +1083,96 @@ static void testLintTryFromToml() { )"_toml; auto lint = Lint::tryFromToml(val).unwrap(); - assertEq(fmt::format("{}", fmt::join(lint.cpplint.filters, ",")), - fmt::format("{}", fmt::join(std::vector{ "+filter1", - "-filter2" }, - ","))); + rs::assertEq( + fmt::format("{}", fmt::join(lint.cpplint.filters, ",")), + fmt::format( + "{}", fmt::join(std::vector{ "+filter1", "-filter2" }, + ","))); } // Empty lint config { const toml::value val{}; auto lint = Lint::tryFromToml(val).unwrap(); - assertTrue(lint.cpplint.filters.empty()); + rs::assertTrue(lint.cpplint.filters.empty()); } - pass(); + rs::pass(); } static void testValidateDepName() { - assertEq(validateDepName("").unwrap_err()->what(), - "dependency name must not be empty"); - assertEq(validateDepName("-").unwrap_err()->what(), - "dependency name must start with an alphanumeric character"); - assertEq(validateDepName("1-").unwrap_err()->what(), - "dependency name must end with an alphanumeric character or `+`"); + rs::assertEq(validateDepName("").unwrap_err()->what(), + "dependency name must not be empty"); + rs::assertEq(validateDepName("-").unwrap_err()->what(), + "dependency name must start with an alphanumeric character"); + rs::assertEq( + validateDepName("1-").unwrap_err()->what(), + "dependency name must end with an alphanumeric character or `+`"); for (char c = 0; c < CHAR_MAX; ++c) { if (std::isalnum(c) || ALLOWED_CHARS.contains(c)) { continue; } - assertEq( + rs::assertEq( validateDepName("1" + std::string(1, c) + "1").unwrap_err()->what(), "dependency name must be alphanumeric, `-`, `_`, `/`, `.`, or `+`"); } - assertEq(validateDepName("1--1").unwrap_err()->what(), - "dependency name must not contain consecutive non-alphanumeric " - "characters"); - assertTrue(validateDepName("1-1-1").is_ok()); + rs::assertEq(validateDepName("1--1").unwrap_err()->what(), + "dependency name must not contain consecutive non-alphanumeric " + "characters"); + rs::assertTrue(validateDepName("1-1-1").is_ok()); - assertTrue(validateDepName("1.1").is_ok()); - assertTrue(validateDepName("1.1.1").is_ok()); - assertEq(validateDepName("a.a").unwrap_err()->what(), - "dependency name must contain `.` wrapped by digits"); + rs::assertTrue(validateDepName("1.1").is_ok()); + rs::assertTrue(validateDepName("1.1.1").is_ok()); + rs::assertEq(validateDepName("a.a").unwrap_err()->what(), + "dependency name must contain `.` wrapped by digits"); - assertTrue(validateDepName("a/b").is_ok()); - assertEq(validateDepName("a/b/c").unwrap_err()->what(), - "dependency name must not contain more than one `/`"); + rs::assertTrue(validateDepName("a/b").is_ok()); + rs::assertEq(validateDepName("a/b/c").unwrap_err()->what(), + "dependency name must not contain more than one `/`"); - assertEq(validateDepName("a+").unwrap_err()->what(), - "dependency name must contain zero or two `+`"); - assertEq(validateDepName("a+++").unwrap_err()->what(), - "dependency name must contain zero or two `+`"); + rs::assertEq(validateDepName("a+").unwrap_err()->what(), + "dependency name must contain zero or two `+`"); + rs::assertEq(validateDepName("a+++").unwrap_err()->what(), + "dependency name must contain zero or two `+`"); - assertEq(validateDepName("a+b+c").unwrap_err()->what(), - "`+` in the dependency name must be consecutive"); + rs::assertEq(validateDepName("a+b+c").unwrap_err()->what(), + "`+` in the dependency name must be consecutive"); // issue #921 - assertTrue(validateDepName("gtkmm-4.0").is_ok()); - assertTrue(validateDepName("ncurses++").is_ok()); + rs::assertTrue(validateDepName("gtkmm-4.0").is_ok()); + rs::assertTrue(validateDepName("ncurses++").is_ok()); - pass(); + rs::pass(); } static void testValidateFlag() { - assertTrue(validateFlag("cxxflags", "-fsanitize=address,undefined").is_ok()); + rs::assertTrue( + validateFlag("cxxflags", "-fsanitize=address,undefined").is_ok()); // issue #1183 - assertTrue(validateFlag("ldflags", "-framework Metal").is_ok()); - assertEq(validateFlag("ldflags", "-framework Metal").unwrap_err()->what(), - "ldflags must only contain [' '] once"); - assertEq( + rs::assertTrue(validateFlag("ldflags", "-framework Metal").is_ok()); + rs::assertEq( + validateFlag("ldflags", "-framework Metal").unwrap_err()->what(), + "ldflags must only contain [' '] once"); + rs::assertEq( validateFlag("ldflags", "-framework Metal && bash").unwrap_err()->what(), "ldflags must only contain [' '] once"); - pass(); + rs::pass(); } -} // namespace tests - int main() { cabin::setColorMode("never"); - tests::testEditionTryFromString(); - tests::testEditionComparison(); - tests::testPackageTryFromToml(); - tests::testParseProfiles(); - tests::testLintTryFromToml(); - tests::testValidateDepName(); - tests::testValidateFlag(); + testEditionTryFromString(); + testEditionComparison(); + testPackageTryFromToml(); + testParseProfiles(); + testLintTryFromToml(); + testValidateDepName(); + testValidateFlag(); } #endif diff --git a/lib/Semver.cc b/lib/Semver.cc index 9cad2ea07..11faaa0ee 100644 --- a/lib/Semver.cc +++ b/lib/Semver.cc @@ -11,7 +11,7 @@ #include // NOLINTBEGIN(readability-identifier-naming,cppcoreguidelines-macro-usage) -#define SemverBail(...) Bail("invalid semver:\n" __VA_ARGS__) +#define SemverBail(...) rs_bail("invalid semver:\n" __VA_ARGS__) #define SemverParseBail(lexer, tok, msg) \ SemverBail("{}\n{}{}{}", (lexer).s, std::string((lexer).pos, ' '), \ @@ -251,7 +251,7 @@ VersionToken VersionLexer::consumeIdent() noexcept { return { VersionToken::Ident, std::string(s.substr(pos - len, len)) }; } -Result VersionLexer::consumeNum() noexcept { +rs::Result VersionLexer::consumeNum() noexcept { std::size_t len = 0; uint64_t value = 0; while (pos < s.size() && std::isdigit(s[pos])) { @@ -272,11 +272,11 @@ Result VersionLexer::consumeNum() noexcept { step(); ++len; } - return Ok(VersionToken{ VersionToken::Num, value }); + return rs::Ok(VersionToken{ VersionToken::Num, value }); } // Note that 012 is an invalid number but 012d is a valid identifier. -Result VersionLexer::consumeNumOrIdent() noexcept { +rs::Result VersionLexer::consumeNumOrIdent() noexcept { const std::size_t oldPos = pos; // we need two passes bool isIdent = false; while (pos < s.size() && (std::isalnum(s[pos]) || s[pos] == '-')) { @@ -288,148 +288,148 @@ Result VersionLexer::consumeNumOrIdent() noexcept { pos = oldPos; if (isIdent) { - return Ok(consumeIdent()); + return rs::Ok(consumeIdent()); } else { return consumeNum(); } } -Result VersionLexer::next() noexcept { +rs::Result VersionLexer::next() noexcept { if (isEof()) { - return Ok(VersionToken{ VersionToken::Eof }); + return rs::Ok(VersionToken{ VersionToken::Eof }); } const char c = s[pos]; if (std::isalpha(c)) { - return Ok(consumeIdent()); + return rs::Ok(consumeIdent()); } else if (std::isdigit(c)) { return consumeNumOrIdent(); } else if (c == '.') { step(); - return Ok(VersionToken{ VersionToken::Dot }); + return rs::Ok(VersionToken{ VersionToken::Dot }); } else if (c == '-') { step(); - return Ok(VersionToken{ VersionToken::Hyphen }); + return rs::Ok(VersionToken{ VersionToken::Hyphen }); } else if (c == '+') { step(); - return Ok(VersionToken{ VersionToken::Plus }); + return rs::Ok(VersionToken{ VersionToken::Plus }); } else { step(); - return Ok(VersionToken{ VersionToken::Unknown }); + return rs::Ok(VersionToken{ VersionToken::Unknown }); } } -Result VersionLexer::peek() noexcept { +rs::Result VersionLexer::peek() noexcept { const std::size_t oldPos = pos; - const VersionToken tok = Try(next()); + const VersionToken tok = rs_try(next()); pos = oldPos; - return Ok(tok); + return rs::Ok(tok); } -Result VersionParser::parse() noexcept { - if (Try(lexer.peek()).kind == VersionToken::Eof) { +rs::Result VersionParser::parse() noexcept { + if (rs_try(lexer.peek()).kind == VersionToken::Eof) { SemverBail("empty string is not a valid semver"); } Version ver; - ver.major = Try(parseNum()); - Try(parseDot()); - ver.minor = Try(parseNum()); - Try(parseDot()); - ver.patch = Try(parseNum()); + ver.major = rs_try(parseNum()); + rs_try(parseDot()); + ver.minor = rs_try(parseNum()); + rs_try(parseDot()); + ver.patch = rs_try(parseNum()); - if (Try(lexer.peek()).kind == VersionToken::Hyphen) { + if (rs_try(lexer.peek()).kind == VersionToken::Hyphen) { lexer.step(); - ver.pre = Try(parsePre()); + ver.pre = rs_try(parsePre()); } else { ver.pre = Prerelease(); } - if (Try(lexer.peek()).kind == VersionToken::Plus) { + if (rs_try(lexer.peek()).kind == VersionToken::Plus) { lexer.step(); - ver.build = Try(parseBuild()); + ver.build = rs_try(parseBuild()); } else { ver.build = BuildMetadata(); } if (!lexer.isEof()) { - SemverParseBail(lexer, Try(lexer.peek()), + SemverParseBail(lexer, rs_try(lexer.peek()), " unexpected character: `" + std::string(1, lexer.curChar()) + '`'); } - return Ok(ver); + return rs::Ok(ver); } // Even if the token can be parsed as an identifier, try to parse it as a // number. -Result VersionParser::parseNum() noexcept { +rs::Result VersionParser::parseNum() noexcept { if (!std::isdigit(lexer.curChar())) { - SemverParseBail(lexer, Try(lexer.peek()), " expected number"); + SemverParseBail(lexer, rs_try(lexer.peek()), " expected number"); } - return Ok(std::get(Try(lexer.consumeNum()).value)); + return rs::Ok(std::get(rs_try(lexer.consumeNum()).value)); } -Result VersionParser::parseDot() noexcept { - const VersionToken tok = Try(lexer.next()); +rs::Result VersionParser::parseDot() noexcept { + const VersionToken tok = rs_try(lexer.next()); if (tok.kind != VersionToken::Dot) { SemverParseBail(lexer, tok, " expected `.`"); } - return Ok(); + return rs::Ok(); } // pre ::= numOrIdent ("." numOrIdent)* -Result VersionParser::parsePre() noexcept { +rs::Result VersionParser::parsePre() noexcept { std::vector pre; - pre.emplace_back(Try(parseNumOrIdent())); - while (Try(lexer.peek()).kind == VersionToken::Dot) { + pre.emplace_back(rs_try(parseNumOrIdent())); + while (rs_try(lexer.peek()).kind == VersionToken::Dot) { lexer.step(); - pre.emplace_back(Try(parseNumOrIdent())); + pre.emplace_back(rs_try(parseNumOrIdent())); } - return Ok(Prerelease{ pre }); + return rs::Ok(Prerelease{ pre }); } // numOrIdent ::= num | ident -Result VersionParser::parseNumOrIdent() noexcept { - const VersionToken tok = Try(lexer.next()); +rs::Result VersionParser::parseNumOrIdent() noexcept { + const VersionToken tok = rs_try(lexer.next()); if (tok.kind != VersionToken::Num && tok.kind != VersionToken::Ident) { SemverParseBail(lexer, tok, " expected number or identifier"); } - return Ok(tok); + return rs::Ok(tok); } // build ::= ident ("." ident)* -Result VersionParser::parseBuild() noexcept { +rs::Result VersionParser::parseBuild() noexcept { std::vector build; - build.emplace_back(Try(parseIdent())); - while (Try(lexer.peek()).kind == VersionToken::Dot) { + build.emplace_back(rs_try(parseIdent())); + while (rs_try(lexer.peek()).kind == VersionToken::Dot) { lexer.step(); - build.emplace_back(Try(parseIdent())); + build.emplace_back(rs_try(parseIdent())); } - return Ok(BuildMetadata{ build }); + return rs::Ok(BuildMetadata{ build }); } // Even if the token can be parsed as a number, try to parse it as an // identifier. -Result VersionParser::parseIdent() noexcept { +rs::Result VersionParser::parseIdent() noexcept { if (!std::isalnum(lexer.curChar())) { - SemverParseBail(lexer, Try(lexer.peek()), " expected identifier"); + SemverParseBail(lexer, rs_try(lexer.peek()), " expected identifier"); } - return Ok(lexer.consumeIdent()); + return rs::Ok(lexer.consumeIdent()); } -Result Prerelease::parse(const std::string_view str) noexcept { +rs::Result Prerelease::parse(const std::string_view str) noexcept { VersionParser parser(str); return parser.parsePre(); } -Result +rs::Result BuildMetadata::parse(const std::string_view str) noexcept { VersionParser parser(str); return parser.parseBuild(); } -Result Version::parse(const std::string_view str) noexcept { +rs::Result Version::parse(const std::string_view str) noexcept { VersionParser parser(str); return parser.parse(); } @@ -438,229 +438,241 @@ Result Version::parse(const std::string_view str) noexcept { # include -namespace tests { - // Thanks to: // https://github.com/dtolnay/semver/blob/55fa2cadd6ec95be02e5a2a87b24355304e44d40/tests/test_version.rs#L13 static void testParse() { - assertEq(Version::parse("").unwrap_err()->what(), - "invalid semver:\n" - "empty string is not a valid semver"); - assertEq(Version::parse(" ").unwrap_err()->what(), "invalid semver:\n" - " \n" - "^ expected number"); - assertEq(Version::parse("1").unwrap_err()->what(), "invalid semver:\n" - "1\n" - " ^ expected `.`"); - assertEq(Version::parse("1.2").unwrap_err()->what(), "invalid semver:\n" - "1.2\n" - " ^ expected `.`"); - assertEq(Version::parse("1.2.3-").unwrap_err()->what(), - "invalid semver:\n" - "1.2.3-\n" - " ^ expected number or identifier"); - assertEq(Version::parse("00").unwrap_err()->what(), "invalid semver:\n" - "00\n" - "^ invalid leading zero"); - assertEq(Version::parse("0.00.0").unwrap_err()->what(), - "invalid semver:\n" - "0.00.0\n" - " ^ invalid leading zero"); - assertEq(Version::parse("0.0.0.0").unwrap_err()->what(), - "invalid semver:\n" - "0.0.0.0\n" - " ^ unexpected character: `.`"); - assertEq(Version::parse("a.b.c").unwrap_err()->what(), "invalid semver:\n" - "a.b.c\n" - "^ expected number"); - assertEq(Version::parse("1.2.3 abc").unwrap_err()->what(), - "invalid semver:\n" - "1.2.3 abc\n" - " ^ unexpected character: ` `"); - assertEq(Version::parse("1.2.3-01").unwrap_err()->what(), - "invalid semver:\n" - "1.2.3-01\n" - " ^ invalid leading zero"); - assertEq(Version::parse("1.2.3++").unwrap_err()->what(), - "invalid semver:\n" - "1.2.3++\n" - " ^ expected identifier"); - assertEq(Version::parse("07").unwrap_err()->what(), "invalid semver:\n" - "07\n" - "^ invalid leading zero"); - assertEq(Version::parse("111111111111111111111.0.0").unwrap_err()->what(), - "invalid semver:\n" - "111111111111111111111.0.0\n" - "^^^^^^^^^^^^^^^^^^^^ number exceeds UINT64_MAX"); - assertEq(Version::parse("0.99999999999999999999999.0").unwrap_err()->what(), - "invalid semver:\n" - "0.99999999999999999999999.0\n" - " ^^^^^^^^^^^^^^^^^^^ number exceeds UINT64_MAX"); - assertEq(Version::parse("8\0").unwrap_err()->what(), "invalid semver:\n" - "8\n" - " ^ expected `.`"); - - assertEq(Version::parse("1.2.3").unwrap(), // - (Version{ .major = 1, - .minor = 2, - .patch = 3, - .pre = Prerelease(), - .build = BuildMetadata() })); - assertEq(Version::parse("1.2.3-alpha1").unwrap(), - (Version{ .major = 1, - .minor = 2, - .patch = 3, - .pre = Prerelease::parse("alpha1").unwrap(), - .build = BuildMetadata() })); - assertEq(Version::parse("1.2.3+build5").unwrap(), - (Version{ .major = 1, - .minor = 2, - .patch = 3, - .pre = Prerelease(), - .build = BuildMetadata::parse("build5").unwrap() })); - assertEq(Version::parse("1.2.3+5build").unwrap(), - (Version{ .major = 1, - .minor = 2, - .patch = 3, - .pre = Prerelease(), - .build = BuildMetadata::parse("5build").unwrap() })); - assertEq(Version::parse("1.2.3-alpha1+build5").unwrap(), - (Version{ .major = 1, - .minor = 2, - .patch = 3, - .pre = Prerelease::parse("alpha1").unwrap(), - .build = BuildMetadata::parse("build5").unwrap() })); - assertEq( + rs::assertEq(Version::parse("").unwrap_err()->what(), + "invalid semver:\n" + "empty string is not a valid semver"); + rs::assertEq(Version::parse(" ").unwrap_err()->what(), "invalid semver:\n" + " \n" + "^ expected number"); + rs::assertEq(Version::parse("1").unwrap_err()->what(), "invalid semver:\n" + "1\n" + " ^ expected `.`"); + rs::assertEq(Version::parse("1.2").unwrap_err()->what(), "invalid semver:\n" + "1.2\n" + " ^ expected `.`"); + rs::assertEq(Version::parse("1.2.3-").unwrap_err()->what(), + "invalid semver:\n" + "1.2.3-\n" + " ^ expected number or identifier"); + rs::assertEq(Version::parse("00").unwrap_err()->what(), + "invalid semver:\n" + "00\n" + "^ invalid leading zero"); + rs::assertEq(Version::parse("0.00.0").unwrap_err()->what(), + "invalid semver:\n" + "0.00.0\n" + " ^ invalid leading zero"); + rs::assertEq(Version::parse("0.0.0.0").unwrap_err()->what(), + "invalid semver:\n" + "0.0.0.0\n" + " ^ unexpected character: `.`"); + rs::assertEq(Version::parse("a.b.c").unwrap_err()->what(), + "invalid semver:\n" + "a.b.c\n" + "^ expected number"); + rs::assertEq(Version::parse("1.2.3 abc").unwrap_err()->what(), + "invalid semver:\n" + "1.2.3 abc\n" + " ^ unexpected character: ` `"); + rs::assertEq(Version::parse("1.2.3-01").unwrap_err()->what(), + "invalid semver:\n" + "1.2.3-01\n" + " ^ invalid leading zero"); + rs::assertEq(Version::parse("1.2.3++").unwrap_err()->what(), + "invalid semver:\n" + "1.2.3++\n" + " ^ expected identifier"); + rs::assertEq(Version::parse("07").unwrap_err()->what(), + "invalid semver:\n" + "07\n" + "^ invalid leading zero"); + rs::assertEq(Version::parse("111111111111111111111.0.0").unwrap_err()->what(), + "invalid semver:\n" + "111111111111111111111.0.0\n" + "^^^^^^^^^^^^^^^^^^^^ number exceeds UINT64_MAX"); + rs::assertEq( + Version::parse("0.99999999999999999999999.0").unwrap_err()->what(), + "invalid semver:\n" + "0.99999999999999999999999.0\n" + " ^^^^^^^^^^^^^^^^^^^ number exceeds UINT64_MAX"); + rs::assertEq(Version::parse("8\0").unwrap_err()->what(), "invalid semver:\n" + "8\n" + " ^ expected `.`"); + + rs::assertEq(Version::parse("1.2.3").unwrap(), // + (Version{ .major = 1, + .minor = 2, + .patch = 3, + .pre = Prerelease(), + .build = BuildMetadata() })); + rs::assertEq(Version::parse("1.2.3-alpha1").unwrap(), + (Version{ .major = 1, + .minor = 2, + .patch = 3, + .pre = Prerelease::parse("alpha1").unwrap(), + .build = BuildMetadata() })); + rs::assertEq(Version::parse("1.2.3+build5").unwrap(), + (Version{ .major = 1, + .minor = 2, + .patch = 3, + .pre = Prerelease(), + .build = BuildMetadata::parse("build5").unwrap() })); + rs::assertEq(Version::parse("1.2.3+5build").unwrap(), + (Version{ .major = 1, + .minor = 2, + .patch = 3, + .pre = Prerelease(), + .build = BuildMetadata::parse("5build").unwrap() })); + rs::assertEq(Version::parse("1.2.3-alpha1+build5").unwrap(), + (Version{ .major = 1, + .minor = 2, + .patch = 3, + .pre = Prerelease::parse("alpha1").unwrap(), + .build = BuildMetadata::parse("build5").unwrap() })); + rs::assertEq( Version::parse("1.2.3-1.alpha1.9+build5.7.3aedf").unwrap(), (Version{ .major = 1, .minor = 2, .patch = 3, .pre = Prerelease::parse("1.alpha1.9").unwrap(), .build = BuildMetadata::parse("build5.7.3aedf").unwrap() })); - assertEq( + rs::assertEq( Version::parse("1.2.3-0a.alpha1.9+05build.7.3aedf").unwrap(), (Version{ .major = 1, .minor = 2, .patch = 3, .pre = Prerelease::parse("0a.alpha1.9").unwrap(), .build = BuildMetadata::parse("05build.7.3aedf").unwrap() })); - assertEq(Version::parse("0.4.0-beta.1+0851523").unwrap(), - (Version{ .major = 0, - .minor = 4, - .patch = 0, - .pre = Prerelease::parse("beta.1").unwrap(), - .build = BuildMetadata::parse("0851523").unwrap() })); - assertEq(Version::parse("1.1.0-beta-10").unwrap(), - (Version{ .major = 1, - .minor = 1, - .patch = 0, - .pre = Prerelease::parse("beta-10").unwrap(), - .build = BuildMetadata() })); - - pass(); + rs::assertEq(Version::parse("0.4.0-beta.1+0851523").unwrap(), + (Version{ .major = 0, + .minor = 4, + .patch = 0, + .pre = Prerelease::parse("beta.1").unwrap(), + .build = BuildMetadata::parse("0851523").unwrap() })); + rs::assertEq(Version::parse("1.1.0-beta-10").unwrap(), + (Version{ .major = 1, + .minor = 1, + .patch = 0, + .pre = Prerelease::parse("beta-10").unwrap(), + .build = BuildMetadata() })); + + rs::pass(); } static void testEq() { - assertEq(Version::parse("1.2.3").unwrap(), Version::parse("1.2.3").unwrap()); - assertEq(Version::parse("1.2.3-alpha1").unwrap(), - Version::parse("1.2.3-alpha1").unwrap()); - assertEq(Version::parse("1.2.3+build.42").unwrap(), - Version::parse("1.2.3+build.42").unwrap()); - assertEq(Version::parse("1.2.3-alpha1+42").unwrap(), - Version::parse("1.2.3-alpha1+42").unwrap()); + rs::assertEq(Version::parse("1.2.3").unwrap(), + Version::parse("1.2.3").unwrap()); + rs::assertEq(Version::parse("1.2.3-alpha1").unwrap(), + Version::parse("1.2.3-alpha1").unwrap()); + rs::assertEq(Version::parse("1.2.3+build.42").unwrap(), + Version::parse("1.2.3+build.42").unwrap()); + rs::assertEq(Version::parse("1.2.3-alpha1+42").unwrap(), + Version::parse("1.2.3-alpha1+42").unwrap()); - pass(); + rs::pass(); } static void testNe() { - assertNe(Version::parse("0.0.0").unwrap(), Version::parse("0.0.1").unwrap()); - assertNe(Version::parse("0.0.0").unwrap(), Version::parse("0.1.0").unwrap()); - assertNe(Version::parse("0.0.0").unwrap(), Version::parse("1.0.0").unwrap()); - assertNe(Version::parse("1.2.3-alpha").unwrap(), - Version::parse("1.2.3-beta").unwrap()); - assertNe(Version::parse("1.2.3+23").unwrap(), - Version::parse("1.2.3+42").unwrap()); + rs::assertNe(Version::parse("0.0.0").unwrap(), + Version::parse("0.0.1").unwrap()); + rs::assertNe(Version::parse("0.0.0").unwrap(), + Version::parse("0.1.0").unwrap()); + rs::assertNe(Version::parse("0.0.0").unwrap(), + Version::parse("1.0.0").unwrap()); + rs::assertNe(Version::parse("1.2.3-alpha").unwrap(), + Version::parse("1.2.3-beta").unwrap()); + rs::assertNe(Version::parse("1.2.3+23").unwrap(), + Version::parse("1.2.3+42").unwrap()); - pass(); + rs::pass(); } static void testDisplay() { { std::ostringstream oss; oss << Version::parse("1.2.3").unwrap(); - assertEq(oss.str(), "1.2.3"); + rs::assertEq(oss.str(), "1.2.3"); } { std::ostringstream oss; oss << Version::parse("1.2.3-alpha1").unwrap(); - assertEq(oss.str(), "1.2.3-alpha1"); + rs::assertEq(oss.str(), "1.2.3-alpha1"); } { std::ostringstream oss; oss << Version::parse("1.2.3+build.42").unwrap(); - assertEq(oss.str(), "1.2.3+build.42"); + rs::assertEq(oss.str(), "1.2.3+build.42"); } { std::ostringstream oss; oss << Version::parse("1.2.3-alpha1+42").unwrap(); - assertEq(oss.str(), "1.2.3-alpha1+42"); + rs::assertEq(oss.str(), "1.2.3-alpha1+42"); } - pass(); + rs::pass(); } static void testLt() { - assertLt(Version::parse("0.0.0").unwrap(), - Version::parse("1.2.3-alpha2").unwrap()); - assertLt(Version::parse("1.0.0").unwrap(), - Version::parse("1.2.3-alpha2").unwrap()); - assertLt(Version::parse("1.2.0").unwrap(), - Version::parse("1.2.3-alpha2").unwrap()); - assertLt(Version::parse("1.2.3-alpha1").unwrap(), - Version::parse("1.2.3").unwrap()); - assertLt(Version::parse("1.2.3-alpha1").unwrap(), - Version::parse("1.2.3-alpha2").unwrap()); - assertFalse(Version::parse("1.2.3-alpha2").unwrap() - < Version::parse("1.2.3-alpha2").unwrap()); - assertLt(Version::parse("1.2.3+23").unwrap(), - Version::parse("1.2.3+42").unwrap()); - - pass(); + rs::assertLt(Version::parse("0.0.0").unwrap(), + Version::parse("1.2.3-alpha2").unwrap()); + rs::assertLt(Version::parse("1.0.0").unwrap(), + Version::parse("1.2.3-alpha2").unwrap()); + rs::assertLt(Version::parse("1.2.0").unwrap(), + Version::parse("1.2.3-alpha2").unwrap()); + rs::assertLt(Version::parse("1.2.3-alpha1").unwrap(), + Version::parse("1.2.3").unwrap()); + rs::assertLt(Version::parse("1.2.3-alpha1").unwrap(), + Version::parse("1.2.3-alpha2").unwrap()); + rs::assertFalse(Version::parse("1.2.3-alpha2").unwrap() + < Version::parse("1.2.3-alpha2").unwrap()); + rs::assertLt(Version::parse("1.2.3+23").unwrap(), + Version::parse("1.2.3+42").unwrap()); + + rs::pass(); } static void testLe() { - assertTrue(Version::parse("0.0.0") <= Version::parse("1.2.3-alpha2")); - assertTrue(Version::parse("1.0.0") <= Version::parse("1.2.3-alpha2")); - assertTrue(Version::parse("1.2.0") <= Version::parse("1.2.3-alpha2")); - assertTrue(Version::parse("1.2.3-alpha1") <= Version::parse("1.2.3-alpha2")); - assertTrue(Version::parse("1.2.3-alpha2") <= Version::parse("1.2.3-alpha2")); - assertTrue(Version::parse("1.2.3+23") <= Version::parse("1.2.3+42")); + rs::assertTrue(Version::parse("0.0.0") <= Version::parse("1.2.3-alpha2")); + rs::assertTrue(Version::parse("1.0.0") <= Version::parse("1.2.3-alpha2")); + rs::assertTrue(Version::parse("1.2.0") <= Version::parse("1.2.3-alpha2")); + rs::assertTrue(Version::parse("1.2.3-alpha1") + <= Version::parse("1.2.3-alpha2")); + rs::assertTrue(Version::parse("1.2.3-alpha2") + <= Version::parse("1.2.3-alpha2")); + rs::assertTrue(Version::parse("1.2.3+23") <= Version::parse("1.2.3+42")); - pass(); + rs::pass(); } static void testGt() { - assertTrue(Version::parse("1.2.3-alpha2") > Version::parse("0.0.0")); - assertTrue(Version::parse("1.2.3-alpha2") > Version::parse("1.0.0")); - assertTrue(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0")); - assertTrue(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha1")); - assertTrue(Version::parse("1.2.3") > Version::parse("1.2.3-alpha2")); - assertFalse(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha2")); - assertFalse(Version::parse("1.2.3+23") > Version::parse("1.2.3+42")); + rs::assertTrue(Version::parse("1.2.3-alpha2") > Version::parse("0.0.0")); + rs::assertTrue(Version::parse("1.2.3-alpha2") > Version::parse("1.0.0")); + rs::assertTrue(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0")); + rs::assertTrue(Version::parse("1.2.3-alpha2") + > Version::parse("1.2.3-alpha1")); + rs::assertTrue(Version::parse("1.2.3") > Version::parse("1.2.3-alpha2")); + rs::assertFalse(Version::parse("1.2.3-alpha2") + > Version::parse("1.2.3-alpha2")); + rs::assertFalse(Version::parse("1.2.3+23") > Version::parse("1.2.3+42")); - pass(); + rs::pass(); } static void testGe() { - assertTrue(Version::parse("1.2.3-alpha2") >= Version::parse("0.0.0")); - assertTrue(Version::parse("1.2.3-alpha2") >= Version::parse("1.0.0")); - assertTrue(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.0")); - assertTrue(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha1")); - assertTrue(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha2")); - assertFalse(Version::parse("1.2.3+23") >= Version::parse("1.2.3+42")); + rs::assertTrue(Version::parse("1.2.3-alpha2") >= Version::parse("0.0.0")); + rs::assertTrue(Version::parse("1.2.3-alpha2") >= Version::parse("1.0.0")); + rs::assertTrue(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.0")); + rs::assertTrue(Version::parse("1.2.3-alpha2") + >= Version::parse("1.2.3-alpha1")); + rs::assertTrue(Version::parse("1.2.3-alpha2") + >= Version::parse("1.2.3-alpha2")); + rs::assertFalse(Version::parse("1.2.3+23") >= Version::parse("1.2.3+42")); - pass(); + rs::pass(); } static void testSpecOrder() { @@ -669,25 +681,23 @@ static void testSpecOrder() { "1.0.0-beta.2", "1.0.0-beta.11", "1.0.0-rc.1", "1.0.0", }; for (std::size_t i = 1; i < vers.size(); ++i) { - assertLt(Version::parse(vers[i - 1]).unwrap(), - Version::parse(vers[i]).unwrap()); + rs::assertLt(Version::parse(vers[i - 1]).unwrap(), + Version::parse(vers[i]).unwrap()); } - pass(); + rs::pass(); } -} // namespace tests - int main() { - tests::testParse(); - tests::testEq(); - tests::testNe(); - tests::testDisplay(); - tests::testLt(); - tests::testLe(); - tests::testGt(); - tests::testGe(); - tests::testSpecOrder(); + testParse(); + testEq(); + testNe(); + testDisplay(); + testLt(); + testLe(); + testGt(); + testGe(); + testSpecOrder(); } #endif diff --git a/lib/VersionReq.cc b/lib/VersionReq.cc index a85e2a5f8..00b53ed13 100644 --- a/lib/VersionReq.cc +++ b/lib/VersionReq.cc @@ -11,8 +11,9 @@ #include // NOLINTBEGIN(readability-identifier-naming,cppcoreguidelines-macro-usage) -#define ComparatorBail(...) Bail("invalid comparator:\n" __VA_ARGS__) -#define VersionReqBail(...) Bail("invalid version requirement:\n" __VA_ARGS__) +#define ComparatorBail(...) rs_bail("invalid comparator:\n" __VA_ARGS__) +#define VersionReqBail(...) \ + rs_bail("invalid version requirement:\n" __VA_ARGS__) // NOLINTEND(readability-identifier-naming,cppcoreguidelines-macro-usage) static std::string toString(const Comparator::Op op) noexcept { @@ -71,70 +72,70 @@ struct ComparatorLexer { } } - Result next() noexcept { + rs::Result next() noexcept { if (isEof()) { - return Ok(ComparatorToken{ ComparatorToken::Eof }); + return rs::Ok(ComparatorToken{ ComparatorToken::Eof }); } const char c = s[pos]; if (c == '=') { step(); - return Ok(ComparatorToken{ ComparatorToken::Eq }); + return rs::Ok(ComparatorToken{ ComparatorToken::Eq }); } else if (c == '>') { step(); if (isEof()) { - return Ok(ComparatorToken{ ComparatorToken::Gt }); + return rs::Ok(ComparatorToken{ ComparatorToken::Gt }); } else if (s[pos] == '=') { step(); - return Ok(ComparatorToken{ ComparatorToken::Gte }); + return rs::Ok(ComparatorToken{ ComparatorToken::Gte }); } else { - return Ok(ComparatorToken{ ComparatorToken::Gt }); + return rs::Ok(ComparatorToken{ ComparatorToken::Gt }); } } else if (c == '<') { step(); if (isEof()) { - return Ok(ComparatorToken{ ComparatorToken::Lt }); + return rs::Ok(ComparatorToken{ ComparatorToken::Lt }); } else if (s[pos] == '=') { step(); - return Ok(ComparatorToken{ ComparatorToken::Lte }); + return rs::Ok(ComparatorToken{ ComparatorToken::Lte }); } else { - return Ok(ComparatorToken{ ComparatorToken::Lt }); + return rs::Ok(ComparatorToken{ ComparatorToken::Lt }); } } else if (std::isdigit(c)) { VersionParser parser(s); parser.lexer.pos = pos; OptVersion ver; - ver.major = Try(parser.parseNum()); + ver.major = rs_try(parser.parseNum()); if (parser.lexer.curChar() != '.') { pos = parser.lexer.pos; - return Ok(ComparatorToken{ ComparatorToken::Ver, std::move(ver) }); + return rs::Ok(ComparatorToken{ ComparatorToken::Ver, std::move(ver) }); } - Try(parser.parseDot()); - ver.minor = Try(parser.parseNum()); + rs_try(parser.parseDot()); + ver.minor = rs_try(parser.parseNum()); if (parser.lexer.curChar() != '.') { pos = parser.lexer.pos; - return Ok(ComparatorToken{ ComparatorToken::Ver, std::move(ver) }); + return rs::Ok(ComparatorToken{ ComparatorToken::Ver, std::move(ver) }); } - Try(parser.parseDot()); - ver.patch = Try(parser.parseNum()); + rs_try(parser.parseDot()); + ver.patch = rs_try(parser.parseNum()); if (parser.lexer.curChar() == '-') { parser.lexer.step(); - ver.pre = Try(parser.parsePre()); + ver.pre = rs_try(parser.parsePre()); } if (parser.lexer.curChar() == '+') { parser.lexer.step(); - Try(parser.parseBuild()); // discard build metadata + rs_try(parser.parseBuild()); // discard build metadata } pos = parser.lexer.pos; - return Ok(ComparatorToken{ ComparatorToken::Ver, std::move(ver) }); + return rs::Ok(ComparatorToken{ ComparatorToken::Ver, std::move(ver) }); } else { - return Ok(ComparatorToken{ ComparatorToken::Unknown }); + return rs::Ok(ComparatorToken{ ComparatorToken::Unknown }); } } }; @@ -144,10 +145,10 @@ struct ComparatorParser { explicit ComparatorParser(const std::string_view str) noexcept : lexer(str) {} - Result parse() noexcept { + rs::Result parse() noexcept { Comparator result; - const auto token = Try(lexer.next()); + const auto token = rs_try(lexer.next()); switch (token.kind) { case ComparatorToken::Eq: result.op = Comparator::Exact; @@ -176,7 +177,7 @@ struct ComparatorParser { // version. if (token.kind != ComparatorToken::Ver) { lexer.skipWs(); - const auto token2 = Try(lexer.next()); + const auto token2 = rs_try(lexer.next()); if (token2.kind != ComparatorToken::Ver) { ComparatorBail("{}\n{}^ expected version", lexer.s, std::string(lexer.pos, ' ')); @@ -184,11 +185,11 @@ struct ComparatorParser { result.from(std::get(token2.value)); } - return Ok(result); + return rs::Ok(result); } }; -Result Comparator::parse(const std::string_view str) noexcept { +rs::Result Comparator::parse(const std::string_view str) noexcept { ComparatorParser parser(str); return parser.parse(); } @@ -445,10 +446,10 @@ struct VersionReqLexer { } } - Result next() noexcept { + rs::Result next() noexcept { skipWs(); if (isEof()) { - return Ok(VersionReqToken{ VersionReqToken::Eof }); + return rs::Ok(VersionReqToken{ VersionReqToken::Eof }); } const char c = s[pos]; @@ -456,16 +457,16 @@ struct VersionReqLexer { ComparatorParser parser(s); parser.lexer.pos = pos; - const Comparator comp = Try(parser.parse()); + const Comparator comp = rs_try(parser.parse()); pos = parser.lexer.pos; - return Ok(VersionReqToken{ VersionReqToken::Comp, comp }); + return rs::Ok(VersionReqToken{ VersionReqToken::Comp, comp }); } else if (c == '&' && pos + 1 < s.size() && s[pos + 1] == '&') { pos += 2; - return Ok(VersionReqToken{ VersionReqToken::And }); + return rs::Ok(VersionReqToken{ VersionReqToken::And }); } - return Ok(VersionReqToken{ VersionReqToken::Unknown }); + return rs::Ok(VersionReqToken{ VersionReqToken::Unknown }); } }; @@ -474,10 +475,10 @@ struct VersionReqParser { explicit VersionReqParser(const std::string_view str) noexcept : lexer(str) {} - Result parse() noexcept { + rs::Result parse() noexcept { VersionReq result; - result.left = Try(parseComparatorOrOptVer()); + result.left = rs_try(parseComparatorOrOptVer()); if (!result.left.op.has_value() || result.left.op.value() == Comparator::Exact) { // NoOp or Exact lexer.skipWs(); @@ -485,35 +486,35 @@ struct VersionReqParser { VersionReqBail("{}\n{}^ NoOp and Exact cannot chain", lexer.s, std::string(lexer.pos, ' ')); } - return Ok(result); + return rs::Ok(result); } - const VersionReqToken token = Try(lexer.next()); + const VersionReqToken token = rs_try(lexer.next()); if (token.kind == VersionReqToken::Eof) { - return Ok(result); + return rs::Ok(result); } else if (token.kind != VersionReqToken::And) { VersionReqBail("{}\n{}^ expected `&&`", lexer.s, std::string(lexer.pos, ' ')); } - result.right = Try(parseComparator()); + result.right = rs_try(parseComparator()); lexer.skipWs(); if (!lexer.isEof()) { VersionReqBail("{}\n{}^ expected end of string", lexer.s, std::string(lexer.pos, ' ')); } - return Ok(result); + return rs::Ok(result); } // Parse `("=" | CompOp)? OptVersion` or `Comparator`. - Result parseComparatorOrOptVer() noexcept { - const VersionReqToken token = Try(lexer.next()); + rs::Result parseComparatorOrOptVer() noexcept { + const VersionReqToken token = rs_try(lexer.next()); if (token.kind != VersionReqToken::Comp) { VersionReqBail("{}\n{}^ expected =, >=, <=, >, <, or version", lexer.s, std::string(lexer.pos, ' ')); } - return Ok(std::get(token.value)); + return rs::Ok(std::get(token.value)); } // If the token is a NoOp or Exact comparator, throw an exception. This @@ -522,7 +523,7 @@ struct VersionReqParser { // simplicity. That is, this method literally accepts `Comparator` defined // in the grammar. Otherwise, return the comparator if the token is a // comparator. - Result parseComparator() noexcept { + rs::Result parseComparator() noexcept { const auto compExpected = [&]() noexcept { VersionReqBail("{}\n{}^ expected >=, <=, >, or <", lexer.s, std::string(lexer.pos, ' ')); @@ -541,15 +542,15 @@ struct VersionReqParser { return compExpected(); } - const VersionReqToken token = Try(lexer.next()); + const VersionReqToken token = rs_try(lexer.next()); if (token.kind != VersionReqToken::Comp) { return compExpected(); } - return Ok(std::get(token.value)); + return rs::Ok(std::get(token.value)); } }; -Result VersionReq::parse(const std::string_view str) noexcept { +rs::Result VersionReq::parse(const std::string_view str) noexcept { VersionReqParser parser(str); return parser.parse(); } @@ -851,8 +852,6 @@ std::ostream& operator<<(std::ostream& os, const VersionReq& req) { # include # include -namespace tests { - using std::string_literals::operator""s; // Thanks to: @@ -862,7 +861,7 @@ inline static void assertMatchAll( const VersionReq& req, const std::span versions, const std::source_location& loc = std::source_location::current()) { for (const std::string_view ver : versions) { - assertTrue(req.satisfiedBy(Version::parse(ver).unwrap()), "", loc); + rs::assertTrue(req.satisfiedBy(Version::parse(ver).unwrap()), "", loc); } } @@ -870,69 +869,69 @@ inline static void assertMatchNone( const VersionReq& req, const std::span versions, const std::source_location& loc = std::source_location::current()) { for (const std::string_view ver : versions) { - assertFalse(req.satisfiedBy(Version::parse(ver).unwrap()), "", loc); + rs::assertFalse(req.satisfiedBy(Version::parse(ver).unwrap()), "", loc); } } static void testBasic() { const auto req = VersionReq::parse("1.0.0").unwrap(); - assertEq(req.toString(), "1.0.0"); + rs::assertEq(req.toString(), "1.0.0"); assertMatchAll(req, { { "1.0.0", "1.1.0", "1.0.1" } }); assertMatchNone(req, { { "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre", "1.0.1-pre" } }); - pass(); + rs::pass(); } static void testExact() { const auto ver1 = VersionReq::parse("=1.0.0").unwrap(); - assertEq(ver1.toString(), "=1.0.0"); + rs::assertEq(ver1.toString(), "=1.0.0"); assertMatchAll(ver1, { { "1.0.0" } }); assertMatchNone(ver1, { { "1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre" } }); const auto ver2 = VersionReq::parse("=0.9.0").unwrap(); - assertEq(ver2.toString(), "=0.9.0"); + rs::assertEq(ver2.toString(), "=0.9.0"); assertMatchAll(ver2, { { "0.9.0" } }); assertMatchNone(ver2, { { "0.9.1", "1.9.0", "0.0.9", "0.9.0-pre" } }); const auto ver3 = VersionReq::parse("=0.0.2").unwrap(); - assertEq(ver3.toString(), "=0.0.2"); + rs::assertEq(ver3.toString(), "=0.0.2"); assertMatchAll(ver3, { { "0.0.2" } }); assertMatchNone(ver3, { { "0.0.1", "0.0.3", "0.0.2-pre" } }); const auto ver4 = VersionReq::parse("=0.1.0-beta2.a").unwrap(); - assertEq(ver4.toString(), "=0.1.0-beta2.a"); + rs::assertEq(ver4.toString(), "=0.1.0-beta2.a"); assertMatchAll(ver4, { { "0.1.0-beta2.a" } }); assertMatchNone(ver4, { { "0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2" } }); const auto ver5 = VersionReq::parse("=0.1.0+meta").unwrap(); - assertEq(ver5.toString(), "=0.1.0"); + rs::assertEq(ver5.toString(), "=0.1.0"); assertMatchAll(ver5, { { "0.1.0", "0.1.0+meta", "0.1.0+any" } }); - pass(); + rs::pass(); } static void testGreaterThan() { const auto ver1 = VersionReq::parse(">=1.0.0").unwrap(); - assertEq(ver1.toString(), ">=1.0.0"); + rs::assertEq(ver1.toString(), ">=1.0.0"); assertMatchAll(ver1, { { "1.0.0", "2.0.0" } }); assertMatchNone(ver1, { { "0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre" } }); const auto ver2 = VersionReq::parse(">=2.1.0-alpha2").unwrap(); - assertEq(ver2.toString(), ">=2.1.0-alpha2"); + rs::assertEq(ver2.toString(), ">=2.1.0-alpha2"); assertMatchAll(ver2, { { "2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0" } }); assertMatchNone( ver2, { { "2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2" } }); - pass(); + rs::pass(); } static void testLessThan() { const auto ver1 = VersionReq::parse("<1.0.0").unwrap(); - assertEq(ver1.toString(), "<1.0.0"); + rs::assertEq(ver1.toString(), "<1.0.0"); assertMatchAll(ver1, { { "0.1.0", "0.0.1" } }); assertMatchNone(ver1, { { "1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha" } }); @@ -951,7 +950,7 @@ static void testLessThan() { const auto ver5 = VersionReq::parse(">1.0.0-alpha && <1").unwrap(); assertMatchNone(ver5, { { "1.0.0-beta" } }); - pass(); + rs::pass(); } // same as caret @@ -999,396 +998,397 @@ static void testNoOp() { assertMatchNone(ver9, { { "0.9.9", "2.0.0", "1.4.2-alpha", "1.4.2-beta.4", "1.4.3-beta.5" } }); - pass(); + rs::pass(); } static void testMultiple() { const auto ver1 = VersionReq::parse(">0.0.9 && <=2.5.3").unwrap(); - assertEq(ver1.toString(), ">0.0.9 && <=2.5.3"); + rs::assertEq(ver1.toString(), ">0.0.9 && <=2.5.3"); assertMatchAll(ver1, { { "0.0.10", "1.0.0", "2.5.3" } }); assertMatchNone(ver1, { { "0.0.8", "2.5.4" } }); const auto ver2 = VersionReq::parse("<=0.2.0 && >=0.5.0").unwrap(); - assertEq(ver2.toString(), "<=0.2.0 && >=0.5.0"); + rs::assertEq(ver2.toString(), "<=0.2.0 && >=0.5.0"); assertMatchNone(ver2, { { "0.0.8", "0.3.0", "0.5.1" } }); const auto ver3 = VersionReq::parse(">=0.5.1-alpha3 && <0.6").unwrap(); - assertEq(ver3.toString(), ">=0.5.1-alpha3 && <0.6"); + rs::assertEq(ver3.toString(), ">=0.5.1-alpha3 && <0.6"); assertMatchAll(ver3, { { "0.5.1-alpha3", "0.5.1-alpha4", "0.5.1-beta", "0.5.1", "0.5.5" } }); assertMatchNone(ver3, { { "0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre", "0.6.0", "0.6.0-pre" } }); - assertEq(VersionReq::parse(">0.3.0 && &&").unwrap_err()->what(), - "invalid version requirement:\n" - ">0.3.0 && &&\n" - " ^ expected >=, <=, >, or <"); + rs::assertEq(VersionReq::parse(">0.3.0 && &&").unwrap_err()->what(), + "invalid version requirement:\n" + ">0.3.0 && &&\n" + " ^ expected >=, <=, >, or <"); const auto ver4 = VersionReq::parse(">=0.5.1-alpha3 && <0.6").unwrap(); - assertEq(ver4.toString(), ">=0.5.1-alpha3 && <0.6"); + rs::assertEq(ver4.toString(), ">=0.5.1-alpha3 && <0.6"); assertMatchAll(ver4, { { "0.5.1-alpha3", "0.5.1-alpha4", "0.5.1-beta", "0.5.1", "0.5.5" } }); assertMatchNone( ver4, { { "0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre" } }); assertMatchNone(ver4, { { "0.6.0", "0.6.0-pre" } }); - assertEq(VersionReq::parse(">1.2.3 - <2.3.4").unwrap_err()->what(), - "invalid version requirement:\n" - ">1.2.3 - <2.3.4\n" - " ^ expected `&&`"); + rs::assertEq(VersionReq::parse(">1.2.3 - <2.3.4").unwrap_err()->what(), + "invalid version requirement:\n" + ">1.2.3 - <2.3.4\n" + " ^ expected `&&`"); - pass(); + rs::pass(); } static void testPre() { const auto ver = VersionReq::parse("=2.1.1-really.0").unwrap(); assertMatchAll(ver, { { "2.1.1-really.0" } }); - pass(); + rs::pass(); } static void testCanonicalizeNoOp() { // 1.1. `A.B.C` (where A > 0) is equivalent to `>=A.B.C && <(A+1).0.0` - assertEq(VersionReq::parse("1.2.3").unwrap().canonicalize().toString(), - ">=1.2.3 && <2.0.0"); + rs::assertEq(VersionReq::parse("1.2.3").unwrap().canonicalize().toString(), + ">=1.2.3 && <2.0.0"); // 1.2. `A.B` (where A > 0 & B > 0) is equivalent to `^A.B.0` (i.e., 1.1) - assertEq(VersionReq::parse("1.2").unwrap().canonicalize().toString(), - ">=1.2.0 && <2.0.0"); + rs::assertEq(VersionReq::parse("1.2").unwrap().canonicalize().toString(), + ">=1.2.0 && <2.0.0"); // 1.3. `A` is equivalent to `=A` (i.e., 2.3) - assertEq(VersionReq::parse("1").unwrap().canonicalize().toString(), - ">=1.0.0 && <2.0.0"); + rs::assertEq(VersionReq::parse("1").unwrap().canonicalize().toString(), + ">=1.0.0 && <2.0.0"); // 1.4. `0.B.C` (where B > 0) is equivalent to `>=0.B.C && <0.(B+1).0` - assertEq(VersionReq::parse("0.2.3").unwrap().canonicalize().toString(), - ">=0.2.3 && <0.3.0"); + rs::assertEq(VersionReq::parse("0.2.3").unwrap().canonicalize().toString(), + ">=0.2.3 && <0.3.0"); // 1.5. `0.0.C` is equivalent to `=0.0.C` (i.e., 2.1) - assertEq(VersionReq::parse("0.0.3").unwrap().canonicalize().toString(), - "=0.0.3"); + rs::assertEq(VersionReq::parse("0.0.3").unwrap().canonicalize().toString(), + "=0.0.3"); // 1.6. `0.0` is equivalent to `=0.0` (i.e., 2.2) - assertEq(VersionReq::parse("0.0").unwrap().canonicalize().toString(), - ">=0.0.0 && <0.1.0"); + rs::assertEq(VersionReq::parse("0.0").unwrap().canonicalize().toString(), + ">=0.0.0 && <0.1.0"); - pass(); + rs::pass(); } static void testCanonicalizeExact() { // 2.1. `=A.B.C` is exactly the version `A.B.C` - assertEq(VersionReq::parse("=1.2.3").unwrap().canonicalize().toString(), - "=1.2.3"); + rs::assertEq(VersionReq::parse("=1.2.3").unwrap().canonicalize().toString(), + "=1.2.3"); // 2.2. `=A.B` is equivalent to `>=A.B.0 && =1.2.0 && <1.3.0"); + rs::assertEq(VersionReq::parse("=1.2").unwrap().canonicalize().toString(), + ">=1.2.0 && <1.3.0"); // 2.3. `=A` is equivalent to `>=A.0.0 && <(A+1).0.0` - assertEq(VersionReq::parse("=1").unwrap().canonicalize().toString(), - ">=1.0.0 && <2.0.0"); + rs::assertEq(VersionReq::parse("=1").unwrap().canonicalize().toString(), + ">=1.0.0 && <2.0.0"); - pass(); + rs::pass(); } static void testCanonicalizeGt() { // 3.1. `>A.B.C` is equivalent to `>=A.B.(C+1)` - assertEq(VersionReq::parse(">1.2.3").unwrap().canonicalize().toString(), - ">=1.2.4"); + rs::assertEq(VersionReq::parse(">1.2.3").unwrap().canonicalize().toString(), + ">=1.2.4"); // 3.2. `>A.B` is equivalent to `>=A.(B+1).0` - assertEq(VersionReq::parse(">1.2").unwrap().canonicalize().toString(), - ">=1.3.0"); + rs::assertEq(VersionReq::parse(">1.2").unwrap().canonicalize().toString(), + ">=1.3.0"); // 3.3. `>A` is equivalent to `>=(A+1).0.0` - assertEq(VersionReq::parse(">1").unwrap().canonicalize().toString(), - ">=2.0.0"); + rs::assertEq(VersionReq::parse(">1").unwrap().canonicalize().toString(), + ">=2.0.0"); - pass(); + rs::pass(); } static void testCanonicalizeGte() { // 4.1. `>=A.B.C` - assertEq(VersionReq::parse(">=1.2.3").unwrap().canonicalize().toString(), - ">=1.2.3"); + rs::assertEq(VersionReq::parse(">=1.2.3").unwrap().canonicalize().toString(), + ">=1.2.3"); // 4.2. `>=A.B` is equivalent to `>=A.B.0` - assertEq(VersionReq::parse(">=1.2").unwrap().canonicalize().toString(), - ">=1.2.0"); + rs::assertEq(VersionReq::parse(">=1.2").unwrap().canonicalize().toString(), + ">=1.2.0"); // 4.3. `>=A` is equivalent to `>=A.0.0` - assertEq(VersionReq::parse(">=1").unwrap().canonicalize().toString(), - ">=1.0.0"); + rs::assertEq(VersionReq::parse(">=1").unwrap().canonicalize().toString(), + ">=1.0.0"); - pass(); + rs::pass(); } static void testCanonicalizeLt() { // 5.1. `what(), - "invalid version requirement:\n" - "\n" - "^ expected =, >=, <=, >, <, or version"); - assertEq(VersionReq::parse(">= >= 0.0.2").unwrap_err()->what(), - "invalid comparator:\n" - ">= >= 0.0.2\n" - " ^ expected version"); - assertEq(VersionReq::parse(">== 0.0.2").unwrap_err()->what(), - "invalid comparator:\n" - ">== 0.0.2\n" - " ^ expected version"); - assertEq(VersionReq::parse("a.0.0").unwrap_err()->what(), - "invalid version requirement:\n" - "a.0.0\n" - "^ expected =, >=, <=, >, <, or version"); - assertEq(VersionReq::parse("1.0.0-").unwrap_err()->what(), - "invalid semver:\n" - "1.0.0-\n" - " ^ expected number or identifier"); - assertEq(VersionReq::parse(">=").unwrap_err()->what(), - "invalid comparator:\n" - ">=\n" - " ^ expected version"); - - pass(); + rs::assertEq(VersionReq::parse("\0").unwrap_err()->what(), + "invalid version requirement:\n" + "\n" + "^ expected =, >=, <=, >, <, or version"); + rs::assertEq(VersionReq::parse(">= >= 0.0.2").unwrap_err()->what(), + "invalid comparator:\n" + ">= >= 0.0.2\n" + " ^ expected version"); + rs::assertEq(VersionReq::parse(">== 0.0.2").unwrap_err()->what(), + "invalid comparator:\n" + ">== 0.0.2\n" + " ^ expected version"); + rs::assertEq(VersionReq::parse("a.0.0").unwrap_err()->what(), + "invalid version requirement:\n" + "a.0.0\n" + "^ expected =, >=, <=, >, <, or version"); + rs::assertEq(VersionReq::parse("1.0.0-").unwrap_err()->what(), + "invalid semver:\n" + "1.0.0-\n" + " ^ expected number or identifier"); + rs::assertEq(VersionReq::parse(">=").unwrap_err()->what(), + "invalid comparator:\n" + ">=\n" + " ^ expected version"); + + rs::pass(); } static void testComparatorParse() { - assertEq(Comparator::parse("1.2.3-01").unwrap_err()->what(), - "invalid semver:\n" - "1.2.3-01\n" - " ^ invalid leading zero"); - assertEq(Comparator::parse("1.2.3+4.").unwrap_err()->what(), - "invalid semver:\n" - "1.2.3+4.\n" - " ^ expected identifier"); - assertEq(Comparator::parse(">").unwrap_err()->what(), "invalid comparator:\n" - ">\n" - " ^ expected version"); - assertEq(Comparator::parse("1.").unwrap_err()->what(), "invalid semver:\n" - "1.\n" - " ^ expected number"); - assertEq(Comparator::parse("1.*.").unwrap_err()->what(), - "invalid semver:\n" - "1.*.\n" - " ^ expected number"); - - pass(); + rs::assertEq(Comparator::parse("1.2.3-01").unwrap_err()->what(), + "invalid semver:\n" + "1.2.3-01\n" + " ^ invalid leading zero"); + rs::assertEq(Comparator::parse("1.2.3+4.").unwrap_err()->what(), + "invalid semver:\n" + "1.2.3+4.\n" + " ^ expected identifier"); + rs::assertEq(Comparator::parse(">").unwrap_err()->what(), + "invalid comparator:\n" + ">\n" + " ^ expected version"); + rs::assertEq(Comparator::parse("1.").unwrap_err()->what(), + "invalid semver:\n" + "1.\n" + " ^ expected number"); + rs::assertEq(Comparator::parse("1.*.").unwrap_err()->what(), + "invalid semver:\n" + "1.*.\n" + " ^ expected number"); + + rs::pass(); } static void testLeadingDigitInPreAndBuild() { for (const auto& cmp : { "", "<", "<=", ">", ">=" }) { // digit then alpha - assertTrue(VersionReq::parse(cmp + "1.2.3-1a"s).is_ok()); - assertTrue(VersionReq::parse(cmp + "1.2.3+1a"s).is_ok()); + rs::assertTrue(VersionReq::parse(cmp + "1.2.3-1a"s).is_ok()); + rs::assertTrue(VersionReq::parse(cmp + "1.2.3+1a"s).is_ok()); // digit then alpha (leading zero) - assertTrue(VersionReq::parse(cmp + "1.2.3-01a"s).is_ok()); - assertTrue(VersionReq::parse(cmp + "1.2.3+01"s).is_ok()); + rs::assertTrue(VersionReq::parse(cmp + "1.2.3-01a"s).is_ok()); + rs::assertTrue(VersionReq::parse(cmp + "1.2.3+01"s).is_ok()); // multiple - assertTrue(VersionReq::parse(cmp + "1.2.3-1+1"s).is_ok()); - assertTrue(VersionReq::parse(cmp + "1.2.3-1-1+1-1-1"s).is_ok()); - assertTrue(VersionReq::parse(cmp + "1.2.3-1a+1a"s).is_ok()); - assertTrue(VersionReq::parse(cmp + "1.2.3-1a-1a+1a-1a-1a"s).is_ok()); + rs::assertTrue(VersionReq::parse(cmp + "1.2.3-1+1"s).is_ok()); + rs::assertTrue(VersionReq::parse(cmp + "1.2.3-1-1+1-1-1"s).is_ok()); + rs::assertTrue(VersionReq::parse(cmp + "1.2.3-1a+1a"s).is_ok()); + rs::assertTrue(VersionReq::parse(cmp + "1.2.3-1a-1a+1a-1a-1a"s).is_ok()); } - pass(); + rs::pass(); } static void testValidSpaces() { - assertTrue(VersionReq::parse(" 1.2 ").is_ok()); - assertTrue(VersionReq::parse("> 1.2.3 ").is_ok()); - assertTrue(VersionReq::parse(" <1.2.3 &&>= 1.2.3").is_ok()); - assertTrue(VersionReq::parse(" < 1.2.3 && >= 1.2.3 ").is_ok()); - assertTrue(VersionReq::parse(" <1.2.3 && >1 ").is_ok()); - assertTrue(VersionReq::parse("<1.2.3&& >=1.2.3").is_ok()); - assertTrue(VersionReq::parse("<1.2.3 &&>=1.2.3").is_ok()); - assertTrue(VersionReq::parse("<1.2.3&&>=1.2.3").is_ok()); - - pass(); + rs::assertTrue(VersionReq::parse(" 1.2 ").is_ok()); + rs::assertTrue(VersionReq::parse("> 1.2.3 ").is_ok()); + rs::assertTrue(VersionReq::parse(" <1.2.3 &&>= 1.2.3").is_ok()); + rs::assertTrue(VersionReq::parse(" < 1.2.3 && >= 1.2.3 ").is_ok()); + rs::assertTrue(VersionReq::parse(" <1.2.3 && >1 ").is_ok()); + rs::assertTrue(VersionReq::parse("<1.2.3&& >=1.2.3").is_ok()); + rs::assertTrue(VersionReq::parse("<1.2.3 &&>=1.2.3").is_ok()); + rs::assertTrue(VersionReq::parse("<1.2.3&&>=1.2.3").is_ok()); + + rs::pass(); } static void testInvalidSpaces() { - assertEq(VersionReq::parse(" < = 1.2.3").unwrap_err()->what(), - "invalid comparator:\n" - " < = 1.2.3\n" - " ^ expected version"); - assertEq(VersionReq::parse("<1.2.3 & & >=1.2.3").unwrap_err()->what(), - "invalid version requirement:\n" - "<1.2.3 & & >=1.2.3\n" - " ^ expected `&&`"); - - pass(); + rs::assertEq(VersionReq::parse(" < = 1.2.3").unwrap_err()->what(), + "invalid comparator:\n" + " < = 1.2.3\n" + " ^ expected version"); + rs::assertEq(VersionReq::parse("<1.2.3 & & >=1.2.3").unwrap_err()->what(), + "invalid version requirement:\n" + "<1.2.3 & & >=1.2.3\n" + " ^ expected `&&`"); + + rs::pass(); } static void testInvalidConjunction() { - assertEq(VersionReq::parse("<1.2.3 &&").unwrap_err()->what(), - "invalid version requirement:\n" - "<1.2.3 &&\n" - " ^ expected >=, <=, >, or <"); - assertEq(VersionReq::parse("<1.2.3 <1.2.3").unwrap_err()->what(), - "invalid version requirement:\n" - "<1.2.3 <1.2.3\n" - " ^ expected `&&`"); - assertEq(VersionReq::parse("<1.2.3 && <1.2.3 &&").unwrap_err()->what(), - "invalid version requirement:\n" - "<1.2.3 && <1.2.3 &&\n" - " ^ expected end of string"); - assertEq(VersionReq::parse("<1.2.3 && <1.2.3 && <1.2.3").unwrap_err()->what(), - "invalid version requirement:\n" - "<1.2.3 && <1.2.3 && <1.2.3\n" - " ^ expected end of string"); - - pass(); + rs::assertEq(VersionReq::parse("<1.2.3 &&").unwrap_err()->what(), + "invalid version requirement:\n" + "<1.2.3 &&\n" + " ^ expected >=, <=, >, or <"); + rs::assertEq(VersionReq::parse("<1.2.3 <1.2.3").unwrap_err()->what(), + "invalid version requirement:\n" + "<1.2.3 <1.2.3\n" + " ^ expected `&&`"); + rs::assertEq(VersionReq::parse("<1.2.3 && <1.2.3 &&").unwrap_err()->what(), + "invalid version requirement:\n" + "<1.2.3 && <1.2.3 &&\n" + " ^ expected end of string"); + rs::assertEq( + VersionReq::parse("<1.2.3 && <1.2.3 && <1.2.3").unwrap_err()->what(), + "invalid version requirement:\n" + "<1.2.3 && <1.2.3 && <1.2.3\n" + " ^ expected end of string"); + + rs::pass(); } static void testNonComparatorChain() { - assertEq(VersionReq::parse("1.2.3 && 4.5.6").unwrap_err()->what(), - "invalid version requirement:\n" - "1.2.3 && 4.5.6\n" - " ^ NoOp and Exact cannot chain"); - assertEq(VersionReq::parse("=1.2.3 && =4.5.6").unwrap_err()->what(), - "invalid version requirement:\n" - "=1.2.3 && =4.5.6\n" - " ^ NoOp and Exact cannot chain"); - assertEq(VersionReq::parse("1.2.3 && =4.5.6").unwrap_err()->what(), - "invalid version requirement:\n" - "1.2.3 && =4.5.6\n" - " ^ NoOp and Exact cannot chain"); - assertEq(VersionReq::parse("=1.2.3 && 4.5.6").unwrap_err()->what(), - "invalid version requirement:\n" - "=1.2.3 && 4.5.6\n" - " ^ NoOp and Exact cannot chain"); - assertEq(VersionReq::parse("<1.2.3 && 4.5.6").unwrap_err()->what(), - "invalid version requirement:\n" - "<1.2.3 && 4.5.6\n" - " ^ expected >=, <=, >, or <"); - assertEq(VersionReq::parse("<1.2.3 && =4.5.6").unwrap_err()->what(), - "invalid version requirement:\n" - "<1.2.3 && =4.5.6\n" - " ^ expected >=, <=, >, or <"); - - pass(); + rs::assertEq(VersionReq::parse("1.2.3 && 4.5.6").unwrap_err()->what(), + "invalid version requirement:\n" + "1.2.3 && 4.5.6\n" + " ^ NoOp and Exact cannot chain"); + rs::assertEq(VersionReq::parse("=1.2.3 && =4.5.6").unwrap_err()->what(), + "invalid version requirement:\n" + "=1.2.3 && =4.5.6\n" + " ^ NoOp and Exact cannot chain"); + rs::assertEq(VersionReq::parse("1.2.3 && =4.5.6").unwrap_err()->what(), + "invalid version requirement:\n" + "1.2.3 && =4.5.6\n" + " ^ NoOp and Exact cannot chain"); + rs::assertEq(VersionReq::parse("=1.2.3 && 4.5.6").unwrap_err()->what(), + "invalid version requirement:\n" + "=1.2.3 && 4.5.6\n" + " ^ NoOp and Exact cannot chain"); + rs::assertEq(VersionReq::parse("<1.2.3 && 4.5.6").unwrap_err()->what(), + "invalid version requirement:\n" + "<1.2.3 && 4.5.6\n" + " ^ expected >=, <=, >, or <"); + rs::assertEq(VersionReq::parse("<1.2.3 && =4.5.6").unwrap_err()->what(), + "invalid version requirement:\n" + "<1.2.3 && =4.5.6\n" + " ^ expected >=, <=, >, or <"); + + rs::pass(); } static void testToString() { - assertEq(VersionReq::parse(" <1.2.3 &&>=1.0 ").unwrap().toString(), - "<1.2.3 && >=1.0"); + rs::assertEq(VersionReq::parse(" <1.2.3 &&>=1.0 ").unwrap().toString(), + "<1.2.3 && >=1.0"); - pass(); + rs::pass(); } static void testToPkgConfigString() { - assertEq( + rs::assertEq( VersionReq::parse(" <1.2.3 &&>=1.0 ").unwrap().toPkgConfigString("foo"), "foo < 1.2.3, foo >= 1.0.0"); - assertEq(VersionReq::parse("1.2.3").unwrap().toPkgConfigString("foo"), - "foo >= 1.2.3, foo < 2.0.0"); + rs::assertEq(VersionReq::parse("1.2.3").unwrap().toPkgConfigString("foo"), + "foo >= 1.2.3, foo < 2.0.0"); - assertEq(VersionReq::parse(">1.2.3").unwrap().toPkgConfigString("foo"), - "foo >= 1.2.4"); + rs::assertEq(VersionReq::parse(">1.2.3").unwrap().toPkgConfigString("foo"), + "foo >= 1.2.4"); - assertEq(VersionReq::parse("=1.2.3").unwrap().toPkgConfigString("foo"), - "foo = 1.2.3"); + rs::assertEq(VersionReq::parse("=1.2.3").unwrap().toPkgConfigString("foo"), + "foo = 1.2.3"); - assertEq(VersionReq::parse("=1.2").unwrap().toPkgConfigString("foo"), - "foo >= 1.2.0, foo < 1.3.0"); + rs::assertEq(VersionReq::parse("=1.2").unwrap().toPkgConfigString("foo"), + "foo >= 1.2.0, foo < 1.3.0"); - assertEq(VersionReq::parse("0.0.1").unwrap().toPkgConfigString("foo"), - "foo = 0.0.1"); + rs::assertEq(VersionReq::parse("0.0.1").unwrap().toPkgConfigString("foo"), + "foo = 0.0.1"); - pass(); + rs::pass(); } static void testCanSimplify() { - assertFalse(VersionReq::parse("1.2.3").unwrap().canSimplify()); - assertFalse(VersionReq::parse("=1.2.3").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse("1.2.3").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse("=1.2.3").unwrap().canSimplify()); - assertTrue(VersionReq::parse(">1 && >2").unwrap().canSimplify()); - assertTrue(VersionReq::parse(">1 && >=2").unwrap().canSimplify()); - assertTrue(VersionReq::parse(">=1 && >2").unwrap().canSimplify()); - assertTrue(VersionReq::parse(">=1 && >=2").unwrap().canSimplify()); + rs::assertTrue(VersionReq::parse(">1 && >2").unwrap().canSimplify()); + rs::assertTrue(VersionReq::parse(">1 && >=2").unwrap().canSimplify()); + rs::assertTrue(VersionReq::parse(">=1 && >2").unwrap().canSimplify()); + rs::assertTrue(VersionReq::parse(">=1 && >=2").unwrap().canSimplify()); - assertTrue(VersionReq::parse("<1 && <2").unwrap().canSimplify()); - assertTrue(VersionReq::parse("<1 && <=2").unwrap().canSimplify()); - assertTrue(VersionReq::parse("<=1 && <2").unwrap().canSimplify()); - assertTrue(VersionReq::parse("<=1 && <=2").unwrap().canSimplify()); + rs::assertTrue(VersionReq::parse("<1 && <2").unwrap().canSimplify()); + rs::assertTrue(VersionReq::parse("<1 && <=2").unwrap().canSimplify()); + rs::assertTrue(VersionReq::parse("<=1 && <2").unwrap().canSimplify()); + rs::assertTrue(VersionReq::parse("<=1 && <=2").unwrap().canSimplify()); // TODO: 1 and 1 are the same, but we have to handle 1.0 and 1 as the same. // Currently, there is no way to do this. - assertFalse(VersionReq::parse(">=1 && <=1").unwrap().canSimplify()); - assertFalse(VersionReq::parse(">=1.0 && <=1").unwrap().canSimplify()); - assertFalse(VersionReq::parse(">=1.0.0 && <=1").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse(">=1 && <=1").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse(">=1.0 && <=1").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse(">=1.0.0 && <=1").unwrap().canSimplify()); - assertFalse(VersionReq::parse("<=1 && >=1").unwrap().canSimplify()); - assertFalse(VersionReq::parse("<=1.0 && >=1").unwrap().canSimplify()); - assertFalse(VersionReq::parse("<=1.0.0 && >=1").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse("<=1 && >=1").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse("<=1.0 && >=1").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse("<=1.0.0 && >=1").unwrap().canSimplify()); - assertFalse(VersionReq::parse(">1 && <1").unwrap().canSimplify()); - assertFalse(VersionReq::parse("<1 && >1").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse(">1 && <1").unwrap().canSimplify()); + rs::assertFalse(VersionReq::parse("<1 && >1").unwrap().canSimplify()); - pass(); + rs::pass(); } -} // namespace tests - int main() { - tests::testBasic(); - tests::testExact(); - tests::testGreaterThan(); - tests::testLessThan(); - tests::testNoOp(); - tests::testMultiple(); - tests::testPre(); - tests::testParse(); - tests::testCanonicalizeNoOp(); - tests::testCanonicalizeExact(); - tests::testCanonicalizeGt(); - tests::testCanonicalizeGte(); - tests::testCanonicalizeLt(); - tests::testCanonicalizeLte(); - tests::testComparatorParse(); - tests::testLeadingDigitInPreAndBuild(); - tests::testValidSpaces(); - tests::testInvalidSpaces(); - tests::testInvalidConjunction(); - tests::testNonComparatorChain(); - tests::testToString(); - tests::testToPkgConfigString(); - tests::testCanSimplify(); + testBasic(); + testExact(); + testGreaterThan(); + testLessThan(); + testNoOp(); + testMultiple(); + testPre(); + testParse(); + testCanonicalizeNoOp(); + testCanonicalizeExact(); + testCanonicalizeGt(); + testCanonicalizeGte(); + testCanonicalizeLt(); + testCanonicalizeLte(); + testComparatorParse(); + testLeadingDigitInPreAndBuild(); + testValidSpaces(); + testInvalidSpaces(); + testInvalidConjunction(); + testNonComparatorChain(); + testToString(); + testToPkgConfigString(); + testCanSimplify(); } #endif diff --git a/rs-cpp/include/rs/result.hpp b/rs-cpp/include/rs/result.hpp index 277e2e9a6..8141a758e 100644 --- a/rs-cpp/include/rs/result.hpp +++ b/rs-cpp/include/rs/result.hpp @@ -9,20 +9,23 @@ // NOLINTBEGIN(readability-identifier-naming,cppcoreguidelines-macro-usage) -#define Try(...) MITAMA_TRY(__VA_ARGS__) -#define Bail(...) MITAMA_BAIL(__VA_ARGS__) -#define Ensure(...) MITAMA_ENSURE(__VA_ARGS__) +#define rs_try(...) MITAMA_TRY(__VA_ARGS__) +#define rs_bail(...) MITAMA_BAIL(__VA_ARGS__) +#define rs_ensure(...) MITAMA_ENSURE(__VA_ARGS__) -namespace anyhow = mitama::anyhow; +namespace rs { + +using mitama::anyhow::anyhow; // FIXME: shared_ptr is an implementation detail. Upstream the fix. -using AnyhowErr = mitama::failure_t>; +using AnyhowErr = mitama::failure_t>; struct UseAnyhow {}; template -using Result = std::conditional_t, - anyhow::result, mitama::result>; +using Result = + std::conditional_t, mitama::anyhow::result, + mitama::result>; template inline auto Ok(Args&&... args) @@ -31,19 +34,21 @@ inline auto Ok(Args&&... args) } template - requires std::is_void_v || std::is_base_of_v + requires std::is_void_v || std::is_base_of_v inline auto Err(Args&&... args) { if constexpr (std::is_void_v) { return mitama::failure(std::forward(args)...); } else { - return anyhow::failure(std::forward(args)...); + return mitama::anyhow::failure(std::forward(args)...); } } inline constexpr auto to_anyhow = [](auto... xs) { - return anyhow::anyhow(std::forward(xs)...); + return anyhow(std::forward(xs)...); }; +} // namespace rs + // NOLINTEND(readability-identifier-naming,cppcoreguidelines-macro-usage) #endif // RS_RESULT_HPP diff --git a/rs-cpp/include/rs/tests.hpp b/rs-cpp/include/rs/tests.hpp index c0827aed6..ab6fc497b 100644 --- a/rs-cpp/include/rs/tests.hpp +++ b/rs-cpp/include/rs/tests.hpp @@ -15,7 +15,7 @@ #include #include -namespace tests { +namespace rs { inline constinit const std::string_view GREEN = "\033[32m"; inline constinit const std::string_view RED = "\033[31m"; @@ -58,8 +58,8 @@ constexpr std::string_view prettifyFuncName(std::string_view func) noexcept { return func.substr(start + 1); } -inline void pass(const std::source_location& loc = - std::source_location::current()) { +inline void +pass(const std::source_location& loc = std::source_location::current()) { std::print(" test {}::{} ... {}ok{}\n", getModName(loc.file_name()), prettifyFuncName(loc.function_name()), GREEN, RESET); } @@ -190,6 +190,6 @@ assertLt(Lhs&& lhs, Rhs&& rhs, const std::string_view msg = "", } } -} // namespace tests +} // namespace rs #endif // RS_TESTS_HPP diff --git a/src/Builder/Builder.cc b/src/Builder/Builder.cc index 8daaa674d..127b6ce90 100644 --- a/src/Builder/Builder.cc +++ b/src/Builder/Builder.cc @@ -19,57 +19,57 @@ Builder::Builder(fs::path rootPath, BuildProfile buildProfile) : basePath(std::move(rootPath)), buildProfile(std::move(buildProfile)), depGraph(basePath) {} -Result Builder::schedule(const ScheduleOptions& options) { +rs::Result Builder::schedule(const ScheduleOptions& options) { this->options = options; - Try(depGraph.resolve()); - graphState.emplace(Try(depGraph.computeBuildGraph(buildProfile))); + rs_try(depGraph.resolve()); + graphState.emplace(rs_try(depGraph.computeBuildGraph(buildProfile))); if (options.enableCoverage) { graphState->enableCoverage(); } - Try(graphState->installDeps(options.includeDevDeps)); + rs_try(graphState->installDeps(options.includeDevDeps)); const bool logAnalysis = !options.suppressAnalysisLog; - Try(graphState->plan(logAnalysis)); + rs_try(graphState->plan(logAnalysis)); outDir = graphState->outBasePath(); - return Ok(); + return rs::Ok(); } -Result Builder::ensurePlanned() const { - Ensure(graphState.has_value(), "builder.schedule() must be called first"); - return Ok(); +rs::Result Builder::ensurePlanned() const { + rs_ensure(graphState.has_value(), "builder.schedule() must be called first"); + return rs::Ok(); } -Result Builder::build() { - Try(ensurePlanned()); +rs::Result Builder::build() { + rs_try(ensurePlanned()); const auto startBuild = std::chrono::steady_clock::now(); ExitStatus status(EXIT_SUCCESS); const Manifest& mf = graphState->manifest(); if (graphState->hasLibraryTarget()) { - status = - Try(graphState->buildTargets({ graphState->libraryName() }, - fmt::format("{}(lib)", mf.package.name))); + status = rs_try( + graphState->buildTargets({ graphState->libraryName() }, + fmt::format("{}(lib)", mf.package.name))); } if (status.success() && graphState->hasBinaryTarget()) { status = - Try(graphState->buildTargets({ mf.package.name }, mf.package.name)); + rs_try(graphState->buildTargets({ mf.package.name }, mf.package.name)); } const auto endBuild = std::chrono::steady_clock::now(); const std::chrono::duration buildElapsed = endBuild - startBuild; const Profile& profile = mf.profiles.at(buildProfile); - Ensure(status.success(), "build failed"); + rs_ensure(status.success(), "build failed"); Diag::info("Finished", "`{}` profile [{}] target(s) in {:.2f}s", buildProfile, profile, buildElapsed.count()); - return Ok(); + return rs::Ok(); } -Result Builder::test() { - Try(ensurePlanned()); +rs::Result Builder::test() { + rs_try(ensurePlanned()); const Manifest& mf = graphState->manifest(); const std::vector& targets = @@ -79,10 +79,10 @@ Result Builder::test() { ExitStatus status(EXIT_SUCCESS); if (graphState->hasLibraryTarget()) { - status = - Try(graphState->buildTargets({ graphState->libraryName() }, - fmt::format("{}(lib)", mf.package.name))); - Ensure(status.success(), "build failed"); + status = rs_try( + graphState->buildTargets({ graphState->libraryName() }, + fmt::format("{}(lib)", mf.package.name))); + rs_ensure(status.success(), "build failed"); } if (!targets.empty()) { @@ -91,12 +91,12 @@ Result Builder::test() { for (const auto& target : targets) { names.push_back(target.ninjaTarget); } - status = Try(graphState->buildTargets( + status = rs_try(graphState->buildTargets( names, fmt::format("{}(test)", mf.package.name))); - Ensure(status.success(), "build failed"); + rs_ensure(status.success(), "build failed"); } else { Diag::warn("No test targets found"); - return Ok(); + return rs::Ok(); } const auto buildEnd = std::chrono::steady_clock::now(); @@ -129,7 +129,7 @@ Result Builder::test() { target.sourcePath, testBinPath); const ExitStatus curExitStatus = - Try(execCmd(Command(absoluteBinary.string()))); + rs_try(execCmd(Command(absoluteBinary.string()))); if (curExitStatus.success()) { ++numPassed; } else { @@ -145,25 +145,25 @@ Result Builder::test() { fmt::format("{} passed; {} failed; finished in {:.2f}s", numPassed, numFailed, runElapsed.count()); if (!summaryStatus.success()) { - return Err(anyhow::anyhow(summary)); + return rs::Err(rs::anyhow(summary)); } Diag::info("Ok", "{}", summary); - return Ok(); + return rs::Ok(); } -Result Builder::run(const std::vector& args) { - Try(build()); +rs::Result Builder::run(const std::vector& args) { + rs_try(build()); const Manifest& mf = graphState->manifest(); Diag::info("Running", "`{}/{}`", fs::relative(outDir, mf.path.parent_path()).string(), mf.package.name); const Command command((outDir / mf.package.name).string(), args); - const ExitStatus exitStatus = Try(execCmd(command)); + const ExitStatus exitStatus = rs_try(execCmd(command)); if (exitStatus.success()) { - return Ok(); + return rs::Ok(); } - Bail("run {}", exitStatus); + rs_bail("run {}", exitStatus); } const BuildGraph& Builder::graph() const { diff --git a/src/Builder/Builder.hpp b/src/Builder/Builder.hpp index 1f6b84d37..44a645875 100644 --- a/src/Builder/Builder.hpp +++ b/src/Builder/Builder.hpp @@ -24,10 +24,10 @@ class Builder { public: Builder(fs::path rootPath, BuildProfile buildProfile); - Result schedule(const ScheduleOptions& options = {}); - Result build(); - Result test(); - Result run(const std::vector& args); + rs::Result schedule(const ScheduleOptions& options = {}); + rs::Result build(); + rs::Result test(); + rs::Result run(const std::vector& args); const BuildGraph& graph() const; const fs::path& outDirPath() const { return outDir; } @@ -42,7 +42,7 @@ class Builder { std::optional graphState; fs::path outDir; - Result ensurePlanned() const; + rs::Result ensurePlanned() const; }; } // namespace cabin diff --git a/src/Builder/Project.cc b/src/Builder/Project.cc index eec137f9d..16d88f1db 100644 --- a/src/Builder/Project.cc +++ b/src/Builder/Project.cc @@ -184,15 +184,15 @@ void Project::includeIfExist(const fs::path& path, bool isSystem) { } } -Result Project::init(const BuildProfile& buildProfile, - const fs::path& rootDir) { - Manifest manifest = Try(Manifest::tryParse(rootDir / Manifest::FILE_NAME)); - return Ok(Project(buildProfile, std::move(manifest), CompilerOpts())); +rs::Result Project::init(const BuildProfile& buildProfile, + const fs::path& rootDir) { + Manifest manifest = rs_try(Manifest::tryParse(rootDir / Manifest::FILE_NAME)); + return rs::Ok(Project(buildProfile, std::move(manifest), CompilerOpts())); } -Result Project::init(const BuildProfile& buildProfile, - const Manifest& manifest) { - return Ok(Project(buildProfile, manifest, CompilerOpts())); +rs::Result Project::init(const BuildProfile& buildProfile, + const Manifest& manifest) { + return rs::Ok(Project(buildProfile, manifest, CompilerOpts())); } } // namespace cabin @@ -201,51 +201,47 @@ Result Project::init(const BuildProfile& buildProfile, # include -namespace tests { - using namespace cabin; // NOLINT(build/namespaces,google-build-using-namespace) static void testParseEnvFlags() { std::vector argsNoEscape = parseEnvFlags(" a b c "); // NOLINTNEXTLINE(*-magic-numbers) - assertEq(argsNoEscape.size(), static_cast(3)); - assertEq(argsNoEscape[0], "a"); - assertEq(argsNoEscape[1], "b"); - assertEq(argsNoEscape[2], "c"); + rs::assertEq(argsNoEscape.size(), static_cast(3)); + rs::assertEq(argsNoEscape[0], "a"); + rs::assertEq(argsNoEscape[1], "b"); + rs::assertEq(argsNoEscape[2], "c"); std::vector argsEscapeBackslash = parseEnvFlags(R"( a\ bc cd\$fg hi windows\\path\\here )"); // NOLINTNEXTLINE(*-magic-numbers) - assertEq(argsEscapeBackslash.size(), static_cast(4)); - assertEq(argsEscapeBackslash[0], "a bc"); - assertEq(argsEscapeBackslash[1], "cd$fg"); - assertEq(argsEscapeBackslash[2], "hi"); - assertEq(argsEscapeBackslash[3], R"(windows\path\here)"); + rs::assertEq(argsEscapeBackslash.size(), static_cast(4)); + rs::assertEq(argsEscapeBackslash[0], "a bc"); + rs::assertEq(argsEscapeBackslash[1], "cd$fg"); + rs::assertEq(argsEscapeBackslash[2], "hi"); + rs::assertEq(argsEscapeBackslash[3], R"(windows\path\here)"); std::vector argsEscapeQuotes = parseEnvFlags( " \"-I/path/contains space\" '-Lanother/path with/space' normal "); // NOLINTNEXTLINE(*-magic-numbers) - assertEq(argsEscapeQuotes.size(), static_cast(3)); - assertEq(argsEscapeQuotes[0], "-I/path/contains space"); - assertEq(argsEscapeQuotes[1], "-Lanother/path with/space"); - assertEq(argsEscapeQuotes[2], "normal"); + rs::assertEq(argsEscapeQuotes.size(), static_cast(3)); + rs::assertEq(argsEscapeQuotes[0], "-I/path/contains space"); + rs::assertEq(argsEscapeQuotes[1], "-Lanother/path with/space"); + rs::assertEq(argsEscapeQuotes[2], "normal"); std::vector argsEscapeMixed = parseEnvFlags( R"-( "-IMy \"Headers\"\\v1" '\?pattern' normal path/contain/\"quote\" mixEverything" abc "\?\# )-"); // NOLINTNEXTLINE(*-magic-numbers) - assertEq(argsEscapeMixed.size(), static_cast(5)); - assertEq(argsEscapeMixed[0], R"(-IMy "Headers"\v1)"); - assertEq(argsEscapeMixed[1], "?pattern"); - assertEq(argsEscapeMixed[2], "normal"); - assertEq(argsEscapeMixed[3], "path/contain/\"quote\""); - assertEq(argsEscapeMixed[4], "mixEverything abc ?#"); - - pass(); + rs::assertEq(argsEscapeMixed.size(), static_cast(5)); + rs::assertEq(argsEscapeMixed[0], R"(-IMy "Headers"\v1)"); + rs::assertEq(argsEscapeMixed[1], "?pattern"); + rs::assertEq(argsEscapeMixed[2], "normal"); + rs::assertEq(argsEscapeMixed[3], "path/contain/\"quote\""); + rs::assertEq(argsEscapeMixed[4], "mixEverything abc ?#"); + + rs::pass(); } -} // namespace tests - -int main() { tests::testParseEnvFlags(); } +int main() { testParseEnvFlags(); } #endif diff --git a/src/Builder/Project.hpp b/src/Builder/Project.hpp index d599fe01b..95251c081 100644 --- a/src/Builder/Project.hpp +++ b/src/Builder/Project.hpp @@ -26,11 +26,11 @@ class Project { const Manifest manifest; CompilerOpts compilerOpts; - static Result init(const BuildProfile& buildProfile, - const fs::path& rootDir); + static rs::Result init(const BuildProfile& buildProfile, + const fs::path& rootDir); - static Result init(const BuildProfile& buildProfile, - const Manifest& manifest); + static rs::Result init(const BuildProfile& buildProfile, + const Manifest& manifest); }; } // namespace cabin diff --git a/src/Cli.cc b/src/Cli.cc index 362baef57..6315dd674 100644 --- a/src/Cli.cc +++ b/src/Cli.cc @@ -193,7 +193,7 @@ std::string Subcmd::formatUsage(FILE* file) const noexcept { return str; } -[[nodiscard]] AnyhowErr Subcmd::noSuchArg(std::string_view arg) const { +[[nodiscard]] rs::AnyhowErr Subcmd::noSuchArg(std::string_view arg) const { std::vector candidates; if (globalOpts.has_value()) { addOptCandidates(candidates, globalOpts.value()); @@ -206,17 +206,17 @@ std::string Subcmd::formatUsage(FILE* file) const noexcept { fmt::format("{} did you mean '{}'?\n\n", Bold(Cyan("Tip:")).toErrStr(), Bold(Yellow(similar.value())).toErrStr()); } - return anyhow::anyhow("unexpected argument '{}' found\n\n" - "{}" - "{}\n\n" - "For more information, try '{}'", - Bold(Yellow(arg)).toErrStr(), suggestion, - formatUsage(stderr), Bold(Cyan("--help")).toErrStr()); + return rs::anyhow("unexpected argument '{}' found\n\n" + "{}" + "{}\n\n" + "For more information, try '{}'", + Bold(Yellow(arg)).toErrStr(), suggestion, + formatUsage(stderr), Bold(Cyan("--help")).toErrStr()); } -[[nodiscard]] AnyhowErr +[[nodiscard]] rs::AnyhowErr Subcmd::missingOptArgumentFor(const std::string_view arg) noexcept { - return anyhow::anyhow("Missing argument for `{}`", arg); + return rs::anyhow("Missing argument for `{}`", arg); } std::size_t Subcmd::calcMaxShortSize() const noexcept { @@ -313,7 +313,7 @@ bool Cli::hasSubcmd(std::string_view subcmd) const noexcept { return subcmds.contains(subcmd); } -[[nodiscard]] AnyhowErr Cli::noSuchArg(std::string_view arg) const { +[[nodiscard]] rs::AnyhowErr Cli::noSuchArg(std::string_view arg) const { std::vector candidates; for (const auto& cmd : subcmds) { candidates.push_back(cmd.second.name); @@ -330,19 +330,19 @@ bool Cli::hasSubcmd(std::string_view subcmd) const noexcept { fmt::format("{} did you mean '{}'?\n\n", Bold(Cyan("Tip:")).toErrStr(), Bold(Yellow(similar.value())).toErrStr()); } - return anyhow::anyhow("unexpected argument '{}' found\n\n" - "{}" - "For a list of commands, try '{}'", - Bold(Yellow(arg)).toErrStr(), suggestion, - Bold(Cyan("cabin help")).toErrStr()); + return rs::anyhow("unexpected argument '{}' found\n\n" + "{}" + "For a list of commands, try '{}'", + Bold(Yellow(arg)).toErrStr(), suggestion, + Bold(Cyan("cabin help")).toErrStr()); } -[[nodiscard]] Result Cli::exec(const std::string_view subcmd, - const CliArgsView args) const { +[[nodiscard]] rs::Result Cli::exec(const std::string_view subcmd, + const CliArgsView args) const { return subcmds.at(subcmd).mainFn(args); } -[[nodiscard]] Result +[[nodiscard]] rs::Result Cli::handleGlobalOpts(std::forward_iterator auto& itr, const std::forward_iterator auto end, const std::string& subcmd) { @@ -357,30 +357,30 @@ Cli::handleGlobalOpts(std::forward_iterator auto& itr, } } else if (matchesAny(arg, { "-v", "--verbose" })) { setDiagLevel(DiagLevel::Verbose); - return Ok(Continue); + return rs::Ok(Continue); } else if (arg == "-vv") { setDiagLevel(DiagLevel::VeryVerbose); - return Ok(Continue); + return rs::Ok(Continue); } else if (matchesAny(arg, { "-q", "--quiet" })) { setDiagLevel(DiagLevel::Off); - return Ok(Continue); + return rs::Ok(Continue); } else if (arg == "--color") { - Ensure(itr + 1 < end, "missing argument for `--color`"); + rs_ensure(itr + 1 < end, "missing argument for `--color`"); setColorMode(*++itr); - return Ok(Continue); + return rs::Ok(Continue); } - return Ok(Fallthrough); + return rs::Ok(Fallthrough); } -Result Cli::parseArgs(const int argc, - char* argv[] // NOLINT(*-avoid-c-arrays) +rs::Result Cli::parseArgs(const int argc, + char* argv[] // NOLINT(*-avoid-c-arrays) ) const noexcept { // Drop the first argument (program name) // NOLINTNEXTLINE(*-bounds-pointer-arithmetic) - return parseArgs(Try(expandOpts({ argv + 1, argv + argc }))); + return parseArgs(rs_try(expandOpts({ argv + 1, argv + argc }))); } -Result Cli::parseArgs(const CliArgsView args) const noexcept { +rs::Result Cli::parseArgs(const CliArgsView args) const noexcept { // Parse arguments (options should appear before the subcommand, as the help // message shows intuitively) // cabin --verbose run --release help --color always --verbose @@ -390,9 +390,9 @@ Result Cli::parseArgs(const CliArgsView args) const noexcept { const std::string_view arg = *itr; // Global options - const auto control = Try(Cli::handleGlobalOpts(itr, args.end())); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end())); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } @@ -403,7 +403,7 @@ Result Cli::parseArgs(const CliArgsView args) const noexcept { return exec("version", { itr + 1, args.end() }); } else if (arg == "--list") { fmt::print("{}", formatAllSubcmds(true)); - return Ok(); + return rs::Ok(); } // Subcommands @@ -411,7 +411,7 @@ Result Cli::parseArgs(const CliArgsView args) const noexcept { try { return exec(arg, { itr + 1, args.end() }); } catch (const std::exception& e) { - Bail(e.what()); + rs_bail(e.what()); } } @@ -424,7 +424,7 @@ Result Cli::parseArgs(const CliArgsView args) const noexcept { return printHelp({}); } -Result> +rs::Result> Cli::expandOpts(const std::span args) const noexcept { struct ShortOpts { std::unordered_map names; @@ -478,7 +478,7 @@ Cli::expandOpts(const std::span args) const noexcept { optName = arg.substr(0, eqPos); } - const auto handleLongOpt = [&](const auto opt) -> Result { + const auto handleLongOpt = [&](const auto opt) -> rs::Result { if (opt->takesArg()) { if (eqPos != std::string_view::npos) { if (eqPos + 1 < arg.size()) { @@ -503,17 +503,17 @@ Cli::expandOpts(const std::span args) const noexcept { } else { expanded.emplace_back(arg); } - return Ok(); + return rs::Ok(); }; auto opt = globalOpts.find(Opt{ optName }); if (opt != globalOpts.end()) { - Try(handleLongOpt(opt)); + rs_try(handleLongOpt(opt)); continue; } opt = curLocalOpts.get().find(Opt{ optName }); if (opt != curLocalOpts.get().end()) { - Try(handleLongOpt(opt)); + rs_try(handleLongOpt(opt)); continue; } // Unknown option is found. @@ -534,7 +534,7 @@ Cli::expandOpts(const std::span args) const noexcept { // Start from the longest option name. const std::string optName = fmt::format("-{}", arg.substr(left, right - left + 1)); - const auto handleShortOpt = [&](const Opt& opt) -> Result { + const auto handleShortOpt = [&](const Opt& opt) -> rs::Result { if (opt.takesArg()) { if (right + 1 < arg.size()) { // Handle "-j1" case. @@ -555,18 +555,18 @@ Cli::expandOpts(const std::span args) const noexcept { expanded.emplace_back(optName); left = right; } - return Ok(); + return rs::Ok(); }; auto opt = globalShortOpts.names.find(optName); if (opt != globalShortOpts.names.end()) { - Try(handleShortOpt(opt->second)); + rs_try(handleShortOpt(opt->second)); handled = true; break; } opt = curLocalShortOpts.names.find(optName); if (opt != curLocalShortOpts.names.end()) { - Try(handleShortOpt(opt->second)); + rs_try(handleShortOpt(opt->second)); handled = true; break; } @@ -581,7 +581,7 @@ Cli::expandOpts(const std::span args) const noexcept { // Unknown arguments are added as is. expanded.emplace_back(arg); } - return Ok(expanded); + return rs::Ok(expanded); } void Cli::printSubcmdHelp(const std::string_view subcmd) const noexcept { @@ -677,20 +677,20 @@ std::string Cli::formatCmdHelp() const noexcept { return str; } -[[nodiscard]] Result +[[nodiscard]] rs::Result Cli::printHelp(const CliArgsView args) const noexcept { // Parse args for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(handleGlobalOpts(itr, args.end(), "help")); + const auto control = rs_try(handleGlobalOpts(itr, args.end(), "help")); if (control == Return) { - return Ok(); + return rs::Ok(); } else if (control == Continue) { continue; } else if (hasSubcmd(arg)) { printSubcmdHelp(arg); - return Ok(); + return rs::Ok(); } else { // TODO: Currently assumes that `help` does not implement any additional // options since we are using `noSuchArg` instead of @@ -702,7 +702,7 @@ Cli::printHelp(const CliArgsView args) const noexcept { // Print help message for cabin itself fmt::print("{}", formatCmdHelp()); - return Ok(); + return rs::Ok(); } } // namespace cabin @@ -727,30 +727,28 @@ const Cli& getCli() noexcept { } // namespace cabin -namespace tests { - using namespace cabin; // NOLINT(build/namespaces,google-build-using-namespace) static void testCliExpandOpts() { { const std::vector args{ "-vvvj4" }; const std::vector expected{ "-vv", "-v", "-j", "4" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { const std::vector args{ "-j4vvv" }; const std::vector expected{ "-j", "4vvv" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { const std::vector args{ "-vj" }; - assertEq(getCli().expandOpts(args).unwrap_err()->what(), - "Missing argument for `-j`"); + rs::assertEq(getCli().expandOpts(args).unwrap_err()->what(), + "Missing argument for `-j`"); } { const std::vector args{ "-j" }; - assertEq(getCli().expandOpts(args).unwrap_err()->what(), - "Missing argument for `-j`"); + rs::assertEq(getCli().expandOpts(args).unwrap_err()->what(), + "Missing argument for `-j`"); } { const std::vector args{ "r", "-j" }; @@ -758,81 +756,79 @@ static void testCliExpandOpts() { // responsibility to check it. // 2. "-j" sounds to take an argument, but not taking an argument is okay. const std::vector expected{ "r", "-j" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { // Passing "run" to the program? const std::vector args{ "run", "run" }; const std::vector expected{ "run", "run" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { // "subcmd" is not a subcommand, but possibly passing it to the program. const std::vector args{ "run", "subcmd" }; const std::vector expected{ "run", "subcmd" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { const std::vector args{ "build", "-t" }; - assertEq(getCli().expandOpts(args).unwrap_err()->what(), - "Missing argument for `-t`"); + rs::assertEq(getCli().expandOpts(args).unwrap_err()->what(), + "Missing argument for `-t`"); } { const std::vector args{ "build", "--target=this" }; const std::vector expected{ "build", "--target", "this" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { const std::vector args{ "build", "--target=", "this" }; const std::vector expected{ "build", "--target=", "this" }; - assertEq(getCli().expandOpts(args).unwrap_err()->what(), - "Missing argument for `--target`"); + rs::assertEq(getCli().expandOpts(args).unwrap_err()->what(), + "Missing argument for `--target`"); } { const std::vector args{ "build", "--target", "this" }; const std::vector expected{ "build", "--target", "this" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { const std::vector args{ "-vv", "build", "--target", "this" }; const std::vector expected{ "-vv", "build", "--target", "this" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { // "subcmd" is not a subcommand, but possibly "build"'s argument. const std::vector args{ "build", "subcmd" }; const std::vector expected{ "build", "subcmd" }; - assertEq(getCli().expandOpts(args).unwrap(), expected); + rs::assertEq(getCli().expandOpts(args).unwrap(), expected); } { // "subcmd" is not a subcommand. const std::vector args{ "subcmd", "build" }; - assertEq(getCli().expandOpts(args).unwrap_err()->what(), - R"(unexpected argument 'subcmd' found + rs::assertEq(getCli().expandOpts(args).unwrap_err()->what(), + R"(unexpected argument 'subcmd' found For a list of commands, try 'cabin help')"); } { // "built" is not a subcommand, but typo of "build"? const std::vector args{ "built" }; - assertEq(getCli().expandOpts(args).unwrap_err()->what(), - R"(unexpected argument 'built' found + rs::assertEq(getCli().expandOpts(args).unwrap_err()->what(), + R"(unexpected argument 'built' found Tip: did you mean 'build'? For a list of commands, try 'cabin help')"); } - pass(); + rs::pass(); } -} // namespace tests - int main() { cabin::setColorMode("never"); - tests::testCliExpandOpts(); + testCliExpandOpts(); } #endif diff --git a/src/Cli.hpp b/src/Cli.hpp index ea32d965d..e50035ad6 100644 --- a/src/Cli.hpp +++ b/src/Cli.hpp @@ -176,7 +176,7 @@ class Arg : public CliBase { class Subcmd : public CliBase, public ShortAndHidden { friend class Cli; - using MainFn = Result(CliArgsView); + using MainFn = rs::Result(CliArgsView); std::string_view cmdName; std::optional globalOpts = std::nullopt; @@ -194,8 +194,8 @@ class Subcmd : public CliBase, public ShortAndHidden { Subcmd& addOpt(Opt opt) noexcept; Subcmd& setMainFn(std::function mainFn) noexcept; - [[nodiscard]] AnyhowErr noSuchArg(std::string_view arg) const; - [[nodiscard]] static AnyhowErr + [[nodiscard]] rs::AnyhowErr noSuchArg(std::string_view arg) const; + [[nodiscard]] static rs::AnyhowErr missingOptArgumentFor(std::string_view arg) noexcept; private: @@ -227,11 +227,11 @@ class Cli : public CliBase { Cli& addOpt(Opt opt) noexcept; bool hasSubcmd(std::string_view subcmd) const noexcept; - [[nodiscard]] AnyhowErr noSuchArg(std::string_view arg) const; - [[nodiscard]] Result exec(std::string_view subcmd, - CliArgsView args) const; + [[nodiscard]] rs::AnyhowErr noSuchArg(std::string_view arg) const; + [[nodiscard]] rs::Result exec(std::string_view subcmd, + CliArgsView args) const; void printSubcmdHelp(std::string_view subcmd) const noexcept; - [[nodiscard]] Result printHelp(CliArgsView args) const noexcept; + [[nodiscard]] rs::Result printHelp(CliArgsView args) const noexcept; std::size_t calcMaxOffset(std::size_t maxShortSize) const noexcept; std::string formatAllSubcmds(bool showHidden, std::size_t maxOffset = 0) const noexcept; @@ -243,20 +243,20 @@ class Cli : public CliBase { }; using enum ControlFlow; - [[nodiscard]] static Result + [[nodiscard]] static rs::Result handleGlobalOpts(std::forward_iterator auto& itr, std::forward_iterator auto end, const std::string& subcmd = ""); // NOLINTNEXTLINE(*-avoid-c-arrays) - Result parseArgs(int argc, char* argv[]) const noexcept; + rs::Result parseArgs(int argc, char* argv[]) const noexcept; // NOTE: This is public only for tests - Result> + rs::Result> expandOpts(std::span args) const noexcept; private: - Result parseArgs(CliArgsView args) const noexcept; + rs::Result parseArgs(CliArgsView args) const noexcept; std::size_t calcMaxShortSize() const noexcept; diff --git a/src/Cmd/Add.cc b/src/Cmd/Add.cc index a6cdace87..ee24c1933 100644 --- a/src/Cmd/Add.cc +++ b/src/Cmd/Add.cc @@ -17,7 +17,7 @@ namespace cabin { -static Result addMain(CliArgsView args); +static rs::Result addMain(CliArgsView args); const Subcmd ADD_CMD = Subcmd{ "add" } @@ -39,15 +39,15 @@ const Subcmd ADD_CMD = .setPlaceholder("")) .setMainFn(addMain); -static Result handleNextArg(CliArgsView::iterator& itr, - const CliArgsView::iterator& end, - std::string& arg) { +static rs::Result handleNextArg(CliArgsView::iterator& itr, + const CliArgsView::iterator& end, + std::string& arg) { ++itr; if (itr == end) { return Subcmd::missingOptArgumentFor(*--itr); } arg = std::string(*itr); - return Ok(); + return rs::Ok(); } static void handleDependency(std::unordered_set& newDeps, @@ -91,7 +91,7 @@ static std::string getDependencyName(const std::string_view dep) { return name; } -static Result +static rs::Result addDependencyToManifest(const std::unordered_set& newDeps, bool isSystemDependency, std::string& version, std::string& tag, std::string& rev, @@ -102,8 +102,8 @@ addDependencyToManifest(const std::unordered_set& newDeps, depData.as_table_fmt().fmt = toml::table_format::oneline; if (isSystemDependency) { - Ensure(!version.empty(), - "The `--version` option is required for system dependencies"); + rs_ensure(!version.empty(), + "The `--version` option is required for system dependencies"); depData["version"] = version; depData["system"] = true; } else { @@ -119,7 +119,7 @@ addDependencyToManifest(const std::unordered_set& newDeps, } // Keep the order of the tables. - const fs::path manifestPath = Try(Manifest::findPath()); + const fs::path manifestPath = rs_try(Manifest::findPath()); auto data = toml::parse(manifestPath); // Check if the dependencies table exists, if not create it. @@ -133,8 +133,8 @@ addDependencyToManifest(const std::unordered_set& newDeps, const std::string gitUrl = getDependencyGitUrl(dep); const std::string depName = getDependencyName(dep); - Ensure(!gitUrl.empty() && !depName.empty(), - "git URL or dependency name must not be empty: {}", dep); + rs_ensure(!gitUrl.empty() && !depName.empty(), + "git URL or dependency name must not be empty: {}", dep); deps[depName] = depData; deps[depName]["git"] = gitUrl; @@ -147,11 +147,11 @@ addDependencyToManifest(const std::unordered_set& newDeps, ofs << data; Diag::info("Added", "to the cabin.toml"); - return Ok(); + return rs::Ok(); } -static Result addMain(const CliArgsView args) { - Ensure(!args.empty(), "No dependencies to add"); +static rs::Result addMain(const CliArgsView args) { + rs_ensure(!args.empty(), "No dependencies to add"); std::unordered_set newDeps = {}; @@ -165,13 +165,13 @@ static Result addMain(const CliArgsView args) { // clang-format off std::unordered_map< std::string_view, - std::function(decltype(args)::iterator&, decltype(args)::iterator)> + std::function(decltype(args)::iterator&, decltype(args)::iterator)> > handlers = { { "--sys", [&](auto&, auto) { isSystemDependency = true; - return Ok(); + return rs::Ok(); } }, { @@ -203,14 +203,14 @@ static Result addMain(const CliArgsView args) { // clang-format on for (auto itr = args.begin(); itr != args.end(); ++itr) { - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "add")); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end(), "add")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else { if (handlers.contains(*itr)) { - Try(handlers.at(*itr)(itr, args.end())); + rs_try(handlers.at(*itr)(itr, args.end())); } else { handleDependency(newDeps, *itr); } diff --git a/src/Cmd/Build.cc b/src/Cmd/Build.cc index 107c22ae9..2df3dcc5b 100644 --- a/src/Cmd/Build.cc +++ b/src/Cmd/Build.cc @@ -23,7 +23,7 @@ namespace cabin { -static Result buildMain(CliArgsView args); +static rs::Result buildMain(CliArgsView args); const Subcmd BUILD_CMD = Subcmd{ "build" } @@ -35,16 +35,17 @@ const Subcmd BUILD_CMD = .addOpt(OPT_JOBS) .setMainFn(buildMain); -static Result buildMain(const CliArgsView args) { +static rs::Result buildMain(const CliArgsView args) { // Parse args BuildProfile buildProfile = BuildProfile::Dev; bool buildCompdb = false; for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "build")); + const auto control = + rs_try(Cli::handleGlobalOpts(itr, args.end(), "build")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (matchesAny(arg, { "-r", "--release" })) { @@ -60,22 +61,22 @@ static Result buildMain(const CliArgsView args) { uint64_t numThreads{}; auto [ptr, ec] = std::from_chars(nextArg.begin(), nextArg.end(), numThreads); - Ensure(ec == std::errc(), "invalid number of threads: {}", nextArg); + rs_ensure(ec == std::errc(), "invalid number of threads: {}", nextArg); setParallelism(numThreads); } else { return BUILD_CMD.noSuchArg(arg); } } - const Manifest manifest = Try(Manifest::tryParse()); + const Manifest manifest = rs_try(Manifest::tryParse()); Builder builder(manifest.path.parent_path(), buildProfile); - Try(builder.schedule()); + rs_try(builder.schedule()); if (buildCompdb) { Diag::info("Generated", "{}/compile_commands.json", fs::relative(builder.compdbRoot(), manifest.path.parent_path()) .string()); - return Ok(); + return rs::Ok(); } return builder.build(); diff --git a/src/Cmd/Clean.cc b/src/Cmd/Clean.cc index 440ec74de..cc59099d9 100644 --- a/src/Cmd/Clean.cc +++ b/src/Cmd/Clean.cc @@ -11,7 +11,7 @@ namespace cabin { -static Result cleanMain(CliArgsView args) noexcept; +static rs::Result cleanMain(CliArgsView args) noexcept; const Subcmd CLEAN_CMD = // Subcmd{ "clean" } @@ -22,17 +22,18 @@ const Subcmd CLEAN_CMD = // .setPlaceholder("")) .setMainFn(cleanMain); -static Result cleanMain(CliArgsView args) noexcept { +static rs::Result cleanMain(CliArgsView args) noexcept { // TODO: share across sources - fs::path outDir = Try(Manifest::findPath()).parent_path() / "cabin-out"; + fs::path outDir = rs_try(Manifest::findPath()).parent_path() / "cabin-out"; // Parse args for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "clean")); + const auto control = + rs_try(Cli::handleGlobalOpts(itr, args.end(), "clean")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (matchesAny(arg, { "-p", "--profile" })) { @@ -42,7 +43,7 @@ static Result cleanMain(CliArgsView args) noexcept { const std::string_view nextArg = *++itr; if (!matchesAny(nextArg, { "dev", "release" })) { - Bail("Invalid argument for {}: {}", arg, nextArg); + rs_bail("Invalid argument for {}: {}", arg, nextArg); } outDir /= nextArg; @@ -55,7 +56,7 @@ static Result cleanMain(CliArgsView args) noexcept { Diag::info("Removing", "{}", fs::canonical(outDir).string()); fs::remove_all(outDir); } - return Ok(); + return rs::Ok(); } } // namespace cabin diff --git a/src/Cmd/Fmt.cc b/src/Cmd/Fmt.cc index 4c13ab048..3d978df42 100644 --- a/src/Cmd/Fmt.cc +++ b/src/Cmd/Fmt.cc @@ -24,7 +24,7 @@ namespace cabin { namespace fs = std::filesystem; -static Result fmtMain(CliArgsView args); +static rs::Result fmtMain(CliArgsView args); const Subcmd FMT_CMD = Subcmd{ "fmt" } @@ -118,7 +118,7 @@ static std::size_t countModifiedFiles(const std::vector& files) { return changedFiles; } -static Result fmtMain(const CliArgsView args) { +static rs::Result fmtMain(const CliArgsView args) { std::vector excludes; bool isCheck = false; bool useVcsIgnoreFiles = true; @@ -126,9 +126,9 @@ static Result fmtMain(const CliArgsView args) { for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "fmt")); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end(), "fmt")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (arg == "--check") { @@ -145,11 +145,11 @@ static Result fmtMain(const CliArgsView args) { } } - Ensure(commandExists("clang-format"), - "fmt command requires clang-format; try installing it by:\n" - " apt/brew install clang-format"); + rs_ensure(commandExists("clang-format"), + "fmt command requires clang-format; try installing it by:\n" + " apt/brew install clang-format"); - const auto manifest = Try(Manifest::tryParse()); + const auto manifest = rs_try(Manifest::tryParse()); std::vector clangFormatArgs{ "--style=file", "--fallback-style=LLVM", @@ -161,7 +161,7 @@ static Result fmtMain(const CliArgsView args) { collectFormatTargets(projectPath, excludes, useVcsIgnoreFiles); if (files.empty()) { Diag::warn("no files to format"); - return Ok(); + return rs::Ok(); } if (isVerbose()) { @@ -184,7 +184,7 @@ static Result fmtMain(const CliArgsView args) { const Command clangFormat = Command(cabinFmt, std::move(clangFormatArgs)) .setWorkingDirectory(projectPath.string()); - const ExitStatus exitStatus = Try(execCmd(clangFormat)); + const ExitStatus exitStatus = rs_try(execCmd(clangFormat)); if (exitStatus.success()) { const std::size_t numFiles = files.size(); if (isCheck) { @@ -195,9 +195,9 @@ static Result fmtMain(const CliArgsView args) { Diag::info("Formatted", "{} out of {} file{}", modifiedFiles, numFiles, numFiles == 1 ? "" : "s"); } - return Ok(); + return rs::Ok(); } else { - Bail("clang-format {}", exitStatus); + rs_bail("clang-format {}", exitStatus); } } diff --git a/src/Cmd/Help.cc b/src/Cmd/Help.cc index 6d11b9bf1..64d3c2931 100644 --- a/src/Cmd/Help.cc +++ b/src/Cmd/Help.cc @@ -4,7 +4,7 @@ namespace cabin { -static Result helpMain(CliArgsView args) noexcept; +static rs::Result helpMain(CliArgsView args) noexcept; const Subcmd HELP_CMD = // Subcmd{ "help" } @@ -12,7 +12,7 @@ const Subcmd HELP_CMD = // .setArg(Arg{ "COMMAND" }.setRequired(false)) .setMainFn(helpMain); -static Result helpMain(const CliArgsView args) noexcept { +static rs::Result helpMain(const CliArgsView args) noexcept { return getCli().printHelp(args); } diff --git a/src/Cmd/Init.cc b/src/Cmd/Init.cc index 9bfee8d27..bc922e60f 100644 --- a/src/Cmd/Init.cc +++ b/src/Cmd/Init.cc @@ -14,7 +14,7 @@ namespace cabin { -static Result initMain(CliArgsView args); +static rs::Result initMain(CliArgsView args); const Subcmd INIT_CMD = Subcmd{ "init" } @@ -23,15 +23,15 @@ const Subcmd INIT_CMD = .addOpt(OPT_LIB) .setMainFn(initMain); -static Result initMain(const CliArgsView args) { +static rs::Result initMain(const CliArgsView args) { // Parse args bool isBin = true; for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "init")); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end(), "init")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (matchesAny(arg, { "-b", "--bin" })) { @@ -43,15 +43,15 @@ static Result initMain(const CliArgsView args) { } } - Ensure(!fs::exists("cabin.toml"), - "cannot initialize an existing cabin package"); + rs_ensure(!fs::exists("cabin.toml"), + "cannot initialize an existing cabin package"); const fs::path root = fs::current_path(); const std::string packageName = root.stem().string(); - Try(validatePackageName(packageName)); + rs_try(validatePackageName(packageName)); - Try(createProjectFiles(isBin, root, packageName, /*skipExisting=*/true)); - return Ok(); + rs_try(createProjectFiles(isBin, root, packageName, /*skipExisting=*/true)); + return rs::Ok(); } } // namespace cabin diff --git a/src/Cmd/Lint.cc b/src/Cmd/Lint.cc index b4c026866..c6d074ce9 100644 --- a/src/Cmd/Lint.cc +++ b/src/Cmd/Lint.cc @@ -19,7 +19,7 @@ namespace cabin { -static Result lintMain(CliArgsView args); +static rs::Result lintMain(CliArgsView args); const Subcmd LINT_CMD = Subcmd{ "lint" } @@ -58,9 +58,9 @@ collectNestedProjectExcludes(const fs::path& manifestDir) { return excludes; } -static Result lint(const std::string_view name, - const std::vector& cpplintArgs, - bool useVcsIgnoreFiles) { +static rs::Result lint(const std::string_view name, + const std::vector& cpplintArgs, + bool useVcsIgnoreFiles) { Diag::info("Linting", "{}", name); Command cpplintCmd("cpplint", cpplintArgs); @@ -84,23 +84,23 @@ static Result lint(const std::string_view name, cpplintCmd.addArg("--recursive"); cpplintCmd.addArg("."); - const ExitStatus exitStatus = Try(execCmd(cpplintCmd)); + const ExitStatus exitStatus = rs_try(execCmd(cpplintCmd)); if (exitStatus.success()) { - return Ok(); + return rs::Ok(); } else { - Bail("cpplint {}", exitStatus); + rs_bail("cpplint {}", exitStatus); } } -static Result lintMain(const CliArgsView args) { +static rs::Result lintMain(const CliArgsView args) { LintArgs lintArgs; bool useVcsIgnoreFiles = true; for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "lint")); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end(), "lint")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (arg == "--exclude") { @@ -117,11 +117,11 @@ static Result lintMain(const CliArgsView args) { } if (!commandExists("cpplint")) { - Bail("lint command requires cpplint; try installing it by:\n" - " pip install cpplint"); + rs_bail("lint command requires cpplint; try installing it by:\n" + " pip install cpplint"); } - const auto manifest = Try(Manifest::tryParse()); + const auto manifest = rs_try(Manifest::tryParse()); std::vector cpplintArgs = std::move(lintArgs.excludes); const fs::path projectDir = manifest.path.parent_path(); diff --git a/src/Cmd/New.cc b/src/Cmd/New.cc index 62fae0e00..1388ccf0c 100644 --- a/src/Cmd/New.cc +++ b/src/Cmd/New.cc @@ -18,7 +18,7 @@ namespace cabin { -static Result newMain(CliArgsView args); +static rs::Result newMain(CliArgsView args); const Subcmd NEW_CMD = // Subcmd{ "new" } @@ -83,25 +83,26 @@ struct FileTemplate { std::string contents; }; -static Result writeToFile(const fs::path& fpath, const std::string& text, - const bool skipIfExists = false) { +static rs::Result writeToFile(const fs::path& fpath, + const std::string& text, + const bool skipIfExists = false) { if (fs::exists(fpath)) { if (skipIfExists) { - return Ok(); + return rs::Ok(); } - Bail("refusing to overwrite `{}`; file already exists", fpath.string()); + rs_bail("refusing to overwrite `{}`; file already exists", fpath.string()); } std::ofstream ofs(fpath, std::ios::trunc); - Ensure(ofs.is_open(), "opening `{}` failed", fpath.string()); + rs_ensure(ofs.is_open(), "opening `{}` failed", fpath.string()); ofs << text; - Ensure(static_cast(ofs), "writing `{}` failed", fpath.string()); - return Ok(); + rs_ensure(static_cast(ofs), "writing `{}` failed", fpath.string()); + return rs::Ok(); } -Result createProjectFiles(const bool isBin, const fs::path& root, - const std::string_view projectName, - const bool skipExisting) { +rs::Result createProjectFiles(const bool isBin, const fs::path& root, + const std::string_view projectName, + const bool skipExisting) { std::vector templates; if (isBin) { fs::create_directories(root / "src"); @@ -144,24 +145,24 @@ void hello_world() {{ } for (const FileTemplate& file : templates) { - Try(writeToFile(file.path, file.contents, skipExisting)); + rs_try(writeToFile(file.path, file.contents, skipExisting)); } Diag::info("Created", "{} `{}` package", isBin ? "binary (application)" : "library", projectName); - return Ok(); + return rs::Ok(); } -static Result newMain(const CliArgsView args) { +static rs::Result newMain(const CliArgsView args) { // Parse args bool isBin = true; std::string packageName; for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "new")); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end(), "new")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (matchesAny(arg, { "-b", "--bin" })) { @@ -175,13 +176,13 @@ static Result newMain(const CliArgsView args) { } } - Try(validatePackageName(packageName)); - Ensure(!fs::exists(packageName), "directory `{}` already exists", - packageName); + rs_try(validatePackageName(packageName)); + rs_ensure(!fs::exists(packageName), "directory `{}` already exists", + packageName); - Try(createProjectFiles(isBin, fs::path(packageName), packageName)); + rs_try(createProjectFiles(isBin, fs::path(packageName), packageName)); git2::Repository().init(packageName); - return Ok(); + return rs::Ok(); } } // namespace cabin diff --git a/src/Cmd/New.hpp b/src/Cmd/New.hpp index afb16c809..f67a4e396 100644 --- a/src/Cmd/New.hpp +++ b/src/Cmd/New.hpp @@ -11,8 +11,9 @@ namespace cabin { extern const Subcmd NEW_CMD; std::string createCabinToml(std::string_view projectName) noexcept; -Result createProjectFiles(bool isBin, const std::filesystem::path& root, - std::string_view projectName, - bool skipExisting = false); +rs::Result createProjectFiles(bool isBin, + const std::filesystem::path& root, + std::string_view projectName, + bool skipExisting = false); } // namespace cabin diff --git a/src/Cmd/Remove.cc b/src/Cmd/Remove.cc index 8bb4d4377..63d08b159 100644 --- a/src/Cmd/Remove.cc +++ b/src/Cmd/Remove.cc @@ -15,7 +15,7 @@ namespace cabin { -static Result removeMain(CliArgsView args); +static rs::Result removeMain(CliArgsView args); const Subcmd REMOVE_CMD = // Subcmd{ "remove" } @@ -26,15 +26,15 @@ const Subcmd REMOVE_CMD = // .setVariadic(true)) .setMainFn(removeMain); -static Result removeMain(const CliArgsView args) { - Ensure(!args.empty(), "`cabin remove` requires at least one argument"); +static rs::Result removeMain(const CliArgsView args) { + rs_ensure(!args.empty(), "`cabin remove` requires at least one argument"); std::vector removedDeps = {}; - const fs::path manifestPath = Try(Manifest::findPath()); + const fs::path manifestPath = rs_try(Manifest::findPath()); auto data = toml::parse(manifestPath); auto& deps = data["dependencies"]; - Ensure(!deps.is_empty(), "No dependencies to remove"); + rs_ensure(!deps.is_empty(), "No dependencies to remove"); for (const std::string& dep : args) { if (deps.contains(dep)) { @@ -53,7 +53,7 @@ static Result removeMain(const CliArgsView args) { Diag::info("Removed", "{} from {}", fmt::join(removedDeps, ", "), manifestPath.string()); } - return Ok(); + return rs::Ok(); } } // namespace cabin diff --git a/src/Cmd/Run.cc b/src/Cmd/Run.cc index 47acfd073..f738e44f5 100644 --- a/src/Cmd/Run.cc +++ b/src/Cmd/Run.cc @@ -22,7 +22,7 @@ namespace cabin { -static Result runMain(CliArgsView args); +static rs::Result runMain(CliArgsView args); const Subcmd RUN_CMD = Subcmd{ "run" } @@ -36,16 +36,16 @@ const Subcmd RUN_CMD = .setRequired(false)) .setMainFn(runMain); -static Result runMain(const CliArgsView args) { +static rs::Result runMain(const CliArgsView args) { // Parse args BuildProfile buildProfile = BuildProfile::Dev; auto itr = args.begin(); for (; itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "run")); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end(), "run")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (matchesAny(arg, { "-r", "--release" })) { @@ -59,7 +59,7 @@ static Result runMain(const CliArgsView args) { uint64_t numThreads{}; auto [ptr, ec] = std::from_chars(nextArg.begin(), nextArg.end(), numThreads); - Ensure(ec == std::errc(), "invalid number of threads: {}", nextArg); + rs_ensure(ec == std::errc(), "invalid number of threads: {}", nextArg); setParallelism(numThreads); } else { // Unknown argument is the start of the program arguments. @@ -72,10 +72,10 @@ static Result runMain(const CliArgsView args) { runArgs.emplace_back(*itr); } - const auto manifest = Try(Manifest::tryParse()); + const auto manifest = rs_try(Manifest::tryParse()); Builder builder(manifest.path.parent_path(), buildProfile); - Try(builder.schedule()); - Try(builder.build()); + rs_try(builder.schedule()); + rs_try(builder.build()); Diag::info( "Running", "`{}/{}`", @@ -83,11 +83,11 @@ static Result runMain(const CliArgsView args) { manifest.package.name); const Command command((builder.outDirPath() / manifest.package.name).string(), runArgs); - const ExitStatus exitStatus = Try(execCmd(command)); + const ExitStatus exitStatus = rs_try(execCmd(command)); if (exitStatus.success()) { - return Ok(); + return rs::Ok(); } else { - Bail("run {}", exitStatus); + rs_bail("run {}", exitStatus); } } diff --git a/src/Cmd/Search.cc b/src/Cmd/Search.cc index 94f6e5fb8..560e84aa8 100644 --- a/src/Cmd/Search.cc +++ b/src/Cmd/Search.cc @@ -15,7 +15,7 @@ namespace cabin { -static Result searchMain(CliArgsView args); +static rs::Result searchMain(CliArgsView args); const Subcmd SEARCH_CMD = Subcmd{ "search" } @@ -93,21 +93,22 @@ static void printTable(const nlohmann::json& packages) { } } -static Result searchMain(const CliArgsView args) { +static rs::Result searchMain(const CliArgsView args) { SearchArgs searchArgs; for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "search")); + const auto control = + rs_try(Cli::handleGlobalOpts(itr, args.end(), "search")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (arg == "--per-page") { - Ensure(itr + 1 < args.end(), "missing argument for `--per-page`"); + rs_ensure(itr + 1 < args.end(), "missing argument for `--per-page`"); searchArgs.perPage = std::stoul(std::string(*++itr)); } else if (arg == "--page") { - Ensure(itr + 1 < args.end(), "missing argument for `--page`"); + rs_ensure(itr + 1 < args.end(), "missing argument for `--page`"); searchArgs.page = std::stoul(std::string(*++itr)); } else if (searchArgs.name.empty()) { searchArgs.name = *itr; @@ -115,16 +116,16 @@ static Result searchMain(const CliArgsView args) { return SEARCH_CMD.noSuchArg(arg); } } - Ensure(!searchArgs.name.empty(), "missing package name"); + rs_ensure(!searchArgs.name.empty(), "missing package name"); const nlohmann::json packages = searchPackages(searchArgs); if (packages.empty()) { Diag::warn("no packages found"); - return Ok(); + return rs::Ok(); } printTable(packages); - return Ok(); + return rs::Ok(); } } // namespace cabin diff --git a/src/Cmd/Test.cc b/src/Cmd/Test.cc index 89cf911d8..e7856caef 100644 --- a/src/Cmd/Test.cc +++ b/src/Cmd/Test.cc @@ -18,7 +18,7 @@ namespace cabin { -static Result testMain(CliArgsView args); +static rs::Result testMain(CliArgsView args); const Subcmd TEST_CMD = // Subcmd{ "test" } @@ -28,15 +28,15 @@ const Subcmd TEST_CMD = // .addOpt(Opt{ "--coverage" }.setDesc("Enable code coverage analysis")) .setMainFn(testMain); -static Result testMain(const CliArgsView args) { +static rs::Result testMain(const CliArgsView args) { bool enableCoverage = false; for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "test")); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end(), "test")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } if (control == Cli::Continue) { continue; @@ -50,7 +50,7 @@ static Result testMain(const CliArgsView args) { uint64_t numThreads{}; auto [ptr, ec] = std::from_chars(nextArg.begin(), nextArg.end(), numThreads); - Ensure(ec == std::errc(), "invalid number of threads: {}", nextArg); + rs_ensure(ec == std::errc(), "invalid number of threads: {}", nextArg); setParallelism(numThreads); } else if (arg == "--coverage") { enableCoverage = true; @@ -59,10 +59,10 @@ static Result testMain(const CliArgsView args) { } } - const Manifest manifest = Try(Manifest::tryParse()); + const Manifest manifest = rs_try(Manifest::tryParse()); Builder builder(manifest.path.parent_path(), BuildProfile::Test); - Try(builder.schedule(ScheduleOptions{ .includeDevDeps = true, - .enableCoverage = enableCoverage })); + rs_try(builder.schedule(ScheduleOptions{ .includeDevDeps = true, + .enableCoverage = enableCoverage })); return builder.test(); } diff --git a/src/Cmd/Tidy.cc b/src/Cmd/Tidy.cc index 46999cd63..f0d1be9da 100644 --- a/src/Cmd/Tidy.cc +++ b/src/Cmd/Tidy.cc @@ -25,7 +25,7 @@ namespace cabin { namespace fs = std::filesystem; -static Result tidyMain(CliArgsView args); +static rs::Result tidyMain(CliArgsView args); const Subcmd TIDY_CMD = Subcmd{ "tidy" } @@ -34,30 +34,30 @@ const Subcmd TIDY_CMD = .addOpt(OPT_JOBS) .setMainFn(tidyMain); -static Result tidyImpl(const Command& makeCmd) { +static rs::Result tidyImpl(const Command& makeCmd) { const auto start = std::chrono::steady_clock::now(); - const ExitStatus exitStatus = Try(execCmd(makeCmd)); + const ExitStatus exitStatus = rs_try(execCmd(makeCmd)); const auto end = std::chrono::steady_clock::now(); const std::chrono::duration elapsed = end - start; if (exitStatus.success()) { Diag::info("Finished", "run-clang-tidy in {:.2f}s", elapsed.count()); - return Ok(); + return rs::Ok(); } - Bail("run-clang-tidy {}", exitStatus); + rs_bail("run-clang-tidy {}", exitStatus); } -static Result tidyMain(const CliArgsView args) { +static rs::Result tidyMain(const CliArgsView args) { // Parse args bool fix = false; for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "tidy")); + const auto control = rs_try(Cli::handleGlobalOpts(itr, args.end(), "tidy")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } else if (arg == "--fix") { @@ -71,7 +71,7 @@ static Result tidyMain(const CliArgsView args) { uint64_t numThreads{}; auto [ptr, ec] = std::from_chars(nextArg.begin(), nextArg.end(), numThreads); - Ensure(ec == std::errc(), "invalid number of threads: {}", nextArg); + rs_ensure(ec == std::errc(), "invalid number of threads: {}", nextArg); setParallelism(numThreads); } else { return TIDY_CMD.noSuchArg(arg); @@ -83,7 +83,7 @@ static Result tidyMain(const CliArgsView args) { setParallelism(1); } - const auto manifest = Try(Manifest::tryParse()); + const auto manifest = rs_try(Manifest::tryParse()); const fs::path projectRoot = manifest.path.parent_path(); // Generate compile_commands for the dev and test profiles so tidy sees both @@ -95,7 +95,7 @@ static Result tidyMain(const CliArgsView args) { for (const BuildProfile& profile : profiles) { Builder builder(projectRoot, profile); const bool includeDevDeps = (profile == BuildProfile::Test); - Try(builder.schedule(ScheduleOptions{ + rs_try(builder.schedule(ScheduleOptions{ .includeDevDeps = includeDevDeps, .enableCoverage = false, .suppressAnalysisLog = !isFirstProfile, @@ -108,7 +108,7 @@ static Result tidyMain(const CliArgsView args) { if (const char* tidyEnv = std::getenv("CABIN_TIDY")) { runClangTidy = tidyEnv; } - Ensure(commandExists(runClangTidy), "run-clang-tidy is required"); + rs_ensure(commandExists(runClangTidy), "run-clang-tidy is required"); Command runCmd(""); if (commandExists("xcrun")) { diff --git a/src/Cmd/Version.cc b/src/Cmd/Version.cc index f5a0e026f..696ed893e 100644 --- a/src/Cmd/Version.cc +++ b/src/Cmd/Version.cc @@ -40,7 +40,7 @@ namespace cabin { -Result versionMain(CliArgsView args) noexcept; +rs::Result versionMain(CliArgsView args) noexcept; const Subcmd VERSION_CMD = // Subcmd{ "version" } @@ -129,15 +129,16 @@ static constinit const char COMPILE_DATE[] = { '\0' }; -Result versionMain(const CliArgsView args) noexcept { +rs::Result versionMain(const CliArgsView args) noexcept { // Parse args for (auto itr = args.begin(); itr != args.end(); ++itr) { const std::string_view arg = *itr; // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign) - const auto control = Try(Cli::handleGlobalOpts(itr, args.end(), "version")); + const auto control = + rs_try(Cli::handleGlobalOpts(itr, args.end(), "version")); if (control == Cli::Return) { - return Ok(); + return rs::Ok(); } else if (control == Cli::Continue) { continue; } @@ -158,7 +159,7 @@ Result versionMain(const CliArgsView args) noexcept { curl::Version()); } - return Ok(); + return rs::Ok(); } } // namespace cabin diff --git a/src/Driver.cc b/src/Driver.cc index 6760a8fd2..e826c5dc3 100644 --- a/src/Driver.cc +++ b/src/Driver.cc @@ -88,8 +88,8 @@ static std::string colorizeAnyhowError(std::string s) { return s; } -Result run(int argc, - char* argv[]) noexcept { // NOLINT(*-avoid-c-arrays) +rs::Result run(int argc, + char* argv[]) noexcept { // NOLINT(*-avoid-c-arrays) // Set up logger spdlog::cfg::load_env_levels(LOG_ENV); if (std::getenv(LOG_ENV_UNUSED)) { diff --git a/src/Driver.hpp b/src/Driver.hpp index 1dc751d92..da9edfe2d 100644 --- a/src/Driver.hpp +++ b/src/Driver.hpp @@ -5,6 +5,6 @@ namespace cabin { // NOLINTNEXTLINE(*-avoid-c-arrays) -Result run(int argc, char* argv[]) noexcept; +rs::Result run(int argc, char* argv[]) noexcept; } // namespace cabin diff --git a/tests/helpers.hpp b/tests/helpers.hpp index 43388885c..7c60be35e 100644 --- a/tests/helpers.hpp +++ b/tests/helpers.hpp @@ -110,8 +110,8 @@ inline std::string sanitizeOutput( return text; } -inline Result runCabin(const std::vector& args, - const fs::path& workdir = {}) { +inline rs::Result runCabin(const std::vector& args, + const fs::path& workdir = {}) { cabin::Command cmd(cabinBinary().string()); cmd.setEnv("CABIN_TERM_COLOR", "never"); for (const auto& arg : args) { @@ -123,12 +123,12 @@ inline Result runCabin(const std::vector& args, cmd.setStdOutConfig(cabin::Command::IOConfig::Piped); cmd.setStdErrConfig(cabin::Command::IOConfig::Piped); - const cabin::CommandOutput output = Try(cmd.output()); - return Ok(RunResult{ output.exitStatus, output.stdOut, output.stdErr }); + const cabin::CommandOutput output = rs_try(cmd.output()); + return rs::Ok(RunResult{ output.exitStatus, output.stdOut, output.stdErr }); } -inline Result runCabin(std::initializer_list args, - const fs::path& workdir = {}) { +inline rs::Result runCabin(std::initializer_list args, + const fs::path& workdir = {}) { return runCabin(std::vector(args), workdir); }