yams/tools/yams-cli/main.cpp
trvon 11c391579c
fix(cli): preserve content bytes during hash hydration
Signed-off-by: trvon <me@trevon.dev>
2026-09-05 11:52:46 -06:00

138 lines
5.4 KiB
C++

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include "logging.h"
#include <spdlog/spdlog.h>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/io_context.hpp>
#include <yams/cli/cli_perf_trace.h>
#include <yams/cli/yams_cli.h>
#include <yams/platform/windows_init.h>
#include <yams/version.hpp>
#if __has_include(<version_generated.h>)
#include <version_generated.h>
#endif
namespace {
bool env_truthy(const char* raw) {
if (raw == nullptr || *raw == '\0') {
return false;
}
std::string value(raw);
for (auto& ch : value) {
ch = static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
}
return value == "1" || value == "true" || value == "on" || value == "yes";
}
} // namespace
int main(int argc, char* argv[]) {
const auto mainStart = std::chrono::steady_clock::now();
try {
#ifndef _WIN32
::setenv("YAMS_CLI_ONE_SHOT", "1", 1);
#else
_putenv_s("YAMS_CLI_ONE_SHOT", "1");
#endif
if (argc == 2 && argv[1] != nullptr && std::string_view(argv[1]) == "--version") {
#if __has_include(<version_generated.h>)
yams::VersionInfo ver{};
std::string longVersion = std::string(ver.effective_version);
std::string commit = ver.git_commit ? std::string(ver.git_commit) : "";
if (!commit.empty()) {
longVersion += " (commit: " + commit + ")";
} else if (std::string(ver.git_describe).size()) {
longVersion += " (" + std::string(ver.git_describe) + ")";
}
longVersion += " built:" + std::string(ver.build_timestamp);
std::cout << longVersion << '\n';
#elif defined(YAMS_VERSION_LONG_STRING)
std::cout << YAMS_VERSION_LONG_STRING << '\n';
#else
std::cout << YAMS_VERSION_STRING << '\n';
#endif
yams::cli::cli_perf_trace("main.total",
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - mainStart),
"version_fast_path");
return 0;
}
// Set up logging with conservative default; YamsCLI::run() adjusts based on flags
yams::cli::initializeCliLogging();
yams::cli::cli_perf_trace("main.logging",
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - mainStart));
// Create io_context for async operations
const auto ioStart = std::chrono::steady_clock::now();
boost::asio::io_context io_context;
auto work_guard = boost::asio::make_work_guard(io_context);
yams::cli::cli_perf_trace("main.io_context",
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - ioStart));
// Start worker threads
const auto threadStart = std::chrono::steady_clock::now();
unsigned int thread_count = std::thread::hardware_concurrency();
if (thread_count == 0)
thread_count = 4;
thread_count = std::min(thread_count, 16u);
if (env_truthy(std::getenv("YAMS_CLI_ONE_SHOT"))) {
thread_count = 1;
}
std::vector<std::thread> threads;
for (unsigned int i = 0; i < thread_count; ++i) {
threads.emplace_back([&io_context]() { io_context.run(); });
}
yams::cli::cli_perf_trace("main.thread_pool",
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - threadStart),
std::to_string(thread_count));
// Create and run CLI with executor
const auto cliStart = std::chrono::steady_clock::now();
yams::cli::YamsCLI cli(io_context.get_executor());
yams::cli::cli_perf_trace("main.cli_ctor",
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - cliStart));
const auto runStart = std::chrono::steady_clock::now();
int result = cli.run(argc, argv);
yams::cli::cli_perf_trace("main.cli_run",
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - runStart));
// Cleanup
const auto cleanupStart = std::chrono::steady_clock::now();
work_guard.reset();
io_context.stop();
for (auto& t : threads) {
if (t.joinable())
t.join();
}
yams::cli::cli_perf_trace("main.cleanup",
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - cleanupStart));
yams::cli::cli_perf_trace("main.total",
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - mainStart));
return result;
} catch (const std::exception& e) {
spdlog::error("Fatal error: {}", e.what());
return 1;
} catch (...) {
spdlog::error("Unknown fatal error");
return 1;
}
}