mirror of
https://github.com/ModOrganizer2/mob.git
synced 2026-07-27 14:07:05 -07:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60eb00e04e |
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
# We'll use defaults from the LLVM style, but with 4 columns indentation.
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# Force pointers to the type for C++.
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
PointerAlignment: Left
|
||||||
|
AlignConsecutiveAssignments: true
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLambdasOnASingleLine: Empty
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignTrailingComments: true
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
NamespaceIndentation: All
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
BreakBeforeBraces: Stroustrup
|
||||||
|
ColumnLimit: 88
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"pch.h"$'
|
||||||
|
Priority: -1
|
||||||
|
SortPriority: -1
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Explicitly declare text files you want to always be normalized and converted
|
||||||
|
# to native line endings on checkout.
|
||||||
|
*.cpp text eol=crlf
|
||||||
|
*.h text eol=crlf
|
||||||
@@ -21,6 +21,10 @@ host =
|
|||||||
super = cmake_common modorganizer* githubpp
|
super = cmake_common modorganizer* githubpp
|
||||||
plugins = check_fnis bsapacker bsa_extractor diagnose_basic installer_* plugin_python preview_base preview_bsa tool_* game_*
|
plugins = check_fnis bsapacker bsa_extractor diagnose_basic installer_* plugin_python preview_base preview_bsa tool_* game_*
|
||||||
|
|
||||||
|
[translations]
|
||||||
|
mo2-translations = organizer
|
||||||
|
mo2-game-bethesda = game_creation game_enderal game_enderalse game_fallout3 game_fallout4 game_fallout4vr game_falloutNV game_gamebryo game_morrowind game_nehrim game_oblivion game_skyrim game_skyrimse game_skyrimvr game_ttw
|
||||||
|
|
||||||
[task]
|
[task]
|
||||||
enabled = true
|
enabled = true
|
||||||
mo_org = ModOrganizer2
|
mo_org = ModOrganizer2
|
||||||
@@ -144,10 +148,10 @@ install_pdbs =
|
|||||||
install_dlls =
|
install_dlls =
|
||||||
install_loot =
|
install_loot =
|
||||||
install_plugins =
|
install_plugins =
|
||||||
|
install_extensions =
|
||||||
install_stylesheets =
|
install_stylesheets =
|
||||||
install_licenses =
|
install_licenses =
|
||||||
install_pythoncore =
|
install_pythoncore =
|
||||||
install_translations =
|
|
||||||
vs =
|
vs =
|
||||||
qt_install =
|
qt_install =
|
||||||
qt_bin =
|
qt_bin =
|
||||||
|
|||||||
+84
-89
@@ -1,95 +1,99 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "commands.h"
|
|
||||||
#include "../core/ini.h"
|
|
||||||
#include "../core/conf.h"
|
#include "../core/conf.h"
|
||||||
#include "../core/context.h"
|
#include "../core/context.h"
|
||||||
|
#include "../core/ini.h"
|
||||||
#include "../core/op.h"
|
#include "../core/op.h"
|
||||||
#include "../tasks/task_manager.h"
|
#include "../tasks/task_manager.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
build_command::build_command()
|
build_command::build_command() : command(requires_options | handle_sigint) {}
|
||||||
: command(requires_options | handle_sigint)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
command::meta_t build_command::meta() const
|
command::meta_t build_command::meta() const
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"build",
|
return {"build", "builds tasks"};
|
||||||
"builds tasks"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group build_command::do_group()
|
clipp::group build_command::do_group()
|
||||||
{
|
{
|
||||||
return
|
return (clipp::command("build")).set(picked_),
|
||||||
(clipp::command("build")).set(picked_),
|
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
(clipp::option("-h", "--help") >> help_) % ("shows this message"),
|
||||||
% ("shows this message"),
|
|
||||||
|
|
||||||
(clipp::option("-g", "--redownload") >> redownload_)
|
(clipp::option("-g", "--redownload") >> redownload_) %
|
||||||
% "redownloads archives, see --reextract",
|
"redownloads archives, see --reextract",
|
||||||
|
|
||||||
(clipp::option("-e", "--reextract") >> reextract_)
|
(clipp::option("-e", "--reextract") >> reextract_) %
|
||||||
% "deletes source directories and re-extracts archives",
|
"deletes source directories and re-extracts archives",
|
||||||
|
|
||||||
(clipp::option("-c", "--reconfigure") >> reconfigure_)
|
(clipp::option("-c", "--reconfigure") >> reconfigure_) %
|
||||||
% "reconfigures the task by running cmake, configure scripts, "
|
"reconfigures the task by running cmake, configure scripts, "
|
||||||
"etc.; some tasks might have to delete the whole source "
|
"etc.; some tasks might have to delete the whole source "
|
||||||
"directory",
|
"directory",
|
||||||
|
|
||||||
(clipp::option("-b", "--rebuild") >> rebuild_)
|
(clipp::option("-b", "--rebuild") >> rebuild_) %
|
||||||
% "cleans and rebuilds projects; some tasks might have to "
|
"cleans and rebuilds projects; some tasks might have to "
|
||||||
"delete the whole source directory",
|
"delete the whole source directory",
|
||||||
|
|
||||||
(clipp::option("-n", "--new") >> new_)
|
(clipp::option("-n", "--new") >> new_) %
|
||||||
% "deletes everything and starts from scratch",
|
"deletes everything and starts from scratch",
|
||||||
|
|
||||||
(
|
(clipp::option("--clean-task").call([&] {
|
||||||
clipp::option("--clean-task").call([&]{ clean_ = true; }) |
|
clean_ = true;
|
||||||
clipp::option("--no-clean-task").call([&]{ clean_ = false; })
|
}) |
|
||||||
) % "sets whether tasks are cleaned",
|
clipp::option("--no-clean-task").call([&] {
|
||||||
|
clean_ = false;
|
||||||
|
})) %
|
||||||
|
"sets whether tasks are cleaned",
|
||||||
|
|
||||||
(
|
(clipp::option("--fetch-task").call([&] {
|
||||||
clipp::option("--fetch-task").call([&]{ fetch_ = true; }) |
|
fetch_ = true;
|
||||||
clipp::option("--no-fetch-task").call([&]{ fetch_ = false; })
|
}) |
|
||||||
) % "sets whether tasks are fetched",
|
clipp::option("--no-fetch-task").call([&] {
|
||||||
|
fetch_ = false;
|
||||||
|
})) %
|
||||||
|
"sets whether tasks are fetched",
|
||||||
|
|
||||||
(
|
(clipp::option("--build-task").call([&] {
|
||||||
clipp::option("--build-task").call([&]{ build_ = true; }) |
|
build_ = true;
|
||||||
clipp::option("--no-build-task").call([&]{ build_ = false; })
|
}) |
|
||||||
) % "sets whether tasks are built",
|
clipp::option("--no-build-task").call([&] {
|
||||||
|
build_ = false;
|
||||||
|
})) %
|
||||||
|
"sets whether tasks are built",
|
||||||
|
|
||||||
(
|
(clipp::option("--pull").call([&] {
|
||||||
clipp::option("--pull").call([&]{ nopull_ = false; }) |
|
nopull_ = false;
|
||||||
clipp::option("--no-pull").call([&]{ nopull_ = true; })
|
}) |
|
||||||
) % "whether to pull repos that are already cloned; global override",
|
clipp::option("--no-pull").call([&] {
|
||||||
|
nopull_ = true;
|
||||||
|
})) %
|
||||||
|
"whether to pull repos that are already cloned; global override",
|
||||||
|
|
||||||
(
|
(clipp::option("--revert-ts").call([&] {
|
||||||
clipp::option("--revert-ts").call([&]{ revert_ts_ = true; }) |
|
revert_ts_ = true;
|
||||||
clipp::option("--no-revert-ts").call([&]{ revert_ts_ = false; })
|
}) |
|
||||||
) % "whether to revert all the .ts files in a repo before pulling to "
|
clipp::option("--no-revert-ts").call([&] {
|
||||||
|
revert_ts_ = false;
|
||||||
|
})) %
|
||||||
|
"whether to revert all the .ts files in a repo before pulling to "
|
||||||
"avoid merge errors; global override",
|
"avoid merge errors; global override",
|
||||||
|
|
||||||
(clipp::option("--ignore-uncommitted-changes") >> ignore_uncommitted_)
|
(clipp::option("--ignore-uncommitted-changes") >> ignore_uncommitted_) %
|
||||||
% "when --reextract is given, directories controlled by git will "
|
"when --reextract is given, directories controlled by git will "
|
||||||
"be deleted even if they contain uncommitted changes",
|
"be deleted even if they contain uncommitted changes",
|
||||||
|
|
||||||
(clipp::option("--keep-msbuild") >> keep_msbuild_)
|
(clipp::option("--keep-msbuild") >> keep_msbuild_) %
|
||||||
% "don't terminate msbuild.exe instances after building",
|
"don't terminate msbuild.exe instances after building",
|
||||||
|
|
||||||
(clipp::opt_values(
|
(clipp::opt_values(clipp::match::prefix_not("-"), "task", tasks_)) %
|
||||||
clipp::match::prefix_not("-"), "task", tasks_))
|
"tasks to run; specify 'super' to only build modorganizer "
|
||||||
% "tasks to run; specify 'super' to only build modorganizer "
|
|
||||||
"projects";
|
"projects";
|
||||||
}
|
}
|
||||||
|
|
||||||
void build_command::convert_cl_to_conf()
|
void build_command::convert_cl_to_conf()
|
||||||
{
|
{
|
||||||
command::convert_cl_to_conf();
|
command::convert_cl_to_conf();
|
||||||
|
|
||||||
if (redownload_ || new_)
|
if (redownload_ || new_)
|
||||||
@@ -107,40 +111,35 @@ void build_command::convert_cl_to_conf()
|
|||||||
if (ignore_uncommitted_)
|
if (ignore_uncommitted_)
|
||||||
common.options.push_back("global/ignore_uncommitted=true");
|
common.options.push_back("global/ignore_uncommitted=true");
|
||||||
|
|
||||||
if (clean_)
|
if (clean_) {
|
||||||
{
|
|
||||||
if (*clean_)
|
if (*clean_)
|
||||||
common.options.push_back("global/clean_task=true");
|
common.options.push_back("global/clean_task=true");
|
||||||
else
|
else
|
||||||
common.options.push_back("global/clean_task=false");
|
common.options.push_back("global/clean_task=false");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fetch_)
|
if (fetch_) {
|
||||||
{
|
|
||||||
if (*fetch_)
|
if (*fetch_)
|
||||||
common.options.push_back("global/fetch_task=true");
|
common.options.push_back("global/fetch_task=true");
|
||||||
else
|
else
|
||||||
common.options.push_back("global/fetch_task=false");
|
common.options.push_back("global/fetch_task=false");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (build_)
|
if (build_) {
|
||||||
{
|
|
||||||
if (*build_)
|
if (*build_)
|
||||||
common.options.push_back("global/build_task=true");
|
common.options.push_back("global/build_task=true");
|
||||||
else
|
else
|
||||||
common.options.push_back("global/build_task=false");
|
common.options.push_back("global/build_task=false");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nopull_)
|
if (nopull_) {
|
||||||
{
|
|
||||||
if (*nopull_)
|
if (*nopull_)
|
||||||
common.options.push_back("_override:task/no_pull=true");
|
common.options.push_back("_override:task/no_pull=true");
|
||||||
else
|
else
|
||||||
common.options.push_back("_override:task/no_pull=false");
|
common.options.push_back("_override:task/no_pull=false");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (revert_ts_)
|
if (revert_ts_) {
|
||||||
{
|
|
||||||
if (*revert_ts_)
|
if (*revert_ts_)
|
||||||
common.options.push_back("_override:task/revert_ts=true");
|
common.options.push_back("_override:task/revert_ts=true");
|
||||||
else
|
else
|
||||||
@@ -149,12 +148,11 @@ void build_command::convert_cl_to_conf()
|
|||||||
|
|
||||||
if (!tasks_.empty())
|
if (!tasks_.empty())
|
||||||
set_task_enabled_flags(tasks_);
|
set_task_enabled_flags(tasks_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int build_command::do_run()
|
int build_command::do_run()
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
create_prefix_ini();
|
create_prefix_ini();
|
||||||
|
|
||||||
task_manager::instance().run_all();
|
task_manager::instance().run_all();
|
||||||
@@ -165,15 +163,14 @@ int build_command::do_run()
|
|||||||
mob::gcx().info(mob::context::generic, "mob done");
|
mob::gcx().info(mob::context::generic, "mob done");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch(bailed&)
|
catch (bailed&) {
|
||||||
{
|
|
||||||
gcx().error(context::generic, "bailing out");
|
gcx().error(context::generic, "bailing out");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void build_command::create_prefix_ini()
|
void build_command::create_prefix_ini()
|
||||||
{
|
{
|
||||||
const auto prefix = conf().path().prefix();
|
const auto prefix = conf().path().prefix();
|
||||||
|
|
||||||
// creating prefix
|
// creating prefix
|
||||||
@@ -181,20 +178,18 @@ void build_command::create_prefix_ini()
|
|||||||
op::create_directories(gcx(), prefix);
|
op::create_directories(gcx(), prefix);
|
||||||
|
|
||||||
const auto ini = prefix / default_ini_filename();
|
const auto ini = prefix / default_ini_filename();
|
||||||
if (!exists(ini))
|
if (!exists(ini)) {
|
||||||
{
|
std::ofstream(ini) << "[paths]\n"
|
||||||
std::ofstream(ini)
|
|
||||||
<< "[paths]\n"
|
|
||||||
<< "prefix = .\n";
|
<< "prefix = .\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void build_command::terminate_msbuild()
|
void build_command::terminate_msbuild()
|
||||||
{
|
{
|
||||||
if (conf().global().dry())
|
if (conf().global().dry())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
system("taskkill /im msbuild.exe /f > NUL 2>&1");
|
system("taskkill /im msbuild.exe /f > NUL 2>&1");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+29
-47
@@ -1,61 +1,44 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "commands.h"
|
|
||||||
#include "../tasks/tasks.h"
|
#include "../tasks/tasks.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
cmake_command::cmake_command()
|
cmake_command::cmake_command() : command(requires_options) {}
|
||||||
: command(requires_options)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
command::meta_t cmake_command::meta() const
|
command::meta_t cmake_command::meta() const
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"cmake",
|
return {"cmake", "runs cmake in a directory"};
|
||||||
"runs cmake in a directory"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group cmake_command::do_group()
|
clipp::group cmake_command::do_group()
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return clipp::group(
|
||||||
clipp::command("cmake").set(picked_),
|
clipp::command("cmake").set(picked_),
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
(clipp::option("-h", "--help") >> help_) % "shows this message",
|
||||||
% "shows this message",
|
|
||||||
|
|
||||||
(clipp::option("-G", "--generator")
|
(clipp::option("-G", "--generator") & clipp::value("GEN") >> gen_) %
|
||||||
& clipp::value("GEN") >> gen_)
|
("sets the -G option for cmake [default: VS]"),
|
||||||
% ("sets the -G option for cmake [default: VS]"),
|
|
||||||
|
|
||||||
(clipp::option("-c", "--cmd")
|
(clipp::option("-c", "--cmd") & clipp::value("CMD") >> cmd_) %
|
||||||
& clipp::value("CMD") >> cmd_)
|
"overrides the cmake command line [default: \"..\"]",
|
||||||
% "overrides the cmake command line [default: \"..\"]",
|
|
||||||
|
|
||||||
(
|
(clipp::option("--x64").set(x64_, true) |
|
||||||
clipp::option("--x64").set(x64_, true) |
|
clipp::option("--x86").set(x64_, false)) %
|
||||||
clipp::option("--x86").set(x64_, false)
|
"whether to use the x64 or x86 vcvars; if -G is not set, "
|
||||||
)
|
|
||||||
% "whether to use the x64 or x86 vcvars; if -G is not set, "
|
|
||||||
"whether to pass \"-A Win32\" or \"-A x64\" for the default "
|
"whether to pass \"-A Win32\" or \"-A x64\" for the default "
|
||||||
"VS generator [default: x64]",
|
"VS generator [default: x64]",
|
||||||
|
|
||||||
(clipp::option("--install-prefix")
|
(clipp::option("--install-prefix") & clipp::value("PATH") >> prefix_) %
|
||||||
& clipp::value("PATH") >> prefix_)
|
"sets CMAKE_INSTALL_PREFIX [default: empty]",
|
||||||
% "sets CMAKE_INSTALL_PREFIX [default: empty]",
|
|
||||||
|
|
||||||
(clipp::value("PATH") >> path_)
|
(clipp::value("PATH") >> path_) % "path from which to run `cmake`");
|
||||||
% "path from which to run `cmake`"
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmake_command::do_run()
|
int cmake_command::do_run()
|
||||||
{
|
{
|
||||||
auto t = tasks::modorganizer::create_cmake_tool(
|
auto t = tasks::modorganizer::create_cmake_tool(fs::path(utf8_to_utf16(path_)));
|
||||||
fs::path(utf8_to_utf16(path_)));
|
|
||||||
|
|
||||||
t.generator(gen_);
|
t.generator(gen_);
|
||||||
t.cmd(cmd_);
|
t.cmd(cmd_);
|
||||||
@@ -71,13 +54,12 @@ int cmake_command::do_run()
|
|||||||
t.run(cxcopy);
|
t.run(cxcopy);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cmake_command::do_doc()
|
std::string cmake_command::do_doc()
|
||||||
{
|
{
|
||||||
return
|
return "Runs `cmake ..` in the given directory with the same command line\n"
|
||||||
"Runs `cmake ..` in the given directory with the same command line\n"
|
|
||||||
"as the one used for modorganizer projects.";
|
"as the one used for modorganizer projects.";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+143
-196
@@ -1,138 +1,119 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "../utility.h"
|
|
||||||
#include "../net.h"
|
|
||||||
#include "../core/conf.h"
|
#include "../core/conf.h"
|
||||||
#include "../core/ini.h"
|
#include "../core/ini.h"
|
||||||
|
#include "../net.h"
|
||||||
#include "../tasks/task_manager.h"
|
#include "../tasks/task_manager.h"
|
||||||
#include "../tools/tools.h"
|
#include "../tools/tools.h"
|
||||||
|
#include "../utility.h"
|
||||||
#include "../utility/threading.h"
|
#include "../utility/threading.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
BOOL WINAPI signal_handler(DWORD) noexcept
|
BOOL WINAPI signal_handler(DWORD) noexcept
|
||||||
{
|
{
|
||||||
// don't use u8cout, this would lock the global mutex, but the handler
|
// don't use u8cout, this would lock the global mutex, but the handler
|
||||||
// can be called while stuff is being output and the mutex is locked
|
// can be called while stuff is being output and the mutex is locked
|
||||||
std::wcout << L"sigint, interrupting...\n";
|
std::wcout << L"sigint, interrupting...\n";
|
||||||
task_manager::instance().interrupt_all();
|
task_manager::instance().interrupt_all();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_sigint_handler()
|
void set_sigint_handler()
|
||||||
{
|
{
|
||||||
::SetConsoleCtrlHandler(mob::signal_handler, TRUE);
|
::SetConsoleCtrlHandler(mob::signal_handler, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void help(const clipp::group& g, const std::string& more)
|
||||||
|
{
|
||||||
|
auto usage_df = clipp::doc_formatting().first_column(4).doc_column(30);
|
||||||
|
|
||||||
void help(const clipp::group& g, const std::string& more)
|
auto options_df = clipp::doc_formatting().first_column(4).doc_column(30);
|
||||||
{
|
|
||||||
auto usage_df = clipp::doc_formatting()
|
|
||||||
.first_column(4)
|
|
||||||
.doc_column(30);
|
|
||||||
|
|
||||||
auto options_df = clipp::doc_formatting()
|
u8cout << "Usage:\n"
|
||||||
.first_column(4)
|
<< clipp::usage_lines(g, "mob", usage_df) << "\n\n"
|
||||||
.doc_column(30);
|
|
||||||
|
|
||||||
u8cout
|
|
||||||
<< "Usage:\n" << clipp::usage_lines(g, "mob", usage_df)
|
|
||||||
<< "\n\n"
|
|
||||||
<< "Options:\n"
|
<< "Options:\n"
|
||||||
<< clipp::documentation(g, options_df)
|
<< clipp::documentation(g, options_df) << "\n\n"
|
||||||
<< "\n\n"
|
|
||||||
<< "To use global options with command options, make sure command \n"
|
<< "To use global options with command options, make sure command \n"
|
||||||
<< "options are together, with no global options in the middle.\n";
|
<< "options are together, with no global options in the middle.\n";
|
||||||
|
|
||||||
if (!more.empty())
|
if (!more.empty())
|
||||||
u8cout << "\n" << more << "\n";
|
u8cout << "\n" << more << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
command::common_options command::common;
|
||||||
|
|
||||||
command::common_options command::common;
|
command::command(flags f) : picked_(false), help_(false), flags_(f), code_() {}
|
||||||
|
|
||||||
command::command(flags f)
|
clipp::group command::common_options_group()
|
||||||
: picked_(false), help_(false), flags_(f), code_()
|
{
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group command::common_options_group()
|
|
||||||
{
|
|
||||||
auto& o = common;
|
auto& o = common;
|
||||||
const auto master = default_ini_filename();
|
const auto master = default_ini_filename();
|
||||||
|
|
||||||
return
|
return (clipp::repeatable(clipp::option("-i", "--ini") &
|
||||||
(clipp::repeatable(clipp::option("-i", "--ini")
|
clipp::value("FILE") >> o.inis)) %
|
||||||
& clipp::value("FILE") >> o.inis))
|
"path to the ini file",
|
||||||
% "path to the ini file",
|
|
||||||
|
|
||||||
(clipp::option("--dry") >> o.dry)
|
(clipp::option("--dry") >> o.dry) % "simulates filesystem operations",
|
||||||
% "simulates filesystem operations",
|
|
||||||
|
|
||||||
(clipp::option("-l", "--log-level")
|
(clipp::option("-l", "--log-level") &
|
||||||
& clipp::value("LEVEL") >> o.output_log_level)
|
clipp::value("LEVEL") >> o.output_log_level) %
|
||||||
% "0 is silent, 6 is max",
|
"0 is silent, 6 is max",
|
||||||
|
|
||||||
(clipp::option("--file-log-level")
|
(clipp::option("--file-log-level") &
|
||||||
& clipp::value("LEVEL") >> o.file_log_level)
|
clipp::value("LEVEL") >> o.file_log_level) %
|
||||||
% "overrides --log-level for the log file",
|
"overrides --log-level for the log file",
|
||||||
|
|
||||||
(clipp::option("--log-file")
|
(clipp::option("--log-file") & clipp::value("FILE") >> o.log_file) %
|
||||||
& clipp::value("FILE") >> o.log_file)
|
"path to log file",
|
||||||
% "path to log file",
|
|
||||||
|
|
||||||
(clipp::option("-d", "--destination")
|
(clipp::option("-d", "--destination") &
|
||||||
& clipp::value("DIR") >> o.prefix)
|
clipp::value("DIR") >> o.prefix) %
|
||||||
% ("base output directory, will contain build/, install/, etc."),
|
("base output directory, will contain build/, install/, etc."),
|
||||||
|
|
||||||
(clipp::repeatable(clipp::option("-s", "--set")
|
(clipp::repeatable(clipp::option("-s", "--set") &
|
||||||
& clipp::value("OPTION", o.options)))
|
clipp::value("OPTION", o.options))) %
|
||||||
% "sets an option, such as 'versions/openssl=1.2'",
|
"sets an option, such as 'versions/openssl=1.2'",
|
||||||
|
|
||||||
(clipp::option("--no-default-inis") >> o.no_default_inis)
|
(clipp::option("--no-default-inis") >> o.no_default_inis) %
|
||||||
% "disables auto loading of ini files, only uses --ini; the first "
|
"disables auto loading of ini files, only uses --ini; the first "
|
||||||
"--ini must be the master ini file";
|
"--ini must be the master ini file";
|
||||||
}
|
}
|
||||||
|
|
||||||
void command::force_exit_code(int code)
|
void command::force_exit_code(int code)
|
||||||
{
|
{
|
||||||
code_ = code;
|
code_ = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void command::force_help()
|
void command::force_help()
|
||||||
{
|
{
|
||||||
help_ = true;
|
help_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool command::picked() const
|
bool command::picked() const
|
||||||
{
|
{
|
||||||
return picked_;
|
return picked_;
|
||||||
}
|
}
|
||||||
|
|
||||||
clipp::group command::group()
|
clipp::group command::group()
|
||||||
{
|
{
|
||||||
return do_group();
|
return do_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
void command::convert_cl_to_conf()
|
void command::convert_cl_to_conf()
|
||||||
{
|
{
|
||||||
auto& o = common;
|
auto& o = common;
|
||||||
|
|
||||||
if (o.file_log_level == -1)
|
if (o.file_log_level == -1)
|
||||||
o.file_log_level = o.output_log_level;
|
o.file_log_level = o.output_log_level;
|
||||||
|
|
||||||
if (o.output_log_level >= 0)
|
if (o.output_log_level >= 0) {
|
||||||
{
|
o.options.push_back("global/output_log_level=" +
|
||||||
o.options.push_back(
|
|
||||||
"global/output_log_level=" +
|
|
||||||
std::to_string(o.output_log_level));
|
std::to_string(o.output_log_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o.file_log_level > 0)
|
if (o.file_log_level > 0) {
|
||||||
{
|
o.options.push_back("global/file_log_level=" +
|
||||||
o.options.push_back(
|
|
||||||
"global/file_log_level=" +
|
|
||||||
std::to_string(o.file_log_level));
|
std::to_string(o.file_log_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,34 +125,30 @@ void command::convert_cl_to_conf()
|
|||||||
|
|
||||||
if (!o.prefix.empty())
|
if (!o.prefix.empty())
|
||||||
o.options.push_back("paths/prefix=" + o.prefix);
|
o.options.push_back("paths/prefix=" + o.prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command::gather_inis(bool verbose)
|
int command::gather_inis(bool verbose)
|
||||||
{
|
{
|
||||||
auto& o = common;
|
auto& o = common;
|
||||||
|
|
||||||
if (o.no_default_inis && o.inis.empty())
|
if (o.no_default_inis && o.inis.empty()) {
|
||||||
{
|
u8cerr << "--no-default-inis requires at least one --ini for the "
|
||||||
u8cerr
|
|
||||||
<< "--no-default-inis requires at least one --ini for the "
|
|
||||||
<< "master ini file\n";
|
<< "master ini file\n";
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
inis_ = find_inis(!o.no_default_inis, o.inis, verbose);
|
inis_ = find_inis(!o.no_default_inis, o.inis, verbose);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch(bailed&)
|
catch (bailed&) {
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void command::set_task_enabled_flags(const std::vector<std::string>& names)
|
void command::set_task_enabled_flags(const std::vector<std::string>& names)
|
||||||
{
|
{
|
||||||
common.options.push_back("task/enabled=false");
|
common.options.push_back("task/enabled=false");
|
||||||
|
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
@@ -181,24 +158,22 @@ void command::set_task_enabled_flags(const std::vector<std::string>& names)
|
|||||||
|
|
||||||
if (failed)
|
if (failed)
|
||||||
throw bailed();
|
throw bailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
int command::prepare_options(bool verbose)
|
int command::prepare_options(bool verbose)
|
||||||
{
|
{
|
||||||
convert_cl_to_conf();
|
convert_cl_to_conf();
|
||||||
return gather_inis(verbose);
|
return gather_inis(verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
int command::run()
|
int command::run()
|
||||||
{
|
|
||||||
if (help_)
|
|
||||||
{
|
{
|
||||||
|
if (help_) {
|
||||||
help(group(), do_doc());
|
help(group(), do_doc());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags_ & requires_options)
|
if (flags_ & requires_options) {
|
||||||
{
|
|
||||||
const auto r = load_options();
|
const auto r = load_options();
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
@@ -213,10 +188,10 @@ int command::run()
|
|||||||
return *code_;
|
return *code_;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int command::load_options()
|
int command::load_options()
|
||||||
{
|
{
|
||||||
const int r = prepare_options(false);
|
const int r = prepare_options(false);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
@@ -230,66 +205,53 @@ int command::load_options()
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
command::meta_t version_command::meta() const
|
||||||
command::meta_t version_command::meta() const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"version",
|
return {"version", "shows the version"};
|
||||||
"shows the version"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group version_command::do_group()
|
clipp::group version_command::do_group()
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return clipp::group(clipp::command("version", "-v", "--version").set(picked_));
|
||||||
clipp::command("version", "-v", "--version").set(picked_));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int version_command::do_run()
|
int version_command::do_run()
|
||||||
{
|
{
|
||||||
u8cout << mob_version() << "\n";
|
u8cout << mob_version() << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
command::meta_t help_command::meta() const
|
||||||
command::meta_t help_command::meta() const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"help",
|
return {"help", "shows this message"};
|
||||||
"shows this message"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void help_command::set_commands(const std::vector<std::shared_ptr<command>>& v)
|
void help_command::set_commands(const std::vector<std::shared_ptr<command>>& v)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, std::string>> s;
|
std::vector<std::pair<std::string, std::string>> s;
|
||||||
|
|
||||||
for (auto&& c : v)
|
for (auto&& c : v)
|
||||||
s.push_back({c->meta().name, c->meta().description});
|
s.push_back({c->meta().name, c->meta().description});
|
||||||
|
|
||||||
commands_ = table(s, 4, 3);
|
commands_ = table(s, 4, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
clipp::group help_command::do_group()
|
clipp::group help_command::do_group()
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return clipp::group(clipp::command("-h", "--help").set(picked_));
|
||||||
clipp::command("-h", "--help").set(picked_));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int help_command::do_run()
|
int help_command::do_run()
|
||||||
{
|
{
|
||||||
#pragma warning(suppress: 4548)
|
#pragma warning(suppress : 4548)
|
||||||
auto doc = (command::common_options_group(), (clipp::value("command")));
|
auto doc = (command::common_options_group(), (clipp::value("command")));
|
||||||
|
|
||||||
const auto master = default_ini_filename();
|
const auto master = default_ini_filename();
|
||||||
|
|
||||||
help(doc,
|
help(doc,
|
||||||
"Commands:\n"
|
"Commands:\n" + commands_ +
|
||||||
+ commands_ +
|
|
||||||
"\n\n"
|
"\n\n"
|
||||||
"Invoking `mob -d some/prefix build` builds everything. Do \n"
|
"Invoking `mob -d some/prefix build` builds everything. Do \n"
|
||||||
"`mob build <task name>...` to build specific tasks. See\n"
|
"`mob build <task name>...` to build specific tasks. See\n"
|
||||||
@@ -297,7 +259,9 @@ int help_command::do_run()
|
|||||||
"\n"
|
"\n"
|
||||||
"INI files\n"
|
"INI files\n"
|
||||||
"\n"
|
"\n"
|
||||||
"By default, mob will look for a master INI `" + master + "` in the \n"
|
"By default, mob will look for a master INI `" +
|
||||||
|
master +
|
||||||
|
"` in the \n"
|
||||||
"root directory (typically where mob.exe resides). Once mob has\n"
|
"root directory (typically where mob.exe resides). Once mob has\n"
|
||||||
"found the master INI, it will look for the same filename in the\n"
|
"found the master INI, it will look for the same filename in the\n"
|
||||||
"current directory, if different from the root. If found, both will\n"
|
"current directory, if different from the root. If found, both will\n"
|
||||||
@@ -307,74 +271,57 @@ int help_command::do_run()
|
|||||||
"disable auto detection and only use --ini.");
|
"disable auto detection and only use --ini.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options_command::options_command() : command(requires_options) {}
|
||||||
|
|
||||||
options_command::options_command()
|
command::meta_t options_command::meta() const
|
||||||
: command(requires_options)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
command::meta_t options_command::meta() const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"options",
|
return {"options", "lists all options and their values from the inis"};
|
||||||
"lists all options and their values from the inis"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group options_command::do_group()
|
clipp::group options_command::do_group()
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return clipp::group(clipp::command("options").set(picked_),
|
||||||
clipp::command("options").set(picked_),
|
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
(clipp::option("-h", "--help") >> help_) %
|
||||||
% ("shows this message")
|
("shows this message"));
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int options_command::do_run()
|
int options_command::do_run()
|
||||||
{
|
{
|
||||||
for (auto&& line : format_options())
|
for (auto&& line : format_options())
|
||||||
u8cout << line << "\n";
|
u8cout << line << "\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string options_command::do_doc()
|
std::string options_command::do_doc()
|
||||||
{
|
|
||||||
return "Lists the final value of all options found by loading the INIs.";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
command::meta_t inis_command::meta() const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"inis",
|
return "Lists the final value of all options found by loading the INIs.";
|
||||||
"lists the INIs used by mob"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group inis_command::do_group()
|
command::meta_t inis_command::meta() const
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return {"inis", "lists the INIs used by mob"};
|
||||||
clipp::command("inis").set(picked_),
|
}
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
clipp::group inis_command::do_group()
|
||||||
% ("shows this message")
|
{
|
||||||
);
|
return clipp::group(clipp::command("inis").set(picked_),
|
||||||
}
|
|
||||||
|
|
||||||
int inis_command::do_run()
|
(clipp::option("-h", "--help") >> help_) %
|
||||||
{
|
("shows this message"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int inis_command::do_run()
|
||||||
|
{
|
||||||
return prepare_options(true);
|
return prepare_options(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string inis_command::do_doc()
|
std::string inis_command::do_doc()
|
||||||
{
|
{
|
||||||
return "Shows which INIs are found.";
|
return "Shows which INIs are found.";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+104
-160
@@ -2,26 +2,22 @@
|
|||||||
|
|
||||||
#include "../utility/enum.h"
|
#include "../utility/enum.h"
|
||||||
|
|
||||||
namespace mob::tasks
|
namespace mob::tasks {
|
||||||
{
|
|
||||||
class modorganizer;
|
class modorganizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
class task;
|
class task;
|
||||||
class url;
|
class url;
|
||||||
|
|
||||||
// base class for all commands
|
// base class for all commands
|
||||||
//
|
//
|
||||||
class command
|
class command {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// values of options available for all commands
|
// values of options available for all commands
|
||||||
//
|
//
|
||||||
struct common_options
|
struct common_options {
|
||||||
{
|
|
||||||
bool dry = false;
|
bool dry = false;
|
||||||
int output_log_level = -1;
|
int output_log_level = -1;
|
||||||
int file_log_level = -1;
|
int file_log_level = -1;
|
||||||
@@ -35,12 +31,10 @@ public:
|
|||||||
|
|
||||||
// returned by meta() by each command
|
// returned by meta() by each command
|
||||||
//
|
//
|
||||||
struct meta_t
|
struct meta_t {
|
||||||
{
|
|
||||||
std::string name, description;
|
std::string name, description;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static common_options common;
|
static common_options common;
|
||||||
static clipp::group common_options_group();
|
static clipp::group common_options_group();
|
||||||
|
|
||||||
@@ -66,16 +60,14 @@ public:
|
|||||||
//
|
//
|
||||||
int run();
|
int run();
|
||||||
|
|
||||||
|
|
||||||
// returns meta information about this command
|
// returns meta information about this command
|
||||||
//
|
//
|
||||||
virtual meta_t meta() const = 0;
|
virtual meta_t meta() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// passed by derived classes in the constructor
|
// passed by derived classes in the constructor
|
||||||
//
|
//
|
||||||
enum flags
|
enum flags {
|
||||||
{
|
|
||||||
noflags = 0x00,
|
noflags = 0x00,
|
||||||
|
|
||||||
// this command needs the ini loaded before running
|
// this command needs the ini loaded before running
|
||||||
@@ -87,15 +79,13 @@ protected:
|
|||||||
|
|
||||||
MOB_ENUM_FRIEND_OPERATORS(flags);
|
MOB_ENUM_FRIEND_OPERATORS(flags);
|
||||||
|
|
||||||
|
|
||||||
// set to true when this command is entered by the user
|
// set to true when this command is entered by the user
|
||||||
bool picked_;
|
bool picked_;
|
||||||
|
|
||||||
// set to true with --help or by force_help()
|
// set to true with --help or by force_help()
|
||||||
bool help_;
|
bool help_;
|
||||||
|
|
||||||
|
command(flags f = noflags);
|
||||||
command(flags f=noflags);
|
|
||||||
|
|
||||||
// some options have a unique version on the command line because they're
|
// some options have a unique version on the command line because they're
|
||||||
// used often, such as --dry or -l; those are converted to their ini
|
// used often, such as --dry or -l; those are converted to their ini
|
||||||
@@ -130,7 +120,7 @@ protected:
|
|||||||
//
|
//
|
||||||
virtual std::string do_doc() { return {}; }
|
virtual std::string do_doc() { return {}; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// flags requested by this command
|
// flags requested by this command
|
||||||
flags flags_;
|
flags flags_;
|
||||||
|
|
||||||
@@ -140,63 +130,54 @@ private:
|
|||||||
// list of inis found by gather_inis()
|
// list of inis found by gather_inis()
|
||||||
std::vector<fs::path> inis_;
|
std::vector<fs::path> inis_;
|
||||||
|
|
||||||
|
|
||||||
// finds all the inis
|
// finds all the inis
|
||||||
//
|
//
|
||||||
int gather_inis(bool verbose);
|
int gather_inis(bool verbose);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// displays mob's version
|
||||||
// displays mob's version
|
//
|
||||||
//
|
class version_command : public command {
|
||||||
class version_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// displays the usage, list of commands and some additional text
|
||||||
// displays the usage, list of commands and some additional text
|
//
|
||||||
//
|
class help_command : public command {
|
||||||
class help_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
void set_commands(const std::vector<std::shared_ptr<command>>& v);
|
void set_commands(const std::vector<std::shared_ptr<command>>& v);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string commands_;
|
std::string commands_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// lists all options and their values
|
||||||
// lists all options and their values
|
//
|
||||||
//
|
class options_command : public command {
|
||||||
class options_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
options_command();
|
options_command();
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
std::string do_doc() override;
|
std::string do_doc() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// builds stuff
|
||||||
// builds stuff
|
//
|
||||||
//
|
class build_command : public command {
|
||||||
class build_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
build_command();
|
build_command();
|
||||||
|
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
@@ -205,12 +186,12 @@ public:
|
|||||||
//
|
//
|
||||||
static void terminate_msbuild();
|
static void terminate_msbuild();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void convert_cl_to_conf() override;
|
void convert_cl_to_conf() override;
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> tasks_;
|
std::vector<std::string> tasks_;
|
||||||
bool redownload_ = false;
|
bool redownload_ = false;
|
||||||
bool reextract_ = false;
|
bool reextract_ = false;
|
||||||
@@ -225,85 +206,75 @@ private:
|
|||||||
bool keep_msbuild_ = false;
|
bool keep_msbuild_ = false;
|
||||||
std::optional<bool> revert_ts_;
|
std::optional<bool> revert_ts_;
|
||||||
|
|
||||||
|
|
||||||
// creates a bare bones ini file in the prefix so mob can be invoked in any
|
// creates a bare bones ini file in the prefix so mob can be invoked in any
|
||||||
// directory below it
|
// directory below it
|
||||||
//
|
//
|
||||||
void create_prefix_ini();
|
void create_prefix_ini();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// applies a pr
|
||||||
// applies a pr
|
//
|
||||||
//
|
class pr_command : public command {
|
||||||
class pr_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
pr_command();
|
pr_command();
|
||||||
|
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
std::string do_doc() override;
|
std::string do_doc() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct pr_info
|
struct pr_info {
|
||||||
{
|
|
||||||
std::string repo, author, branch, title, number;
|
std::string repo, author, branch, title, number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
std::string op_;
|
std::string op_;
|
||||||
std::string pr_;
|
std::string pr_;
|
||||||
std::string github_token_;
|
std::string github_token_;
|
||||||
|
|
||||||
std::pair<const tasks::modorganizer*, std::string> parse_pr(
|
std::pair<const tasks::modorganizer*, std::string>
|
||||||
const std::string& pr) const;
|
parse_pr(const std::string& pr) const;
|
||||||
|
|
||||||
pr_info get_pr_info(const tasks::modorganizer* task, const std::string& pr);
|
pr_info get_pr_info(const tasks::modorganizer* task, const std::string& pr);
|
||||||
|
|
||||||
std::vector<pr_command::pr_info> get_matching_prs(
|
std::vector<pr_command::pr_info> get_matching_prs(const std::string& repo_pr);
|
||||||
const std::string& repo_pr);
|
|
||||||
|
|
||||||
std::vector<pr_info> search_prs(
|
std::vector<pr_info> search_prs(const std::string& org,
|
||||||
const std::string& org,
|
const std::string& author,
|
||||||
const std::string& author, const std::string& branch);
|
const std::string& branch);
|
||||||
|
|
||||||
std::vector<pr_info> validate_prs(const std::vector<pr_info>& prs);
|
std::vector<pr_info> validate_prs(const std::vector<pr_info>& prs);
|
||||||
|
|
||||||
int pull();
|
int pull();
|
||||||
int find();
|
int find();
|
||||||
int revert();
|
int revert();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// lists available tasks
|
||||||
// lists available tasks
|
//
|
||||||
//
|
class list_command : public command {
|
||||||
class list_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool all_ = false;
|
bool all_ = false;
|
||||||
bool aliases_ = false;
|
bool aliases_ = false;
|
||||||
std::vector<std::string> tasks_;
|
std::vector<std::string> tasks_;
|
||||||
|
|
||||||
void dump(const std::vector<task*>& v, std::size_t indent) const;
|
void dump(const std::vector<task*>& v, std::size_t indent) const;
|
||||||
void dump_aliases() const;
|
void dump_aliases() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// creates a devbuild or an official release
|
||||||
// creates a devbuild or an official release
|
//
|
||||||
//
|
class release_command : public command {
|
||||||
class release_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
release_command();
|
release_command();
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
@@ -313,22 +284,16 @@ public:
|
|||||||
void make_uibase();
|
void make_uibase();
|
||||||
void make_installer();
|
void make_installer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
std::string do_doc() override;
|
std::string do_doc() override;
|
||||||
void convert_cl_to_conf() override;
|
void convert_cl_to_conf() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class modes
|
enum class modes { none = 0, devbuild, official };
|
||||||
{
|
|
||||||
none = 0,
|
|
||||||
devbuild,
|
|
||||||
official
|
|
||||||
};
|
|
||||||
|
|
||||||
|
modes mode_ = modes::none;
|
||||||
modes mode_= modes::none;
|
|
||||||
bool bin_ = true;
|
bool bin_ = true;
|
||||||
bool src_ = true;
|
bool src_ = true;
|
||||||
bool pdbs_ = true;
|
bool pdbs_ = true;
|
||||||
@@ -345,7 +310,6 @@ private:
|
|||||||
std::string suffix_;
|
std::string suffix_;
|
||||||
std::string branch_;
|
std::string branch_;
|
||||||
|
|
||||||
|
|
||||||
int do_devbuild();
|
int do_devbuild();
|
||||||
int do_official();
|
int do_official();
|
||||||
|
|
||||||
@@ -355,37 +319,28 @@ private:
|
|||||||
|
|
||||||
fs::path make_filename(const std::string& what) const;
|
fs::path make_filename(const std::string& what) const;
|
||||||
|
|
||||||
void walk_dir(
|
void walk_dir(const fs::path& dir, std::vector<fs::path>& files,
|
||||||
const fs::path& dir, std::vector<fs::path>& files,
|
const std::vector<std::regex>& ignore_re,
|
||||||
const std::vector<std::regex>& ignore_re, std::size_t& total_size);
|
std::size_t& total_size);
|
||||||
|
|
||||||
std::string version_from_exe() const;
|
std::string version_from_exe() const;
|
||||||
std::string version_from_rc() const;
|
std::string version_from_rc() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// manages git repos
|
||||||
// manages git repos
|
//
|
||||||
//
|
class git_command : public command {
|
||||||
class git_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
git_command();
|
git_command();
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
std::string do_doc() override;
|
std::string do_doc() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class modes
|
enum class modes { none = 0, set_remotes, add_remote, ignore_ts, branches };
|
||||||
{
|
|
||||||
none = 0,
|
|
||||||
set_remotes,
|
|
||||||
add_remote,
|
|
||||||
ignore_ts,
|
|
||||||
branches
|
|
||||||
};
|
|
||||||
|
|
||||||
modes mode_ = modes::none;
|
modes mode_ = modes::none;
|
||||||
std::string username_;
|
std::string username_;
|
||||||
@@ -410,66 +365,55 @@ private:
|
|||||||
void do_branches();
|
void do_branches();
|
||||||
|
|
||||||
std::vector<fs::path> get_repos() const;
|
std::vector<fs::path> get_repos() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// runs cmake in a directory with the same parameters as `build` would
|
||||||
// runs cmake in a directory with the same parameters as `build` would
|
//
|
||||||
//
|
class cmake_command : public command {
|
||||||
class cmake_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
cmake_command();
|
cmake_command();
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
std::string do_doc() override;
|
std::string do_doc() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string gen_;
|
std::string gen_;
|
||||||
std::string cmd_;
|
std::string cmd_;
|
||||||
bool x64_ = true;
|
bool x64_ = true;
|
||||||
std::string prefix_;
|
std::string prefix_;
|
||||||
std::string path_;
|
std::string path_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// lists the inis found by mob
|
||||||
// lists the inis found by mob
|
//
|
||||||
//
|
class inis_command : public command {
|
||||||
class inis_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
std::string do_doc() override;
|
std::string do_doc() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// manages transifex
|
||||||
// manages transifex
|
//
|
||||||
//
|
class tx_command : public command {
|
||||||
class tx_command : public command
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
tx_command();
|
tx_command();
|
||||||
meta_t meta() const override;
|
meta_t meta() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
clipp::group do_group() override;
|
clipp::group do_group() override;
|
||||||
void convert_cl_to_conf() override;
|
void convert_cl_to_conf() override;
|
||||||
int do_run() override;
|
int do_run() override;
|
||||||
std::string do_doc() override;
|
std::string do_doc() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class modes
|
enum class modes { none = 0, get, build };
|
||||||
{
|
|
||||||
none = 0,
|
|
||||||
get,
|
|
||||||
build
|
|
||||||
};
|
|
||||||
|
|
||||||
modes mode_ = modes::none;
|
modes mode_ = modes::none;
|
||||||
std::string key_, team_, project_, url_;
|
std::string key_, team_, project_, url_;
|
||||||
@@ -480,6 +424,6 @@ private:
|
|||||||
|
|
||||||
void do_get();
|
void do_get();
|
||||||
void do_build();
|
void do_build();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+87
-125
@@ -1,125 +1,98 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "commands.h"
|
|
||||||
#include "../tasks/tasks.h"
|
#include "../tasks/tasks.h"
|
||||||
#include "../tools/tools.h"
|
#include "../tools/tools.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
git_command::git_command()
|
git_command::git_command() : command(requires_options) {}
|
||||||
: command(requires_options)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
command::meta_t git_command::meta() const
|
command::meta_t git_command::meta() const
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"git",
|
return {"git", "manages the git repos"};
|
||||||
"manages the git repos"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group git_command::do_group()
|
clipp::group git_command::do_group()
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return clipp::group(
|
||||||
clipp::command("git").set(picked_),
|
clipp::command("git").set(picked_),
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
(clipp::option("-h", "--help") >> help_) % ("shows this message"),
|
||||||
% ("shows this message"),
|
|
||||||
|
|
||||||
"set-remotes" %
|
"set-remotes" %
|
||||||
(clipp::command("set-remotes").set(mode_, modes::set_remotes),
|
(clipp::command("set-remotes").set(mode_, modes::set_remotes),
|
||||||
(clipp::required("-u", "--username")
|
(clipp::required("-u", "--username") &
|
||||||
& clipp::value("USERNAME") >> username_)
|
clipp::value("USERNAME") >> username_) %
|
||||||
% "git username",
|
"git username",
|
||||||
|
|
||||||
(clipp::required("-e", "--email")
|
(clipp::required("-e", "--email") &
|
||||||
& clipp::value("EMAIL") >> email_)
|
clipp::value("EMAIL") >> email_) %
|
||||||
% "git email",
|
"git email",
|
||||||
|
|
||||||
(clipp::option("-k", "--key")
|
(clipp::option("-k", "--key") & clipp::value("PATH") >> key_) %
|
||||||
& clipp::value("PATH") >> key_)
|
"path to putty key",
|
||||||
% "path to putty key",
|
|
||||||
|
|
||||||
(clipp::option("-s", "--no-push").set(nopush_)
|
(clipp::option("-s", "--no-push").set(nopush_) %
|
||||||
% "disables pushing to 'upstream' by changing the push url "
|
"disables pushing to 'upstream' by changing the push url "
|
||||||
"to 'nopushurl' to avoid accidental pushes"),
|
"to 'nopushurl' to avoid accidental pushes"),
|
||||||
|
|
||||||
(clipp::option("-p", "--push-origin").set(push_default_)
|
(clipp::option("-p", "--push-origin").set(push_default_) %
|
||||||
% "sets the new 'origin' remote as the default push target"),
|
"sets the new 'origin' remote as the default push target"),
|
||||||
|
|
||||||
(clipp::opt_value("path") >> path_)
|
(clipp::opt_value("path") >> path_) % "only use this repo")
|
||||||
% "only use this repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
|
|
||||||
|
|
||||||
"add-remote" %
|
"add-remote" %
|
||||||
(clipp::command("add-remote").set(mode_, modes::add_remote),
|
(clipp::command("add-remote").set(mode_, modes::add_remote),
|
||||||
(clipp::required("-n", "--name")
|
(clipp::required("-n", "--name") &
|
||||||
& clipp::value("NAME") >> remote_)
|
clipp::value("NAME") >> remote_) %
|
||||||
% "name of new remote",
|
"name of new remote",
|
||||||
|
|
||||||
(clipp::required("-u", "--username")
|
(clipp::required("-u", "--username") &
|
||||||
& clipp::value("USERNAME") >> username_)
|
clipp::value("USERNAME") >> username_) %
|
||||||
% "git username",
|
"git username",
|
||||||
|
|
||||||
(clipp::option("-k", "--key")
|
(clipp::option("-k", "--key") & clipp::value("PATH") >> key_) %
|
||||||
& clipp::value("PATH") >> key_)
|
"path to putty key",
|
||||||
% "path to putty key",
|
|
||||||
|
|
||||||
(clipp::option("-p", "--push-origin").set(push_default_)
|
(clipp::option("-p", "--push-origin").set(push_default_) %
|
||||||
% "sets this new remote as the default push target"),
|
"sets this new remote as the default push target"),
|
||||||
|
|
||||||
(clipp::opt_value("path") >> path_)
|
(clipp::opt_value("path") >> path_) % "only use this repo")
|
||||||
% "only use this repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
|
|
||||||
|
|
||||||
"ignore-ts" %
|
"ignore-ts" % (clipp::command("ignore-ts").set(mode_, modes::ignore_ts),
|
||||||
(clipp::command("ignore-ts").set(mode_, modes::ignore_ts),
|
(clipp::command("on").set(tson_, true) |
|
||||||
(
|
clipp::command("off").set(tson_, false)))
|
||||||
clipp::command("on").set(tson_, true) |
|
|
||||||
clipp::command("off").set(tson_, false)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
|
|
||||||
|
|
||||||
"branches" %
|
"branches" % (clipp::command("branches").set(mode_, modes::branches),
|
||||||
(clipp::command("branches").set(mode_, modes::branches),
|
clipp::option("-a", "--all").set(all_branches_) %
|
||||||
clipp::option("-a", "--all").set(all_branches_)
|
"shows all branches, including those on master"));
|
||||||
% "shows all branches, including those on master"
|
}
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
int git_command::do_run()
|
int git_command::do_run()
|
||||||
{
|
|
||||||
switch (mode_)
|
|
||||||
{
|
|
||||||
case modes::set_remotes:
|
|
||||||
{
|
{
|
||||||
|
switch (mode_) {
|
||||||
|
case modes::set_remotes: {
|
||||||
do_set_remotes();
|
do_set_remotes();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case modes::add_remote:
|
case modes::add_remote: {
|
||||||
{
|
|
||||||
do_add_remote();
|
do_add_remote();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case modes::ignore_ts:
|
case modes::ignore_ts: {
|
||||||
{
|
|
||||||
do_ignore_ts();
|
do_ignore_ts();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case modes::branches:
|
case modes::branches: {
|
||||||
{
|
|
||||||
do_branches();
|
do_branches();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -131,12 +104,11 @@ int git_command::do_run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string git_command::do_doc()
|
std::string git_command::do_doc()
|
||||||
{
|
{
|
||||||
return
|
return "All the commands will go through all modorganizer repos, plus usvfs\n"
|
||||||
"All the commands will go through all modorganizer repos, plus usvfs\n"
|
|
||||||
"and NCC.\n"
|
"and NCC.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Commands:\n"
|
"Commands:\n"
|
||||||
@@ -156,90 +128,82 @@ std::string git_command::do_doc()
|
|||||||
"branches\n"
|
"branches\n"
|
||||||
" Lists all git repos that are not on master. With -a, show all \n"
|
" Lists all git repos that are not on master. With -a, show all \n"
|
||||||
" repos and their current branch.";
|
" repos and their current branch.";
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_command::do_set_remotes()
|
void git_command::do_set_remotes()
|
||||||
{
|
|
||||||
if (path_.empty())
|
|
||||||
{
|
{
|
||||||
|
if (path_.empty()) {
|
||||||
const auto repos = get_repos();
|
const auto repos = get_repos();
|
||||||
|
|
||||||
for (auto&& r : repos)
|
for (auto&& r : repos)
|
||||||
do_set_remotes(r);
|
do_set_remotes(r);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
do_set_remotes(path_);
|
do_set_remotes(path_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_command::do_set_remotes(const fs::path& r)
|
void git_command::do_set_remotes(const fs::path& r)
|
||||||
{
|
{
|
||||||
u8cout << "setting up " << path_to_utf8(r.filename()) << "\n";
|
u8cout << "setting up " << path_to_utf8(r.filename()) << "\n";
|
||||||
|
|
||||||
git_wrap(r).set_credentials(username_, email_);
|
git_wrap(r).set_credentials(username_, email_);
|
||||||
|
|
||||||
git_wrap(r).set_origin_and_upstream_remotes(
|
git_wrap(r).set_origin_and_upstream_remotes(username_, key_, nopush_,
|
||||||
username_, key_, nopush_, push_default_);
|
push_default_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_command::do_add_remote()
|
void git_command::do_add_remote()
|
||||||
{
|
{
|
||||||
u8cout
|
u8cout << "adding remote '" << remote_ << "' "
|
||||||
<< "adding remote '" << remote_ << "' "
|
|
||||||
<< "from '" << username_ << "' to repos\n";
|
<< "from '" << username_ << "' to repos\n";
|
||||||
|
|
||||||
if (path_.empty())
|
if (path_.empty()) {
|
||||||
{
|
|
||||||
const auto repos = get_repos();
|
const auto repos = get_repos();
|
||||||
|
|
||||||
for (auto&& r : repos)
|
for (auto&& r : repos)
|
||||||
do_add_remote(r);
|
do_add_remote(r);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
do_add_remote(path_);
|
do_add_remote(path_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_command::do_add_remote(const fs::path& r)
|
void git_command::do_add_remote(const fs::path& r)
|
||||||
{
|
{
|
||||||
u8cout << path_to_utf8(r.filename()) << "\n";
|
u8cout << path_to_utf8(r.filename()) << "\n";
|
||||||
git_wrap(r).add_remote(remote_, username_, key_, push_default_);
|
git_wrap(r).add_remote(remote_, username_, key_, push_default_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_command::do_ignore_ts()
|
void git_command::do_ignore_ts()
|
||||||
{
|
{
|
||||||
if (tson_)
|
if (tson_)
|
||||||
u8cout << "ignoring .ts files\n";
|
u8cout << "ignoring .ts files\n";
|
||||||
else
|
else
|
||||||
u8cout << "un-ignoring .ts files\n";
|
u8cout << "un-ignoring .ts files\n";
|
||||||
|
|
||||||
if (path_.empty())
|
if (path_.empty()) {
|
||||||
{
|
|
||||||
const auto repos = get_repos();
|
const auto repos = get_repos();
|
||||||
|
|
||||||
for (auto&& r : repos)
|
for (auto&& r : repos)
|
||||||
do_ignore_ts(r);
|
do_ignore_ts(r);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
do_ignore_ts(path_);
|
do_ignore_ts(path_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_command::do_ignore_ts(const fs::path& r)
|
void git_command::do_ignore_ts(const fs::path& r)
|
||||||
{
|
{
|
||||||
u8cout << path_to_utf8(r.filename()) << "\n";
|
u8cout << path_to_utf8(r.filename()) << "\n";
|
||||||
git_wrap(r).ignore_ts(tson_);
|
git_wrap(r).ignore_ts(tson_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_command::do_branches()
|
void git_command::do_branches()
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, std::string>> v;
|
std::vector<std::pair<std::string, std::string>> v;
|
||||||
|
|
||||||
for (auto&& r : get_repos())
|
for (auto&& r : get_repos()) {
|
||||||
{
|
|
||||||
const auto b = git_wrap(r).current_branch();
|
const auto b = git_wrap(r).current_branch();
|
||||||
if (b == "master" && !all_branches_)
|
if (b == "master" && !all_branches_)
|
||||||
continue;
|
continue;
|
||||||
@@ -251,10 +215,10 @@ void git_command::do_branches()
|
|||||||
}
|
}
|
||||||
|
|
||||||
u8cout << table(v, 0, 3) << "\n";
|
u8cout << table(v, 0, 3) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<fs::path> git_command::get_repos() const
|
std::vector<fs::path> git_command::get_repos() const
|
||||||
{
|
{
|
||||||
std::vector<fs::path> v;
|
std::vector<fs::path> v;
|
||||||
|
|
||||||
// usvfs
|
// usvfs
|
||||||
@@ -264,10 +228,8 @@ std::vector<fs::path> git_command::get_repos() const
|
|||||||
const auto super = tasks::modorganizer::super_path();
|
const auto super = tasks::modorganizer::super_path();
|
||||||
|
|
||||||
// all directories in super except for those starting with a dot
|
// all directories in super except for those starting with a dot
|
||||||
if (fs::exists(super))
|
if (fs::exists(super)) {
|
||||||
{
|
for (auto e : fs::directory_iterator(super)) {
|
||||||
for (auto e : fs::directory_iterator(super))
|
|
||||||
{
|
|
||||||
if (!e.is_directory())
|
if (!e.is_directory())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -280,6 +242,6 @@ std::vector<fs::path> git_command::get_repos() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+32
-49
@@ -1,55 +1,43 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "commands.h"
|
|
||||||
#include "../tasks/task_manager.h"
|
|
||||||
#include "../tasks/task.h"
|
#include "../tasks/task.h"
|
||||||
|
#include "../tasks/task_manager.h"
|
||||||
#include "../utility/io.h"
|
#include "../utility/io.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
command::meta_t list_command::meta() const
|
command::meta_t list_command::meta() const
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"list",
|
return {"list", "lists available tasks"};
|
||||||
"lists available tasks"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group list_command::do_group()
|
clipp::group list_command::do_group()
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return clipp::group(
|
||||||
clipp::command("list").set(picked_),
|
clipp::command("list").set(picked_),
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
(clipp::option("-h", "--help") >> help_) % "shows this message",
|
||||||
% "shows this message",
|
|
||||||
|
|
||||||
(clipp::option("-a", "--all") >> all_)
|
(clipp::option("-a", "--all") >> all_) %
|
||||||
% "shows all the tasks, including pseudo parallel tasks",
|
"shows all the tasks, including pseudo parallel tasks",
|
||||||
|
|
||||||
(clipp::option("-i", "--aliases") >> aliases_)
|
(clipp::option("-i", "--aliases") >> aliases_) % "shows only aliases",
|
||||||
% "shows only aliases",
|
|
||||||
|
|
||||||
(clipp::opt_values(
|
(clipp::opt_values(clipp::match::prefix_not("-"), "task", tasks_)) %
|
||||||
clipp::match::prefix_not("-"), "task", tasks_))
|
"with -a; when given, acts like the tasks given to `build` and "
|
||||||
% "with -a; when given, acts like the tasks given to `build` and "
|
"shows only the tasks that would run");
|
||||||
"shows only the tasks that would run"
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
int list_command::do_run()
|
int list_command::do_run()
|
||||||
{
|
{
|
||||||
auto& tm = task_manager::instance();
|
auto& tm = task_manager::instance();
|
||||||
|
|
||||||
if (aliases_)
|
if (aliases_) {
|
||||||
{
|
|
||||||
load_options();
|
load_options();
|
||||||
dump_aliases();
|
dump_aliases();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
if (all_) {
|
||||||
if (all_)
|
|
||||||
{
|
|
||||||
if (!tasks_.empty())
|
if (!tasks_.empty())
|
||||||
set_task_enabled_flags(tasks_);
|
set_task_enabled_flags(tasks_);
|
||||||
|
|
||||||
@@ -59,42 +47,37 @@ int list_command::do_run()
|
|||||||
u8cout << "\n\naliases:\n";
|
u8cout << "\n\naliases:\n";
|
||||||
dump_aliases();
|
dump_aliases();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
for (auto&& t : tm.all())
|
for (auto&& t : tm.all())
|
||||||
u8cout << " - " << join(t->names(), ", ") << "\n";
|
u8cout << " - " << join(t->names(), ", ") << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_command::dump(const std::vector<task*>& v, std::size_t indent) const
|
void list_command::dump(const std::vector<task*>& v, std::size_t indent) const
|
||||||
{
|
|
||||||
for (auto&& t : v)
|
|
||||||
{
|
{
|
||||||
|
for (auto&& t : v) {
|
||||||
if (!t->enabled())
|
if (!t->enabled())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
u8cout
|
u8cout << std::string(indent * 4, ' ') << " - " << join(t->names(), ",")
|
||||||
<< std::string(indent*4, ' ')
|
|
||||||
<< " - " << join(t->names(), ",")
|
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
if (auto* pt=dynamic_cast<parallel_tasks*>(t))
|
if (auto* pt = dynamic_cast<parallel_tasks*>(t))
|
||||||
dump(pt->children(), indent + 1);
|
dump(pt->children(), indent + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_command::dump_aliases() const
|
void list_command::dump_aliases() const
|
||||||
{
|
{
|
||||||
const auto v = task_manager::instance().aliases();
|
const auto v = task_manager::instance().aliases();
|
||||||
if (v.empty())
|
if (v.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto&& [k, patterns] : v)
|
for (auto&& [k, patterns] : v)
|
||||||
u8cout << " - " << k << ": " << join(patterns, ", ") << "\n";
|
u8cout << " - " << k << ": " << join(patterns, ", ") << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+103
-148
@@ -1,38 +1,28 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "commands.h"
|
|
||||||
#include "../core/conf.h"
|
#include "../core/conf.h"
|
||||||
#include "../tasks/task_manager.h"
|
#include "../tasks/task_manager.h"
|
||||||
#include "../tasks/tasks.h"
|
#include "../tasks/tasks.h"
|
||||||
#include "../utility.h"
|
#include "../utility.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
std::string read_file(const fs::path& p)
|
std::string read_file(const fs::path& p)
|
||||||
{
|
{
|
||||||
std::ifstream t(p);
|
std::ifstream t(p);
|
||||||
return {std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>()};
|
return {std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pr_command::pr_command() : command(requires_options | handle_sigint) {}
|
||||||
|
|
||||||
pr_command::pr_command()
|
command::meta_t pr_command::meta() const
|
||||||
: command(requires_options | handle_sigint)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
command::meta_t pr_command::meta() const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"pr",
|
return {"pr", "applies changes from PRs"};
|
||||||
"applies changes from PRs"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string pr_command::do_doc()
|
std::string pr_command::do_doc()
|
||||||
{
|
{
|
||||||
return
|
return "Operations:\n"
|
||||||
"Operations:\n"
|
|
||||||
" - find: lists all the repos that would affected by `pull` or\n"
|
" - find: lists all the repos that would affected by `pull` or\n"
|
||||||
" `revert`\n"
|
" `revert`\n"
|
||||||
" - pull: fetches the pr's branch and checks it out; all repos\n"
|
" - pull: fetches the pr's branch and checks it out; all repos\n"
|
||||||
@@ -44,29 +34,27 @@ std::string pr_command::do_doc()
|
|||||||
" - umbrella\n"
|
" - umbrella\n"
|
||||||
" - any repo that's not in modorganizer_super\n"
|
" - any repo that's not in modorganizer_super\n"
|
||||||
" - modorganizer_installer";
|
" - modorganizer_installer";
|
||||||
}
|
}
|
||||||
|
|
||||||
clipp::group pr_command::do_group()
|
clipp::group pr_command::do_group()
|
||||||
{
|
{
|
||||||
return
|
return (clipp::command("pr")).set(picked_),
|
||||||
(clipp::command("pr")).set(picked_),
|
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
(clipp::option("-h", "--help") >> help_) % ("shows this message"),
|
||||||
% ("shows this message"),
|
|
||||||
|
|
||||||
(clipp::option("--github-token")
|
(clipp::option("--github-token") &
|
||||||
& clipp::value("TOKEN") >> github_token_)
|
clipp::value("TOKEN") >> github_token_) %
|
||||||
% "github api key",
|
"github api key",
|
||||||
|
|
||||||
(clipp::value("OP") >> op_)
|
(clipp::value("OP") >> op_) %
|
||||||
% "one of `find`, `pull` or `revert`; see below",
|
"one of `find`, `pull` or `revert`; see below",
|
||||||
|
|
||||||
(clipp::value("PR") >> pr_)
|
(clipp::value("PR") >> pr_) %
|
||||||
% "PR to apply, must be `task/pr`, such as `modorganizer/123`";
|
"PR to apply, must be `task/pr`, such as `modorganizer/123`";
|
||||||
}
|
}
|
||||||
|
|
||||||
int pr_command::do_run()
|
int pr_command::do_run()
|
||||||
{
|
{
|
||||||
if (github_token_.empty())
|
if (github_token_.empty())
|
||||||
github_token_ = conf().global().get("github_key");
|
github_token_ = conf().global().get("github_key");
|
||||||
|
|
||||||
@@ -80,17 +68,16 @@ int pr_command::do_run()
|
|||||||
u8cerr << "bad operation '" << op_ << "'\n";
|
u8cerr << "bad operation '" << op_ << "'\n";
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<const tasks::modorganizer*, std::string> pr_command::parse_pr(
|
std::pair<const tasks::modorganizer*, std::string>
|
||||||
const std::string& pr) const
|
pr_command::parse_pr(const std::string& pr) const
|
||||||
{
|
{
|
||||||
if (pr.empty())
|
if (pr.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const auto cs = split(pr, "/");
|
const auto cs = split(pr, "/");
|
||||||
if (cs.size() != 2)
|
if (cs.size() != 2) {
|
||||||
{
|
|
||||||
u8cerr << "--pr must be task/pr, such as modorganizer/123\n";
|
u8cerr << "--pr must be task/pr, such as modorganizer/123\n";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -103,17 +90,16 @@ std::pair<const tasks::modorganizer*, std::string> pr_command::parse_pr(
|
|||||||
return {};
|
return {};
|
||||||
|
|
||||||
const auto* mo_task = dynamic_cast<const tasks::modorganizer*>(task);
|
const auto* mo_task = dynamic_cast<const tasks::modorganizer*>(task);
|
||||||
if (!mo_task)
|
if (!mo_task) {
|
||||||
{
|
|
||||||
u8cerr << "only modorganizer tasks are supported\n";
|
u8cerr << "only modorganizer tasks are supported\n";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {mo_task, pr_number};
|
return {mo_task, pr_number};
|
||||||
}
|
}
|
||||||
|
|
||||||
int pr_command::pull()
|
int pr_command::pull()
|
||||||
{
|
{
|
||||||
const auto prs = get_matching_prs(pr_);
|
const auto prs = get_matching_prs(pr_);
|
||||||
if (prs.empty())
|
if (prs.empty())
|
||||||
return 1;
|
return 1;
|
||||||
@@ -122,24 +108,20 @@ int pr_command::pull()
|
|||||||
if (okay_prs.empty())
|
if (okay_prs.empty())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
for (auto&& pr : okay_prs) {
|
||||||
for (auto&& pr : okay_prs)
|
|
||||||
{
|
|
||||||
const auto* task = dynamic_cast<const tasks::modorganizer*>(
|
const auto* task = dynamic_cast<const tasks::modorganizer*>(
|
||||||
task_manager::instance().find_one(pr.repo));
|
task_manager::instance().find_one(pr.repo));
|
||||||
|
|
||||||
if (!task)
|
if (!task)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
u8cout
|
u8cout << "checking out pr " << pr.number << " "
|
||||||
<< "checking out pr " << pr.number << " "
|
|
||||||
<< "in " << task->name() << "\n";
|
<< "in " << task->name() << "\n";
|
||||||
|
|
||||||
git_wrap g(task->source_path());
|
git_wrap g(task->source_path());
|
||||||
|
|
||||||
g.fetch(
|
g.fetch(task->git_url().string(),
|
||||||
task->git_url().string(),
|
|
||||||
fmt::format("pull/{}/head", pr.number));
|
fmt::format("pull/{}/head", pr.number));
|
||||||
|
|
||||||
g.checkout("FETCH_HEAD");
|
g.checkout("FETCH_HEAD");
|
||||||
@@ -149,20 +131,19 @@ int pr_command::pull()
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch (std::exception& e) {
|
||||||
{
|
|
||||||
u8cerr << e.what() << "\n";
|
u8cerr << e.what() << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pr_command::find()
|
int pr_command::find()
|
||||||
{
|
{
|
||||||
return !get_matching_prs(pr_).empty();
|
return !get_matching_prs(pr_).empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
int pr_command::revert()
|
int pr_command::revert()
|
||||||
{
|
{
|
||||||
const auto prs = get_matching_prs(pr_);
|
const auto prs = get_matching_prs(pr_);
|
||||||
if (prs.empty())
|
if (prs.empty())
|
||||||
return 1;
|
return 1;
|
||||||
@@ -171,10 +152,8 @@ int pr_command::revert()
|
|||||||
if (okay_prs.empty())
|
if (okay_prs.empty())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
for (auto&& pr : okay_prs) {
|
||||||
for (auto&& pr : okay_prs)
|
|
||||||
{
|
|
||||||
const auto* task = dynamic_cast<const tasks::modorganizer*>(
|
const auto* task = dynamic_cast<const tasks::modorganizer*>(
|
||||||
task_manager::instance().find_one(pr.repo));
|
task_manager::instance().find_one(pr.repo));
|
||||||
|
|
||||||
@@ -188,16 +167,15 @@ int pr_command::revert()
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch (std::exception& e) {
|
||||||
{
|
|
||||||
u8cerr << e.what() << "\n";
|
u8cerr << e.what() << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<pr_command::pr_info> pr_command::get_matching_prs(
|
std::vector<pr_command::pr_info>
|
||||||
const std::string& repo_pr)
|
pr_command::get_matching_prs(const std::string& repo_pr)
|
||||||
{
|
{
|
||||||
auto&& [task, src_pr] = parse_pr(repo_pr);
|
auto&& [task, src_pr] = parse_pr(repo_pr);
|
||||||
if (!task)
|
if (!task)
|
||||||
return {};
|
return {};
|
||||||
@@ -214,29 +192,28 @@ std::vector<pr_command::pr_info> pr_command::get_matching_prs(
|
|||||||
|
|
||||||
u8cout << "found matching prs in " << prs.size() << " repos:\n";
|
u8cout << "found matching prs in " << prs.size() << " repos:\n";
|
||||||
|
|
||||||
u8cout
|
u8cout << table(map(prs,
|
||||||
<< table(map(prs, [&](auto&& pr)
|
[&](auto&& pr) {
|
||||||
{
|
|
||||||
return std::pair(pr.repo + "/" + pr.number, pr.title);
|
return std::pair(pr.repo + "/" + pr.number, pr.title);
|
||||||
}), 2, 5)
|
}),
|
||||||
|
2, 5)
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
return prs;
|
return prs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<pr_command::pr_info> pr_command::search_prs(
|
std::vector<pr_command::pr_info> pr_command::search_prs(const std::string& org,
|
||||||
const std::string& org, const std::string& author, const std::string& branch)
|
const std::string& author,
|
||||||
{
|
const std::string& branch)
|
||||||
|
{
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
|
|
||||||
constexpr auto* pattern =
|
constexpr auto* pattern =
|
||||||
"https://api.github.com/search/issues?per_page=100&q="
|
"https://api.github.com/search/issues?per_page=100&q="
|
||||||
"is:pr+org:{org:}+author:{author:}+is:open+head:{branch:}";
|
"is:pr+org:{org:}+author:{author:}+is:open+head:{branch:}";
|
||||||
|
|
||||||
const auto search_url = fmt::format(
|
const auto search_url =
|
||||||
pattern,
|
fmt::format(pattern, fmt::arg("org", org), fmt::arg("author", author),
|
||||||
fmt::arg("org", org),
|
|
||||||
fmt::arg("author", author),
|
|
||||||
fmt::arg("branch", branch));
|
fmt::arg("branch", branch));
|
||||||
|
|
||||||
u8cout << "search url is " << search_url << "\n";
|
u8cout << "search url is " << search_url << "\n";
|
||||||
@@ -245,14 +222,12 @@ std::vector<pr_command::pr_info> pr_command::search_prs(
|
|||||||
|
|
||||||
curl_downloader dl;
|
curl_downloader dl;
|
||||||
|
|
||||||
dl
|
dl.url(search_url)
|
||||||
.url(search_url)
|
|
||||||
.header("Authorization", "token " + github_token_)
|
.header("Authorization", "token " + github_token_)
|
||||||
.start()
|
.start()
|
||||||
.join();
|
.join();
|
||||||
|
|
||||||
if (!dl.ok())
|
if (!dl.ok()) {
|
||||||
{
|
|
||||||
u8cerr << "failed to search github\n";
|
u8cerr << "failed to search github\n";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -260,66 +235,54 @@ std::vector<pr_command::pr_info> pr_command::search_prs(
|
|||||||
const auto output = dl.steal_output();
|
const auto output = dl.steal_output();
|
||||||
json = nlohmann::json::parse(output);
|
json = nlohmann::json::parse(output);
|
||||||
|
|
||||||
|
|
||||||
std::map<std::string, pr_info> repos;
|
std::map<std::string, pr_info> repos;
|
||||||
|
|
||||||
for (auto&& item : json["items"])
|
for (auto&& item : json["items"]) {
|
||||||
{
|
|
||||||
// ex: https://api.github.com/repos/ModOrganizer2/modorganizer-Installer
|
// ex: https://api.github.com/repos/ModOrganizer2/modorganizer-Installer
|
||||||
const std::string url = item["repository_url"];
|
const std::string url = item["repository_url"];
|
||||||
|
|
||||||
const auto last_slash = url.find_last_of("/");
|
const auto last_slash = url.find_last_of("/");
|
||||||
if (last_slash == std::string::npos)
|
if (last_slash == std::string::npos) {
|
||||||
{
|
|
||||||
u8cerr << "bad repo url in search: '" << url << "'\n";
|
u8cerr << "bad repo url in search: '" << url << "'\n";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto repo = url.substr(last_slash + 1);
|
const auto repo = url.substr(last_slash + 1);
|
||||||
|
|
||||||
pr_info info = {
|
pr_info info = {repo, author, branch, item["title"],
|
||||||
repo, author, branch, item["title"],
|
std::to_string(item["number"].get<int>())};
|
||||||
std::to_string(item["number"].get<int>())
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!repos.emplace(repo, info).second)
|
if (!repos.emplace(repo, info).second) {
|
||||||
{
|
u8cerr << "multiple prs found in repo " << repo << ", "
|
||||||
u8cerr
|
|
||||||
<< "multiple prs found in repo " << repo << ", "
|
|
||||||
<< "not supported\n";
|
<< "not supported\n";
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return map(repos, [&](auto&& pair){ return pair.second; });
|
return map(repos, [&](auto&& pair) {
|
||||||
}
|
return pair.second;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pr_command::pr_info pr_command::get_pr_info(
|
pr_command::pr_info pr_command::get_pr_info(const tasks::modorganizer* task,
|
||||||
const tasks::modorganizer* task, const std::string& pr)
|
const std::string& pr)
|
||||||
{
|
{
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
|
|
||||||
if (github_token_.empty())
|
if (github_token_.empty()) {
|
||||||
{
|
|
||||||
u8cerr << "missing --github-token\n";
|
u8cerr << "missing --github-token\n";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const url u(fmt::format(
|
const url u(fmt::format("https://api.github.com/repos/{}/{}/pulls/{}",
|
||||||
"https://api.github.com/repos/{}/{}/pulls/{}",
|
|
||||||
task->org(), task->repo(), pr));
|
task->org(), task->repo(), pr));
|
||||||
|
|
||||||
curl_downloader dl;
|
curl_downloader dl;
|
||||||
|
|
||||||
dl
|
dl.url(u).header("Authorization", "token " + github_token_).start().join();
|
||||||
.url(u)
|
|
||||||
.header("Authorization", "token " + github_token_)
|
|
||||||
.start()
|
|
||||||
.join();
|
|
||||||
|
|
||||||
if (!dl.ok())
|
if (!dl.ok()) {
|
||||||
{
|
|
||||||
u8cerr << "failed to get pr info from github\n";
|
u8cerr << "failed to get pr info from github\n";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -332,44 +295,37 @@ pr_command::pr_info pr_command::get_pr_info(
|
|||||||
const std::string branch = json["head"]["ref"];
|
const std::string branch = json["head"]["ref"];
|
||||||
|
|
||||||
return {repo, author, branch};
|
return {repo, author, branch};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<pr_command::pr_info> pr_command::validate_prs(
|
std::vector<pr_command::pr_info>
|
||||||
const std::vector<pr_info>& prs)
|
pr_command::validate_prs(const std::vector<pr_info>& prs)
|
||||||
{
|
{
|
||||||
std::vector<std::string> problems;
|
std::vector<std::string> problems;
|
||||||
std::vector<pr_info> okay_prs;
|
std::vector<pr_info> okay_prs;
|
||||||
|
|
||||||
for (auto&& pr : prs)
|
for (auto&& pr : prs) {
|
||||||
{
|
if (pr.repo == "mob") {
|
||||||
if (pr.repo == "mob")
|
|
||||||
{
|
|
||||||
problems.push_back("there's a pr for mob itself");
|
problems.push_back("there's a pr for mob itself");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
const auto tasks = task_manager::instance().find(pr.repo);
|
const auto tasks = task_manager::instance().find(pr.repo);
|
||||||
|
|
||||||
if (tasks.empty())
|
if (tasks.empty()) {
|
||||||
{
|
|
||||||
problems.push_back("task " + pr.repo + " does not exist");
|
problems.push_back("task " + pr.repo + " does not exist");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (tasks.size() > 1)
|
else if (tasks.size() > 1) {
|
||||||
{
|
|
||||||
problems.push_back("found more than one task for repo " + pr.repo);
|
problems.push_back("found more than one task for repo " + pr.repo);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
const auto* mo_task =
|
const auto* mo_task =
|
||||||
dynamic_cast<const tasks::modorganizer*>(tasks[0]);
|
dynamic_cast<const tasks::modorganizer*>(tasks[0]);
|
||||||
|
|
||||||
if (!mo_task)
|
if (!mo_task) {
|
||||||
{
|
problems.push_back("task " + pr.repo +
|
||||||
problems.push_back(
|
" is not a modorganizer repo");
|
||||||
"task " + pr.repo + " is not a modorganizer repo");
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -379,8 +335,7 @@ std::vector<pr_command::pr_info> pr_command::validate_prs(
|
|||||||
okay_prs.push_back(pr);
|
okay_prs.push_back(pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!problems.empty())
|
if (!problems.empty()) {
|
||||||
{
|
|
||||||
{
|
{
|
||||||
console_color cc(console_color::yellow);
|
console_color cc(console_color::yellow);
|
||||||
|
|
||||||
@@ -391,19 +346,19 @@ std::vector<pr_command::pr_info> pr_command::validate_prs(
|
|||||||
|
|
||||||
u8cout << "\n";
|
u8cout << "\n";
|
||||||
|
|
||||||
if (okay_prs.empty())
|
if (okay_prs.empty()) {
|
||||||
{
|
|
||||||
u8cout << "all prs would be ignored, bailing out\n";
|
u8cout << "all prs would be ignored, bailing out\n";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ask_yes_no("these prs will be ignored; proceed anyway?", yn::no) != yn::yes)
|
if (ask_yes_no("these prs will be ignored; proceed anyway?", yn::no) !=
|
||||||
|
yn::yes)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
u8cout << "\n";
|
u8cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return okay_prs;
|
return okay_prs;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+171
-233
File diff suppressed because it is too large
Load Diff
+60
-85
@@ -1,82 +1,67 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "commands.h"
|
|
||||||
#include "../net.h"
|
|
||||||
#include "../utility.h"
|
|
||||||
#include "../core/conf.h"
|
#include "../core/conf.h"
|
||||||
#include "../core/context.h"
|
#include "../core/context.h"
|
||||||
#include "../core/env.h"
|
#include "../core/env.h"
|
||||||
|
#include "../net.h"
|
||||||
#include "../tasks/tasks.h"
|
#include "../tasks/tasks.h"
|
||||||
|
#include "../utility.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
tx_command::tx_command()
|
tx_command::tx_command() : command(requires_options) {}
|
||||||
: command(requires_options)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
command::meta_t tx_command::meta() const
|
command::meta_t tx_command::meta() const
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
"tx",
|
return {"tx", "manages transifex translations"};
|
||||||
"manages transifex translations"
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group tx_command::do_group()
|
clipp::group tx_command::do_group()
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return clipp::group(
|
||||||
clipp::command("tx").set(picked_),
|
clipp::command("tx").set(picked_),
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
(clipp::option("-h", "--help") >> help_) % ("shows this message"),
|
||||||
% ("shows this message"),
|
|
||||||
|
|
||||||
"get" %
|
"get" % (clipp::command("get").set(mode_, modes::get),
|
||||||
(clipp::command("get").set(mode_, modes::get),
|
(clipp::option("-k", "--key") & clipp::value("APIKEY") >> key_) %
|
||||||
(clipp::option("-k", "--key")
|
"API key",
|
||||||
& clipp::value("APIKEY") >> key_)
|
|
||||||
% "API key",
|
|
||||||
|
|
||||||
(clipp::option("-t", "--team")
|
(clipp::option("-t", "--team") & clipp::value("TEAM") >> team_) %
|
||||||
& clipp::value("TEAM") >> team_)
|
"team name",
|
||||||
% "team name",
|
|
||||||
|
|
||||||
(clipp::option("-p", "--project")
|
(clipp::option("-p", "--project") &
|
||||||
& clipp::value("PROJECT") >> project_)
|
clipp::value("PROJECT") >> project_) %
|
||||||
% "project name",
|
"project name",
|
||||||
|
|
||||||
(clipp::option("-u", "--url")
|
(clipp::option("-u", "--url") & clipp::value("URL") >> url_) %
|
||||||
& clipp::value("URL") >> url_)
|
"project URL",
|
||||||
% "project URL",
|
|
||||||
|
|
||||||
(clipp::option("-m", "--minimum")
|
(clipp::option("-m", "--minimum") &
|
||||||
& clipp::value("PERCENT").set(min_))
|
clipp::value("PERCENT").set(min_)) %
|
||||||
% "minimum translation threshold to download [0-100]",
|
"minimum translation threshold to download [0-100]",
|
||||||
|
|
||||||
(clipp::option("-f", "--force").call([&]{ force_ = true; }))
|
(clipp::option("-f", "--force").call([&] {
|
||||||
% "don't check timestamps, re-download all translation files",
|
force_ = true;
|
||||||
|
})) %
|
||||||
|
"don't check timestamps, re-download all translation files",
|
||||||
|
|
||||||
(clipp::value("path") >> path_)
|
(clipp::value("path") >> path_) %
|
||||||
% "path that will contain the .tx directory"
|
"path that will contain the .tx directory")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
|
|
||||||
|
|
||||||
"build" %
|
"build" % (clipp::command("build").set(mode_, modes::build),
|
||||||
(clipp::command("build").set(mode_, modes::build),
|
|
||||||
|
|
||||||
(clipp::value("source") >> path_)
|
(clipp::value("source") >> path_) %
|
||||||
% "path that contains the translation directories",
|
"path that contains the translation directories",
|
||||||
|
|
||||||
(clipp::value("destination") >> dest_)
|
(clipp::value("destination") >> dest_) %
|
||||||
% "path that will contain the .qm files"
|
"path that will contain the .qm files"));
|
||||||
)
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tx_command::convert_cl_to_conf()
|
void tx_command::convert_cl_to_conf()
|
||||||
{
|
{
|
||||||
command::convert_cl_to_conf();
|
command::convert_cl_to_conf();
|
||||||
|
|
||||||
if (!key_.empty())
|
if (!key_.empty())
|
||||||
@@ -96,12 +81,11 @@ void tx_command::convert_cl_to_conf()
|
|||||||
|
|
||||||
if (force_)
|
if (force_)
|
||||||
common.options.push_back("transifex/force=" + std::to_string(*force_));
|
common.options.push_back("transifex/force=" + std::to_string(*force_));
|
||||||
}
|
}
|
||||||
|
|
||||||
int tx_command::do_run()
|
int tx_command::do_run()
|
||||||
{
|
|
||||||
switch (mode_)
|
|
||||||
{
|
{
|
||||||
|
switch (mode_) {
|
||||||
case modes::get:
|
case modes::get:
|
||||||
do_get();
|
do_get();
|
||||||
break;
|
break;
|
||||||
@@ -117,12 +101,11 @@ int tx_command::do_run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tx_command::do_doc()
|
std::string tx_command::do_doc()
|
||||||
{
|
{
|
||||||
return
|
return "Some values will be taken from the INI file if not specified.\n"
|
||||||
"Some values will be taken from the INI file if not specified.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"Commands:\n"
|
"Commands:\n"
|
||||||
"get\n"
|
"get\n"
|
||||||
@@ -133,21 +116,18 @@ std::string tx_command::do_doc()
|
|||||||
" Builds all .qm files. The path can either be the transifex\n"
|
" Builds all .qm files. The path can either be the transifex\n"
|
||||||
" project (where .tx is) or the `translations` directory (where the\n"
|
" project (where .tx is) or the `translations` directory (where the\n"
|
||||||
" individual translation directories are).";
|
" individual translation directories are).";
|
||||||
}
|
}
|
||||||
|
|
||||||
void tx_command::do_get()
|
void tx_command::do_get()
|
||||||
{
|
{
|
||||||
const url u =
|
const url u = conf().transifex().get("url") + "/" +
|
||||||
conf().transifex().get("url") + "/" +
|
|
||||||
conf().transifex().get("team") + "/" +
|
conf().transifex().get("team") + "/" +
|
||||||
conf().transifex().get("project");
|
conf().transifex().get("project");
|
||||||
|
|
||||||
const std::string key = conf().transifex().get("key");
|
const std::string key = conf().transifex().get("key");
|
||||||
|
|
||||||
if (key.empty() && !this_env::get_opt("TX_TOKEN"))
|
if (key.empty() && !this_env::get_opt("TX_TOKEN")) {
|
||||||
{
|
u8cout << "(no key was in the INI, --key wasn't given and TX_TOKEN env\n"
|
||||||
u8cout <<
|
|
||||||
"(no key was in the INI, --key wasn't given and TX_TOKEN env\n"
|
|
||||||
"variable doesn't exist, this will probably fail)\n\n";
|
"variable doesn't exist, this will probably fail)\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,9 +135,7 @@ void tx_command::do_get()
|
|||||||
context cxcopy = gcx();
|
context cxcopy = gcx();
|
||||||
|
|
||||||
u8cout << "initializing\n";
|
u8cout << "initializing\n";
|
||||||
transifex(transifex::init)
|
transifex(transifex::init).root(path_).run(cxcopy);
|
||||||
.root(path_)
|
|
||||||
.run(cxcopy);
|
|
||||||
|
|
||||||
u8cout << "configuring\n";
|
u8cout << "configuring\n";
|
||||||
transifex(transifex::config)
|
transifex(transifex::config)
|
||||||
@@ -175,10 +153,10 @@ void tx_command::do_get()
|
|||||||
.minimum(conf().transifex().get<int>("minimum"))
|
.minimum(conf().transifex().get<int>("minimum"))
|
||||||
.force(conf().transifex().get<bool>("force"))
|
.force(conf().transifex().get<bool>("force"))
|
||||||
.run(cxcopy);
|
.run(cxcopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tx_command::do_build()
|
void tx_command::do_build()
|
||||||
{
|
{
|
||||||
fs::path root = path_;
|
fs::path root = path_;
|
||||||
if (fs::exists(root / ".tx") && fs::exists(root / "translations"))
|
if (fs::exists(root / ".tx") && fs::exists(root / "translations"))
|
||||||
root = root / "translations";
|
root = root / "translations";
|
||||||
@@ -193,13 +171,10 @@ void tx_command::do_build()
|
|||||||
|
|
||||||
thread_pool tp;
|
thread_pool tp;
|
||||||
|
|
||||||
for (auto& p : ps.get())
|
for (auto& p : ps.get()) {
|
||||||
{
|
for (auto& lg : p.langs) {
|
||||||
for (auto& lg : p.langs)
|
|
||||||
{
|
|
||||||
// copy the global context, each thread must have its own
|
// copy the global context, each thread must have its own
|
||||||
tp.add([&, cxcopy=gcx()]() mutable
|
tp.add([&, cxcopy = gcx()]() mutable {
|
||||||
{
|
|
||||||
lrelease()
|
lrelease()
|
||||||
.project(p.name)
|
.project(p.name)
|
||||||
.sources(lg.ts_files)
|
.sources(lg.ts_files)
|
||||||
@@ -208,6 +183,6 @@ void tx_command::do_build()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+310
-370
File diff suppressed because it is too large
Load Diff
+129
-131
@@ -3,73 +3,77 @@
|
|||||||
// these shouldn't be called directly, they're used by some of the template
|
// these shouldn't be called directly, they're used by some of the template
|
||||||
// below
|
// below
|
||||||
//
|
//
|
||||||
namespace mob::details
|
namespace mob::details {
|
||||||
{
|
|
||||||
|
|
||||||
// returns an option named `key` from the given `section`
|
// returns an option named `key` from the given `section`
|
||||||
//
|
//
|
||||||
std::string get_string(std::string_view section, std::string_view key);
|
std::string get_string(std::string_view section, std::string_view key,
|
||||||
|
std::optional<std::string> default_ = {});
|
||||||
|
|
||||||
// calls get_string(), converts to bool
|
// calls get_string(), converts to bool
|
||||||
//
|
//
|
||||||
bool get_bool(std::string_view section, std::string_view key);
|
bool get_bool(std::string_view section, std::string_view key,
|
||||||
|
std::optional<bool> default_ = {});
|
||||||
|
|
||||||
// calls get_string(), converts to in
|
// calls get_string(), converts to in
|
||||||
//
|
//
|
||||||
int get_int(std::string_view section, std::string_view key);
|
int get_int(std::string_view section, std::string_view key,
|
||||||
|
std::optional<int> default_ = {});
|
||||||
|
|
||||||
// sets the given option, bails out if the option doesn't exist
|
// sets the given option, bails out if the option doesn't exist
|
||||||
//
|
//
|
||||||
void set_string(
|
void set_string(std::string_view section, std::string_view key,
|
||||||
std::string_view section, std::string_view key, std::string_view value);
|
std::string_view value);
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob::details
|
||||||
|
|
||||||
|
namespace mob {
|
||||||
|
|
||||||
namespace mob
|
// reads options from the given inis and option strings, resolves all the paths
|
||||||
{
|
// and necessary tools, also adds a couple of things to PATH
|
||||||
|
//
|
||||||
|
void init_options(const std::vector<fs::path>& inis,
|
||||||
|
const std::vector<std::string>& opts);
|
||||||
|
|
||||||
// reads options from the given inis and option strings, resolves all the paths
|
// checks some of the options once everything is loaded, returns false if
|
||||||
// and necessary tools, also adds a couple of things to PATH
|
// something's wrong
|
||||||
//
|
//
|
||||||
void init_options(
|
bool verify_options();
|
||||||
const std::vector<fs::path>& inis, const std::vector<std::string>& opts);
|
|
||||||
|
|
||||||
// checks some of the options once everything is loaded, returns false if
|
// returns all options formatted as three columns
|
||||||
// something's wrong
|
//
|
||||||
//
|
std::vector<std::string> format_options();
|
||||||
bool verify_options();
|
|
||||||
|
|
||||||
// returns all options formatted as three columns
|
// base class for all conf structs
|
||||||
//
|
//
|
||||||
std::vector<std::string> format_options();
|
template <class DefaultType>
|
||||||
|
class conf_section {
|
||||||
|
public:
|
||||||
// base class for all conf structs
|
DefaultType get(std::string_view key,
|
||||||
//
|
std::optional<DefaultType> default_ = {}) const
|
||||||
template <class DefaultType>
|
|
||||||
class conf_section
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DefaultType get(std::string_view key) const
|
|
||||||
{
|
{
|
||||||
|
if constexpr (std::is_same_v<DefaultType, std::string>) {
|
||||||
|
return details::get_string(name_, key, default_);
|
||||||
|
}
|
||||||
|
else {
|
||||||
return details::get_string(name_, key);
|
return details::get_string(name_, key);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// undefined
|
// undefined
|
||||||
template <class T>
|
template <class T>
|
||||||
T get(std::string_view key) const;
|
T get(std::string_view key, std::optional<T> default_ = {}) const;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool get<bool>(std::string_view key) const
|
bool get<bool>(std::string_view key, std::optional<bool> default_) const
|
||||||
{
|
{
|
||||||
return details::get_bool(name_, key);
|
return details::get_bool(name_, key, default_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
int get<int>(std::string_view key) const
|
int get<int>(std::string_view key, std::optional<int> default_) const
|
||||||
{
|
{
|
||||||
return details::get_int(name_, key);
|
return details::get_int(name_, key, default_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(std::string_view key, std::string_view value)
|
void set(std::string_view key, std::string_view value)
|
||||||
@@ -77,24 +81,19 @@ public:
|
|||||||
details::set_string(name_, key, value);
|
details::set_string(name_, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
conf_section(std::string section_name)
|
conf_section(std::string section_name) : name_(std::move(section_name)) {}
|
||||||
: name_(std::move(section_name))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& name() const { return name_; }
|
const auto& name() const { return name_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// options in [global]
|
||||||
// options in [global]
|
//
|
||||||
//
|
class conf_global : public conf_section<std::string> {
|
||||||
class conf_global : public conf_section<std::string>
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
conf_global();
|
conf_global();
|
||||||
|
|
||||||
// convenience, doesn't need string manipulation
|
// convenience, doesn't need string manipulation
|
||||||
@@ -110,14 +109,12 @@ public:
|
|||||||
bool clean() const { return get<bool>("clean_task"); }
|
bool clean() const { return get<bool>("clean_task"); }
|
||||||
bool fetch() const { return get<bool>("fetch_task"); }
|
bool fetch() const { return get<bool>("fetch_task"); }
|
||||||
bool build() const { return get<bool>("build_task"); }
|
bool build() const { return get<bool>("build_task"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// options in [task] or [task_name:task]
|
||||||
// options in [task] or [task_name:task]
|
//
|
||||||
//
|
class conf_task {
|
||||||
class conf_task
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
conf_task(std::vector<std::string> names);
|
conf_task(std::vector<std::string> names);
|
||||||
|
|
||||||
std::string get(std::string_view key) const;
|
std::string get(std::string_view key) const;
|
||||||
@@ -136,7 +133,7 @@ public:
|
|||||||
std::string mo_fallback_branch() const { return get("mo_fallback"); }
|
std::string mo_fallback_branch() const { return get("mo_fallback"); }
|
||||||
bool no_pull() const { return get<bool>("no_pull"); }
|
bool no_pull() const { return get<bool>("no_pull"); }
|
||||||
bool revert_ts() const { return get<bool>("revert_ts"); }
|
bool revert_ts() const { return get<bool>("revert_ts"); }
|
||||||
bool ignore_ts()const { return get<bool>("ignore_ts"); }
|
bool ignore_ts() const { return get<bool>("ignore_ts"); }
|
||||||
std::string git_url_prefix() const { return get("git_url_prefix"); }
|
std::string git_url_prefix() const { return get("git_url_prefix"); }
|
||||||
bool git_shallow() const { return get<bool>("git_shallow"); }
|
bool git_shallow() const { return get<bool>("git_shallow"); }
|
||||||
std::string git_user() const { return get("git_username"); }
|
std::string git_user() const { return get("git_username"); }
|
||||||
@@ -144,21 +141,25 @@ public:
|
|||||||
bool set_origin_remote() const { return get<bool>("set_origin_remote"); }
|
bool set_origin_remote() const { return get<bool>("set_origin_remote"); }
|
||||||
std::string remote_org() const { return get("remote_org"); }
|
std::string remote_org() const { return get("remote_org"); }
|
||||||
std::string remote_key() const { return get("remote_key"); }
|
std::string remote_key() const { return get("remote_key"); }
|
||||||
bool remote_no_push_upstream() const { return get<bool>("remote_no_push_upstream"); }
|
bool remote_no_push_upstream() const
|
||||||
bool remote_push_default_origin() const { return get<bool>("remote_push_default_origin"); }
|
{
|
||||||
|
return get<bool>("remote_no_push_upstream");
|
||||||
|
}
|
||||||
|
bool remote_push_default_origin() const
|
||||||
|
{
|
||||||
|
return get<bool>("remote_push_default_origin");
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> names_;
|
std::vector<std::string> names_;
|
||||||
|
|
||||||
bool get_bool(std::string_view name) const;
|
bool get_bool(std::string_view name) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// options in [task] or [task_name:task]
|
||||||
// options in [task] or [task_name:task]
|
//
|
||||||
//
|
class conf_cmake : conf_section<std::string> {
|
||||||
class conf_cmake : conf_section<std::string>
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
class cmake_constant {
|
class cmake_constant {
|
||||||
std::string value_;
|
std::string value_;
|
||||||
|
|
||||||
@@ -169,10 +170,9 @@ public:
|
|||||||
friend class conf_cmake;
|
friend class conf_cmake;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr cmake_constant(std::string_view value) : value_{value} { }
|
constexpr cmake_constant(std::string_view value) : value_{value} {}
|
||||||
constexpr const auto& value() const { return value_; }
|
constexpr const auto& value() const { return value_; }
|
||||||
constexpr operator const std::string& () const { return value(); }
|
constexpr operator const std::string&() const { return value(); }
|
||||||
|
|
||||||
|
|
||||||
friend bool operator==(cmake_constant const& lhs, cmake_constant const& rhs)
|
friend bool operator==(cmake_constant const& lhs, cmake_constant const& rhs)
|
||||||
{
|
{
|
||||||
@@ -182,15 +182,13 @@ public:
|
|||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const cmake_constant ALWAYS;
|
static const cmake_constant ALWAYS;
|
||||||
static const cmake_constant LAZY;
|
static const cmake_constant LAZY;
|
||||||
static const cmake_constant NEVER;
|
static const cmake_constant NEVER;
|
||||||
|
|
||||||
|
public:
|
||||||
public:
|
|
||||||
conf_cmake();
|
conf_cmake();
|
||||||
|
|
||||||
// specify the value for CMAKE_INSTALL_MESSAGE
|
// specify the value for CMAKE_INSTALL_MESSAGE
|
||||||
@@ -204,56 +202,58 @@ public:
|
|||||||
//
|
//
|
||||||
std::string host() const;
|
std::string host() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cmake_constant read_cmake_constant(
|
cmake_constant
|
||||||
std::string_view key, std::vector<cmake_constant> const& allowed) const;
|
read_cmake_constant(std::string_view key,
|
||||||
};
|
std::vector<cmake_constant> const& allowed) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// options in [tools]
|
||||||
// options in [tools]
|
//
|
||||||
//
|
class conf_tools : public conf_section<fs::path> {
|
||||||
class conf_tools : public conf_section<fs::path>
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
conf_tools();
|
conf_tools();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// options in [transifex]
|
||||||
// options in [transifex]
|
//
|
||||||
//
|
class conf_transifex : public conf_section<std::string> {
|
||||||
class conf_transifex : public conf_section<std::string>
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
conf_transifex();
|
conf_transifex();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// options in [versions]
|
||||||
// options in [versions]
|
//
|
||||||
//
|
class conf_versions : public conf_section<std::string> {
|
||||||
class conf_versions : public conf_section<std::string>
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
conf_versions();
|
conf_versions();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// options in [translations]
|
||||||
|
//
|
||||||
|
class conf_translations : public conf_section<std::string> {
|
||||||
|
public:
|
||||||
|
conf_translations();
|
||||||
|
};
|
||||||
|
|
||||||
// options in [prebuilt]
|
// options in [prebuilt]
|
||||||
//
|
//
|
||||||
class conf_prebuilt : public conf_section<std::string>
|
class conf_prebuilt : public conf_section<std::string> {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
conf_prebuilt();
|
conf_prebuilt();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// options in [paths]
|
||||||
// options in [paths]
|
//
|
||||||
//
|
class conf_paths : public conf_section<fs::path> {
|
||||||
class conf_paths : public conf_section<fs::path>
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
conf_paths();
|
conf_paths();
|
||||||
|
|
||||||
#define VALUE(NAME) fs::path NAME() const { return get(#NAME); }
|
#define VALUE(NAME) \
|
||||||
|
fs::path NAME() const \
|
||||||
|
{ \
|
||||||
|
return get(#NAME); \
|
||||||
|
}
|
||||||
|
|
||||||
VALUE(third_party);
|
VALUE(third_party);
|
||||||
VALUE(prefix);
|
VALUE(prefix);
|
||||||
@@ -270,11 +270,10 @@ public:
|
|||||||
|
|
||||||
VALUE(install_dlls);
|
VALUE(install_dlls);
|
||||||
VALUE(install_loot);
|
VALUE(install_loot);
|
||||||
VALUE(install_plugins);
|
VALUE(install_extensions);
|
||||||
VALUE(install_stylesheets);
|
VALUE(install_stylesheets);
|
||||||
VALUE(install_licenses);
|
VALUE(install_licenses);
|
||||||
VALUE(install_pythoncore);
|
VALUE(install_pythoncore);
|
||||||
VALUE(install_translations);
|
|
||||||
|
|
||||||
VALUE(vs);
|
VALUE(vs);
|
||||||
VALUE(qt_install);
|
VALUE(qt_install);
|
||||||
@@ -286,20 +285,19 @@ public:
|
|||||||
VALUE(temp_dir);
|
VALUE(temp_dir);
|
||||||
|
|
||||||
#undef VALUE
|
#undef VALUE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// should be used as conf().global().whatever(), doesn't actually hold anything,
|
||||||
// should be used as conf().global().whatever(), doesn't actually hold anything,
|
// but it's better than a bunch of static functions
|
||||||
// but it's better than a bunch of static functions
|
//
|
||||||
//
|
class conf {
|
||||||
class conf
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
conf_global global();
|
conf_global global();
|
||||||
conf_task task(const std::vector<std::string>& names);
|
conf_task task(const std::vector<std::string>& names);
|
||||||
conf_cmake cmake();
|
conf_cmake cmake();
|
||||||
conf_tools tool();
|
conf_tools tool();
|
||||||
conf_transifex transifex();
|
conf_transifex transifex();
|
||||||
|
conf_translations translation();
|
||||||
conf_prebuilt prebuilt();
|
conf_prebuilt prebuilt();
|
||||||
conf_versions version();
|
conf_versions version();
|
||||||
conf_paths path();
|
conf_paths path();
|
||||||
@@ -307,6 +305,6 @@ public:
|
|||||||
// opens the log file, creates the directory if needed
|
// opens the log file, creates the directory if needed
|
||||||
//
|
//
|
||||||
void set_log_file();
|
void set_log_file();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+187
-214
File diff suppressed because it is too large
Load Diff
+59
-81
@@ -7,80 +7,66 @@
|
|||||||
// those are kept in this namespace so they don't leak all over the place;
|
// those are kept in this namespace so they don't leak all over the place;
|
||||||
// they're used directly by context::do_log() below
|
// they're used directly by context::do_log() below
|
||||||
|
|
||||||
namespace mob::details
|
namespace mob::details {
|
||||||
{
|
|
||||||
|
|
||||||
class mob::url;
|
class mob::url;
|
||||||
|
|
||||||
template <class T, class=void>
|
template <class T, class = void>
|
||||||
struct converter
|
struct converter {
|
||||||
{
|
static const T& convert(const T& t) { return t; }
|
||||||
static const T& convert(const T& t)
|
};
|
||||||
{
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct converter<std::wstring>
|
struct converter<std::wstring> {
|
||||||
{
|
|
||||||
static std::string convert(const std::wstring& s);
|
static std::string convert(const std::wstring& s);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct converter<fs::path>
|
struct converter<fs::path> {
|
||||||
{
|
|
||||||
static std::string convert(const fs::path& s);
|
static std::string convert(const fs::path& s);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct converter<url>
|
struct converter<url> {
|
||||||
{
|
|
||||||
static std::string convert(const url& u);
|
static std::string convert(const url& u);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct converter<T, std::enable_if_t<std::is_enum_v<T>>>
|
struct converter<T, std::enable_if_t<std::is_enum_v<T>>> {
|
||||||
{
|
|
||||||
static std::string convert(T e)
|
static std::string convert(T e)
|
||||||
{
|
{
|
||||||
return std::to_string(static_cast<std::underlying_type_t<T>>(e));
|
return std::to_string(static_cast<std::underlying_type_t<T>>(e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob::details
|
||||||
|
|
||||||
|
namespace mob {
|
||||||
|
|
||||||
namespace mob
|
class tool;
|
||||||
{
|
|
||||||
|
|
||||||
class tool;
|
// system error message
|
||||||
|
//
|
||||||
|
std::string error_message(DWORD e);
|
||||||
|
|
||||||
// system error message
|
// a logger with some context, this is passed around everywhere and knows which
|
||||||
//
|
// task and tool is currently running to get better context when logging
|
||||||
std::string error_message(DWORD e);
|
//
|
||||||
|
// each log must have a reason, `generic` can be used if no reason makes sense
|
||||||
|
//
|
||||||
// a logger with some context, this is passed around everywhere and knows which
|
// in places where there is no context available, there's a global one can that
|
||||||
// task and tool is currently running to get better context when logging
|
// be retrieved with gcx() for logging
|
||||||
//
|
//
|
||||||
// each log must have a reason, `generic` can be used if no reason makes sense
|
// all log functions will use fmt::format() internally, so they can be used
|
||||||
//
|
// like:
|
||||||
// in places where there is no context available, there's a global one can that
|
//
|
||||||
// be retrieved with gcx() for logging
|
// cx.log(context::generic, "eat more {}", "potatoes");
|
||||||
//
|
//
|
||||||
// all log functions will use fmt::format() internally, so they can be used
|
class context {
|
||||||
// like:
|
public:
|
||||||
//
|
|
||||||
// cx.log(context::generic, "eat more {}", "potatoes");
|
|
||||||
//
|
|
||||||
class context
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// reason for a log or bailing out
|
// reason for a log or bailing out
|
||||||
//
|
//
|
||||||
enum reason
|
enum reason {
|
||||||
{
|
|
||||||
// generic
|
// generic
|
||||||
generic,
|
generic,
|
||||||
|
|
||||||
@@ -120,8 +106,7 @@ public:
|
|||||||
// level of a log entry, `dump` should only be used for really verbose
|
// level of a log entry, `dump` should only be used for really verbose
|
||||||
// stuff that shouldn't be very useful, like curl's debugging logs
|
// stuff that shouldn't be very useful, like curl's debugging logs
|
||||||
//
|
//
|
||||||
enum class level
|
enum class level {
|
||||||
{
|
|
||||||
dump = 1,
|
dump = 1,
|
||||||
trace,
|
trace,
|
||||||
debug,
|
debug,
|
||||||
@@ -152,7 +137,6 @@ public:
|
|||||||
//
|
//
|
||||||
static void close_log_file();
|
static void close_log_file();
|
||||||
|
|
||||||
|
|
||||||
// creates a context for a task; the global context has no name
|
// creates a context for a task; the global context has no name
|
||||||
//
|
//
|
||||||
context(std::string task_name);
|
context(std::string task_name);
|
||||||
@@ -232,14 +216,13 @@ public:
|
|||||||
do_log(true, r, level::error, f, std::forward<Args>(args)...);
|
do_log(true, r, level::error, f, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// current task, may be empty
|
// current task, may be empty
|
||||||
std::string task_;
|
std::string task_;
|
||||||
|
|
||||||
// current tool, may be null
|
// current tool, may be null
|
||||||
const tool* tool_;
|
const tool* tool_;
|
||||||
|
|
||||||
|
|
||||||
// all logs above end up in here; if `bail` is true, this will throw a
|
// all logs above end up in here; if `bail` is true, this will throw a
|
||||||
// bailed exception after logging
|
// bailed exception after logging
|
||||||
//
|
//
|
||||||
@@ -250,17 +233,15 @@ private:
|
|||||||
if (!bail && !enabled(lv))
|
if (!bail && !enabled(lv))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
// formatting string
|
// formatting string
|
||||||
const std::string s = fmt::format(
|
const std::string s =
|
||||||
f, details::converter<std::decay_t<Args>>::convert(
|
fmt::format(f, details::converter<std::decay_t<Args>>::convert(
|
||||||
std::forward<Args>(args))...);
|
std::forward<Args>(args))...);
|
||||||
|
|
||||||
do_log_impl(bail, r, lv, s);
|
do_log_impl(bail, r, lv, s);
|
||||||
}
|
}
|
||||||
catch(std::exception&)
|
catch (std::exception&) {
|
||||||
{
|
|
||||||
// this is typically a bad format string, but there's not a lot
|
// this is typically a bad format string, but there's not a lot
|
||||||
// that can be done except logging to stderr and asserting
|
// that can be done except logging to stderr and asserting
|
||||||
|
|
||||||
@@ -273,8 +254,7 @@ private:
|
|||||||
std::wstring s;
|
std::wstring s;
|
||||||
|
|
||||||
const char* p = f;
|
const char* p = f;
|
||||||
while (*p)
|
while (*p) {
|
||||||
{
|
|
||||||
s += (wchar_t)*p;
|
s += (wchar_t)*p;
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
@@ -294,27 +274,25 @@ private:
|
|||||||
// formats the log line: adds the timestamp, task name and tool name, if
|
// formats the log line: adds the timestamp, task name and tool name, if
|
||||||
// any
|
// any
|
||||||
//
|
//
|
||||||
std::string_view make_log_string(
|
std::string_view make_log_string(reason r, level lv, std::string_view s) const;
|
||||||
reason r, level lv, std::string_view s) const;
|
|
||||||
|
|
||||||
// writes the given string to the console and the log file, and keeps all
|
// writes the given string to the console and the log file, and keeps all
|
||||||
// errors and warnings in global lists so they can be dumped just before mob
|
// errors and warnings in global lists so they can be dumped just before mob
|
||||||
// exits
|
// exits
|
||||||
//
|
//
|
||||||
void emit_log(level lv, std::string_view s) const;
|
void emit_log(level lv, std::string_view s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// global context, convenience
|
||||||
// global context, convenience
|
//
|
||||||
//
|
inline const context& gcx()
|
||||||
inline const context& gcx()
|
{
|
||||||
{
|
|
||||||
return *context::global();
|
return *context::global();
|
||||||
}
|
}
|
||||||
|
|
||||||
// called in main() just before mob exits, dumps all errors and warnings seen
|
// called in main() just before mob exits, dumps all errors and warnings seen
|
||||||
// during the build if the console log level was high enough
|
// during the build if the console log level was high enough
|
||||||
//
|
//
|
||||||
void dump_logs();
|
void dump_logs();
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+143
-177
File diff suppressed because it is too large
Load Diff
+19
-33
@@ -2,25 +2,18 @@
|
|||||||
|
|
||||||
#include "../utility.h"
|
#include "../utility.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
// a set of environment variables; copy-on-write because this gets copied a lot
|
// a set of environment variables; copy-on-write because this gets copied a lot
|
||||||
//
|
//
|
||||||
class env
|
class env {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
using map = std::map<std::wstring, std::wstring>;
|
using map = std::map<std::wstring, std::wstring>;
|
||||||
|
|
||||||
// used in set(); replaces, appends or prepends to a variable if it already
|
// used in set(); replaces, appends or prepends to a variable if it already
|
||||||
// exists
|
// exists
|
||||||
//
|
//
|
||||||
enum flags
|
enum flags { replace = 1, append, prepend };
|
||||||
{
|
|
||||||
replace = 1,
|
|
||||||
append,
|
|
||||||
prepend
|
|
||||||
};
|
|
||||||
|
|
||||||
// Visual Studio environment variables for 32-bit
|
// Visual Studio environment variables for 32-bit
|
||||||
//
|
//
|
||||||
@@ -34,7 +27,6 @@ public:
|
|||||||
//
|
//
|
||||||
static env vs(arch a);
|
static env vs(arch a);
|
||||||
|
|
||||||
|
|
||||||
// empty set
|
// empty set
|
||||||
//
|
//
|
||||||
env();
|
env();
|
||||||
@@ -58,8 +50,8 @@ public:
|
|||||||
|
|
||||||
// sets k=v
|
// sets k=v
|
||||||
//
|
//
|
||||||
env& set(std::string_view k, std::string_view v, flags f=replace);
|
env& set(std::string_view k, std::string_view v, flags f = replace);
|
||||||
env& set(std::wstring k, std::wstring v, flags f=replace);
|
env& set(std::wstring k, std::wstring v, flags f = replace);
|
||||||
|
|
||||||
// returns the variable' value, empty if not found
|
// returns the variable' value, empty if not found
|
||||||
//
|
//
|
||||||
@@ -74,11 +66,10 @@ public:
|
|||||||
//
|
//
|
||||||
void* get_unicode_pointers() const;
|
void* get_unicode_pointers() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// shared between copies
|
// shared between copies
|
||||||
//
|
//
|
||||||
struct data
|
struct data {
|
||||||
{
|
|
||||||
std::mutex m;
|
std::mutex m;
|
||||||
map vars;
|
map vars;
|
||||||
|
|
||||||
@@ -93,7 +84,6 @@ private:
|
|||||||
// when the data must be modified
|
// when the data must be modified
|
||||||
bool own_;
|
bool own_;
|
||||||
|
|
||||||
|
|
||||||
// creates the unicode strings
|
// creates the unicode strings
|
||||||
//
|
//
|
||||||
void create_sys() const;
|
void create_sys() const;
|
||||||
@@ -115,19 +105,15 @@ private:
|
|||||||
// value
|
// value
|
||||||
//
|
//
|
||||||
env& change_path(const std::vector<fs::path>& v, flags f);
|
env& change_path(const std::vector<fs::path>& v, flags f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// represents mob's environment variables
|
||||||
// represents mob's environment variables
|
//
|
||||||
//
|
struct this_env {
|
||||||
struct this_env
|
|
||||||
{
|
|
||||||
// sets a variable
|
// sets a variable
|
||||||
//
|
//
|
||||||
static void set(
|
static void set(const std::string& k, const std::string& v,
|
||||||
const std::string& k,
|
env::flags f = env::replace);
|
||||||
const std::string& v,
|
|
||||||
env::flags f=env::replace);
|
|
||||||
|
|
||||||
// changes PATH
|
// changes PATH
|
||||||
//
|
//
|
||||||
@@ -146,10 +132,10 @@ struct this_env
|
|||||||
//
|
//
|
||||||
static std::optional<std::string> get_opt(const std::string& k);
|
static std::optional<std::string> get_opt(const std::string& k);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// used by get() and get_opt(), does the actual work
|
// used by get() and get_opt(), does the actual work
|
||||||
//
|
//
|
||||||
static std::optional<std::wstring> get_impl(const std::string& k);
|
static std::optional<std::wstring> get_impl(const std::string& k);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+78
-121
@@ -1,65 +1,55 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "ini.h"
|
#include "ini.h"
|
||||||
#include "paths.h"
|
|
||||||
#include "context.h"
|
|
||||||
#include "env.h"
|
|
||||||
#include "conf.h"
|
|
||||||
#include "../tasks/task_manager.h"
|
#include "../tasks/task_manager.h"
|
||||||
#include "../utility/string.h"
|
#include "../utility/string.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "env.h"
|
||||||
|
#include "paths.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
template <class... Args>
|
template <class... Args>
|
||||||
void ini_error(
|
void ini_error(const ini_data& ini, std::size_t line, std::string_view f,
|
||||||
const ini_data& ini, std::size_t line, std::string_view f, Args&&... args)
|
Args&&... args)
|
||||||
{
|
|
||||||
gcx().bail_out(context::conf,
|
|
||||||
"{}:{}: {}",
|
|
||||||
path_to_utf8(ini.path), (line + 1),
|
|
||||||
fmt::format(f, std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ini_data::kv_map& ini_data::get_section(std::string_view name)
|
|
||||||
{
|
|
||||||
for (auto itor=sections.begin(); itor!=sections.end(); ++itor)
|
|
||||||
{
|
{
|
||||||
|
gcx().bail_out(context::conf, "{}:{}: {}", path_to_utf8(ini.path), (line + 1),
|
||||||
|
fmt::format(f, std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_data::kv_map& ini_data::get_section(std::string_view name)
|
||||||
|
{
|
||||||
|
for (auto itor = sections.begin(); itor != sections.end(); ++itor) {
|
||||||
if (itor->first == name)
|
if (itor->first == name)
|
||||||
return itor->second;
|
return itor->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
sections.push_back({std::string(name), kv_map()});
|
sections.push_back({std::string(name), kv_map()});
|
||||||
return sections.back().second;
|
return sections.back().second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ini_data::set(std::string_view section, std::string key, std::string value)
|
void ini_data::set(std::string_view section, std::string key, std::string value)
|
||||||
{
|
{
|
||||||
auto& s = get_section(section);
|
auto& s = get_section(section);
|
||||||
s.emplace(std::move(key), std::move(value));
|
s.emplace(std::move(key), std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string default_ini_filename()
|
||||||
|
{
|
||||||
std::string default_ini_filename()
|
|
||||||
{
|
|
||||||
return "mob.ini";
|
return "mob.ini";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<fs::path> find_inis(
|
std::vector<fs::path>
|
||||||
bool auto_detect, const std::vector<std::string>& from_cl, bool verbose)
|
find_inis(bool auto_detect, const std::vector<std::string>& from_cl, bool verbose)
|
||||||
{
|
{
|
||||||
// the string is just for verbose
|
// the string is just for verbose
|
||||||
std::vector<std::pair<std::string, fs::path>> v;
|
std::vector<std::pair<std::string, fs::path>> v;
|
||||||
|
|
||||||
// adds a path to the vector; if the path already exists, moves it to
|
// adds a path to the vector; if the path already exists, moves it to
|
||||||
// the last element
|
// the last element
|
||||||
auto add_or_move_up = [&](std::string where, fs::path p)
|
auto add_or_move_up = [&](std::string where, fs::path p) {
|
||||||
{
|
for (auto itor = v.begin(); itor != v.end(); ++itor) {
|
||||||
for (auto itor=v.begin(); itor!=v.end(); ++itor)
|
if (fs::equivalent(p, itor->second)) {
|
||||||
{
|
|
||||||
if (fs::equivalent(p, itor->second))
|
|
||||||
{
|
|
||||||
auto pair = std::move(*itor);
|
auto pair = std::move(*itor);
|
||||||
v.erase(itor);
|
v.erase(itor);
|
||||||
v.push_back({where + ", was " + pair.first, p});
|
v.push_back({where + ", was " + pair.first, p});
|
||||||
@@ -71,10 +61,8 @@ std::vector<fs::path> find_inis(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// whether the ini is already in the list
|
// whether the ini is already in the list
|
||||||
auto ini_already_found = [&](auto&& p)
|
auto ini_already_found = [&](auto&& p) {
|
||||||
{
|
for (auto itor = v.begin(); itor != v.end(); ++itor) {
|
||||||
for (auto itor=v.begin(); itor!=v.end(); ++itor)
|
|
||||||
{
|
|
||||||
if (fs::equivalent(p, itor->second))
|
if (fs::equivalent(p, itor->second))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -82,14 +70,11 @@ std::vector<fs::path> find_inis(
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
fs::path master;
|
fs::path master;
|
||||||
|
|
||||||
// auto detect from exe directory
|
// auto detect from exe directory
|
||||||
if (auto_detect)
|
if (auto_detect) {
|
||||||
{
|
if (verbose) {
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
const auto r = find_root(verbose);
|
const auto r = find_root(verbose);
|
||||||
u8cout << "root is " << path_to_utf8(r) << "\n";
|
u8cout << "root is " << path_to_utf8(r) << "\n";
|
||||||
}
|
}
|
||||||
@@ -102,18 +87,14 @@ std::vector<fs::path> find_inis(
|
|||||||
v.push_back({"master", master});
|
v.push_back({"master", master});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MOBINI environment variable
|
// MOBINI environment variable
|
||||||
if (auto e=this_env::get_opt("MOBINI"))
|
if (auto e = this_env::get_opt("MOBINI")) {
|
||||||
{
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
u8cout << "found env MOBINI: '" << *e << "'\n";
|
u8cout << "found env MOBINI: '" << *e << "'\n";
|
||||||
|
|
||||||
for (auto&& i : split(*e, ";"))
|
for (auto&& i : split(*e, ";")) {
|
||||||
{
|
|
||||||
auto p = fs::path(i);
|
auto p = fs::path(i);
|
||||||
if (!fs::exists(p))
|
if (!fs::exists(p)) {
|
||||||
{
|
|
||||||
u8cerr << "ini from env MOBINI " << i << " not found\n";
|
u8cerr << "ini from env MOBINI " << i << " not found\n";
|
||||||
throw bailed();
|
throw bailed();
|
||||||
}
|
}
|
||||||
@@ -127,24 +108,20 @@ std::vector<fs::path> find_inis(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// auto detect from the current directory
|
// auto detect from the current directory
|
||||||
if (auto_detect)
|
if (auto_detect) {
|
||||||
{
|
|
||||||
MOB_ASSERT(!master.empty());
|
MOB_ASSERT(!master.empty());
|
||||||
|
|
||||||
auto cwd = fs::current_path();
|
auto cwd = fs::current_path();
|
||||||
|
|
||||||
while (!cwd.empty())
|
while (!cwd.empty()) {
|
||||||
{
|
|
||||||
const auto in_cwd = cwd / default_ini_filename();
|
const auto in_cwd = cwd / default_ini_filename();
|
||||||
|
|
||||||
if (fs::exists(in_cwd) && !ini_already_found(in_cwd))
|
if (fs::exists(in_cwd) && !ini_already_found(in_cwd)) {
|
||||||
{
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
u8cout << "also found in cwd " << path_to_utf8(in_cwd) << "\n";
|
u8cout << "also found in cwd " << path_to_utf8(in_cwd) << "\n";
|
||||||
|
|
||||||
v.push_back({ "cwd", fs::canonical(in_cwd) });
|
v.push_back({"cwd", fs::canonical(in_cwd)});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,13 +133,10 @@ std::vector<fs::path> find_inis(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// command line
|
// command line
|
||||||
for (auto&& i : from_cl)
|
for (auto&& i : from_cl) {
|
||||||
{
|
|
||||||
auto p = fs::path(i);
|
auto p = fs::path(i);
|
||||||
if (!fs::exists(p))
|
if (!fs::exists(p)) {
|
||||||
{
|
|
||||||
u8cerr << "ini " << i << " not found\n";
|
u8cerr << "ini " << i << " not found\n";
|
||||||
throw bailed();
|
throw bailed();
|
||||||
}
|
}
|
||||||
@@ -175,31 +149,27 @@ std::vector<fs::path> find_inis(
|
|||||||
add_or_move_up("cl", p);
|
add_or_move_up("cl", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
u8cout << "\nhigher number overrides lower\n";
|
u8cout << "\nhigher number overrides lower\n";
|
||||||
|
|
||||||
for (std::size_t i=0; i<v.size(); ++i)
|
for (std::size_t i = 0; i < v.size(); ++i) {
|
||||||
|
u8cout << " " << (i + 1) << ") " << path_to_utf8(v[i].second) << " ("
|
||||||
|
<< v[i].first << ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map(v, [&](auto&& p) {
|
||||||
|
return p.second;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> read_ini(const fs::path& ini)
|
||||||
{
|
{
|
||||||
u8cout
|
|
||||||
<< " " << (i + 1) << ") "
|
|
||||||
<< path_to_utf8(v[i].second) << " (" << v[i].first << ")\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return map(v, [&](auto&& p){ return p.second; });
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> read_ini(const fs::path& ini)
|
|
||||||
{
|
|
||||||
std::ifstream in(ini);
|
std::ifstream in(ini);
|
||||||
|
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(in, line);
|
std::getline(in, line);
|
||||||
trim(line);
|
trim(line);
|
||||||
@@ -214,12 +184,11 @@ std::vector<std::string> read_ini(const fs::path& ini)
|
|||||||
gcx().bail_out(context::conf, "failed to read ini {}", ini);
|
gcx().bail_out(context::conf, "failed to read ini {}", ini);
|
||||||
|
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_line(
|
void parse_line(ini_data& ini, std::size_t i, const std::string& line,
|
||||||
ini_data& ini, std::size_t i, const std::string& line,
|
|
||||||
const std::string& task, const std::string& section)
|
const std::string& task, const std::string& section)
|
||||||
{
|
{
|
||||||
auto& tm = task_manager::instance();
|
auto& tm = task_manager::instance();
|
||||||
|
|
||||||
const auto sep = line.find("=");
|
const auto sep = line.find("=");
|
||||||
@@ -232,54 +201,46 @@ void parse_line(
|
|||||||
if (k.empty())
|
if (k.empty())
|
||||||
ini_error(ini, i, "bad line '{}'", line);
|
ini_error(ini, i, "bad line '{}'", line);
|
||||||
|
|
||||||
if (section == "aliases")
|
if (section == "aliases") {
|
||||||
{
|
|
||||||
tm.add_alias(k, split_quoted(v, " "));
|
tm.add_alias(k, split_quoted(v, " "));
|
||||||
}
|
}
|
||||||
else if (task.empty())
|
else if (task.empty()) {
|
||||||
{
|
|
||||||
ini.set(section, k, v);
|
ini.set(section, k, v);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
if (!tm.valid_task_name(task))
|
if (!tm.valid_task_name(task))
|
||||||
ini_error(ini, i, "no task matching '{}' found", task);
|
ini_error(ini, i, "no task matching '{}' found", task);
|
||||||
|
|
||||||
ini.set(task + ":" + section, k, v);
|
ini.set(task + ":" + section, k, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_section(
|
void parse_section(ini_data& ini, std::size_t& i,
|
||||||
ini_data& ini, std::size_t& i, const std::vector<std::string>& lines,
|
const std::vector<std::string>& lines,
|
||||||
const std::string& section_string)
|
const std::string& section_string)
|
||||||
{
|
{
|
||||||
std::string task, section;
|
std::string task, section;
|
||||||
|
|
||||||
const auto col = section_string.find(":");
|
const auto col = section_string.find(":");
|
||||||
|
|
||||||
if (col == std::string::npos)
|
if (col == std::string::npos) {
|
||||||
{
|
|
||||||
section = section_string;
|
section = section_string;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
task = section_string.substr(0, col);
|
task = section_string.substr(0, col);
|
||||||
section = section_string.substr(col + 1);
|
section = section_string.substr(col + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
if (i >= lines.size() || lines[i][0] == '[')
|
if (i >= lines.size() || lines[i][0] == '[')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const auto& line = lines[i];
|
const auto& line = lines[i];
|
||||||
|
|
||||||
// empty or comment
|
// empty or comment
|
||||||
if (line.empty() || line[0] == '#' || line[0] == ';')
|
if (line.empty() || line[0] == '#' || line[0] == ';') {
|
||||||
{
|
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -287,10 +248,10 @@ void parse_section(
|
|||||||
parse_line(ini, i, line, task, section);
|
parse_line(ini, i, line, task, section);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ini_data parse_ini(const fs::path& path)
|
ini_data parse_ini(const fs::path& path)
|
||||||
{
|
{
|
||||||
gcx().debug(context::conf, "using ini at {}", path);
|
gcx().debug(context::conf, "using ini at {}", path);
|
||||||
|
|
||||||
ini_data ini;
|
ini_data ini;
|
||||||
@@ -299,32 +260,28 @@ ini_data parse_ini(const fs::path& path)
|
|||||||
const auto lines = read_ini(path);
|
const auto lines = read_ini(path);
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
if (i >= lines.size())
|
if (i >= lines.size())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const auto& line = lines[i];
|
const auto& line = lines[i];
|
||||||
|
|
||||||
// empty or comment
|
// empty or comment
|
||||||
if (line.empty() || line[0] == '#' || line[0] == ';')
|
if (line.empty() || line[0] == '#' || line[0] == ';') {
|
||||||
{
|
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.starts_with("[") && line.ends_with("]"))
|
if (line.starts_with("[") && line.ends_with("]")) {
|
||||||
{
|
|
||||||
const std::string name = line.substr(1, line.size() - 2);
|
const std::string name = line.substr(1, line.size() - 2);
|
||||||
parse_section(ini, i, lines, name);
|
parse_section(ini, i, lines, name);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
ini_error(ini, i, "bad line '{}'", line);
|
ini_error(ini, i, "bad line '{}'", line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ini;
|
return ini;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+9
-13
@@ -1,17 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
std::string default_ini_filename();
|
std::string default_ini_filename();
|
||||||
|
|
||||||
std::vector<fs::path> find_inis(
|
std::vector<fs::path>
|
||||||
bool auto_detect, const std::vector<std::string>& from_cl,
|
find_inis(bool auto_detect, const std::vector<std::string>& from_cl, bool verbose);
|
||||||
bool verbose);
|
|
||||||
|
|
||||||
|
struct ini_data {
|
||||||
struct ini_data
|
|
||||||
{
|
|
||||||
using alias_patterns = std::vector<std::string>;
|
using alias_patterns = std::vector<std::string>;
|
||||||
using aliases_map = std::map<std::string, alias_patterns>;
|
using aliases_map = std::map<std::string, alias_patterns>;
|
||||||
|
|
||||||
@@ -24,9 +20,9 @@ struct ini_data
|
|||||||
|
|
||||||
kv_map& get_section(std::string_view name);
|
kv_map& get_section(std::string_view name);
|
||||||
void set(std::string_view section, std::string key, std::string value);
|
void set(std::string_view section, std::string key, std::string value);
|
||||||
};
|
};
|
||||||
|
|
||||||
ini_data parse_ini(const fs::path& ini);
|
ini_data parse_ini(const fs::path& ini);
|
||||||
std::string default_ini_filename();
|
std::string default_ini_filename();
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user