Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/Sources/Main.cpp
diff options
context:
space:
mode:
authorLeitwolf112026-11-05 06:29:20 +0300
committerLeitwolf112026-11-05 06:29:20 +0300
commit52490ff852f3d72ce9c9eb76898080223e9e17fd (patch)
tree4dd64d7cdce703fa15956dfa51bf587b3f397153 /Sources/Main.cpp
downloadtazelish-52490ff852f3d72ce9c9eb76898080223e9e17fd.tar.gz
Start Tazelish with its command line and version files
Tazelish installs Tazel and chooses which version of it runs, for those who use Tazel alone. This first part holds everything that needs no download: - Versions: MAJOR.SEMIMAJOR.MINOR.PATCH without leading zeros, unstable, nightly, and YYYY-MM-DD-unstable or -nightly with a date the calendar has. - The command line, read by hand into a typed command: install, use and default with --force before or after the version, self update|remove|purge, and help with or without a command. A wrong command line ends with exit code 2. - tazelish.txt and config.txt: the nearest tazelish.txt in the current folder or above it comes first, then $HOME/.tazelish/config.txt or %USERPROFILE%\.tazelish\config.txt. use and default refuse to write over a file that exists unless --force is given. install and self download from static.tazel.net, which this build does not do; they say so and end with exit code 1. C++17 with fmt, tested with Catch3, built by Bazel (clang-cl on Windows, with the rules_cc patch the Tala repository carries). The code throws no exceptions and builds with warnings as errors; the tests leave out -Wconversion, which the headers of Catch3 do not pass. CI tests on Linux, macOS and Windows.
Diffstat (limited to 'Sources/Main.cpp')
-rw-r--r--Sources/Main.cpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/Sources/Main.cpp b/Sources/Main.cpp
new file mode 100644
index 0000000..8ea8b89
--- /dev/null
+++ b/Sources/Main.cpp
@@ -0,0 +1,140 @@
+// SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
+// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0
+
+#include <cstdio>
+#include <filesystem>
+#include <fmt/format.h>
+#include <string_view>
+#include <vector>
+
+#include "Progmasoft/Tazelish/CommandLine.hpp"
+#include "Progmasoft/Tazelish/Help.hpp"
+#include "Progmasoft/Tazelish/VersionFiles.hpp"
+
+namespace
+{
+
+ namespace fs = std::filesystem;
+ namespace tazelish = Progmasoft::Tazelish;
+
+ constexpr int kSuccess = 0;
+ constexpr int kFailure = 1;
+ constexpr int kUsage = 2;
+
+ int
+ Report(const tazelish::FileError &error)
+ {
+ fmt::print(stderr,
+ "error: {} {}\n",
+ error.file.string(),
+ error.message);
+ return kFailure;
+ }
+
+ int
+ Write(const fs::path &file, const tazelish::Version &version, bool force)
+ {
+ if (auto error = tazelish::WriteVersionFile(file, version, force))
+ {
+ return Report(*error);
+ }
+ fmt::print("Wrote {} to {}\n",
+ tazelish::FormatVersion(version),
+ file.string());
+ return kSuccess;
+ }
+
+ int
+ RunUse(const tazelish::Use &use)
+ {
+ return Write(fs::path(".") / fs::path(tazelish::kProjectFileName),
+ use.version,
+ use.force);
+ }
+
+ int
+ RunDefault(const tazelish::Default &choice)
+ {
+ const auto home = tazelish::HomeDirectory();
+ if (!home)
+ {
+#ifdef _WIN32
+ fmt::print(stderr, "error: USERPROFILE is not set\n");
+#else
+ fmt::print(stderr, "error: HOME is not set\n");
+#endif
+ return kFailure;
+ }
+ return Write(tazelish::ConfigFile(*home), choice.version, choice.force);
+ }
+
+ // Installing and updating download from static.tazel.net, which this build
+ // of Tazelish does not do.
+ int
+ RunDownloading(std::string_view command)
+ {
+ fmt::print(
+ stderr,
+ "error: tazelish {} downloads from static.tazel.net, and this "
+ "build of Tazelish does not download\n",
+ command);
+ return kFailure;
+ }
+
+ std::string_view
+ SelfName(tazelish::SelfAction action)
+ {
+ switch (action)
+ {
+ case tazelish::SelfAction::kUpdate:
+ return "self update";
+ case tazelish::SelfAction::kRemove:
+ return "self remove";
+ case tazelish::SelfAction::kPurge:
+ return "self purge";
+ }
+ return "self";
+ }
+
+ int
+ Run(const tazelish::Command &command)
+ {
+ if (const auto *help = std::get_if<tazelish::Help>(&command))
+ {
+ fmt::print("{}", tazelish::HelpText(help->topic));
+ return kSuccess;
+ }
+ if (const auto *use = std::get_if<tazelish::Use>(&command))
+ {
+ return RunUse(*use);
+ }
+ if (const auto *choice = std::get_if<tazelish::Default>(&command))
+ {
+ return RunDefault(*choice);
+ }
+ if (std::holds_alternative<tazelish::Install>(command))
+ {
+ return RunDownloading("install");
+ }
+ return RunDownloading(
+ SelfName(std::get<tazelish::Self>(command).action));
+ }
+
+} // namespace
+
+int
+main(int argc, char **argv)
+{
+ std::vector<std::string_view> arguments;
+ for (int index = 1; index < argc; ++index)
+ {
+ arguments.emplace_back(argv[index]);
+ }
+ const auto parsed = tazelish::ParseCommandLine(arguments);
+ if (const auto *rejection = std::get_if<tazelish::Rejection>(&parsed))
+ {
+ fmt::print(stderr, "error: {}\n", rejection->message);
+ return kUsage;
+ }
+ return Run(std::get<tazelish::Command>(parsed));
+}