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 =
|
||||||
|
|||||||
+68
-73
@@ -1,90 +1,94 @@
|
|||||||
#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
|
return {"build", "builds tasks"};
|
||||||
{
|
|
||||||
"build",
|
|
||||||
"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";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -153,8 +152,7 @@ void build_command::convert_cl_to_conf()
|
|||||||
|
|
||||||
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,8 +163,7 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -181,10 +178,8 @@ 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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,4 +192,4 @@ void build_command::terminate_msbuild()
|
|||||||
system("taskkill /im msbuild.exe /f > NUL 2>&1");
|
system("taskkill /im msbuild.exe /f > NUL 2>&1");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+18
-36
@@ -1,22 +1,14 @@
|
|||||||
#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
|
return {"cmake", "runs cmake in a directory"};
|
||||||
{
|
|
||||||
"cmake",
|
|
||||||
"runs cmake in a directory"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clipp::group cmake_command::do_group()
|
clipp::group cmake_command::do_group()
|
||||||
@@ -24,38 +16,29 @@ 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_);
|
||||||
@@ -75,9 +58,8 @@ int cmake_command::do_run()
|
|||||||
|
|
||||||
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
|
||||||
|
|||||||
+57
-110
@@ -1,15 +1,14 @@
|
|||||||
#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
|
||||||
{
|
{
|
||||||
@@ -25,23 +24,16 @@ void set_sigint_handler()
|
|||||||
::SetConsoleCtrlHandler(mob::signal_handler, TRUE);
|
::SetConsoleCtrlHandler(mob::signal_handler, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void help(const clipp::group& g, const std::string& more)
|
void help(const clipp::group& g, const std::string& more)
|
||||||
{
|
{
|
||||||
auto usage_df = clipp::doc_formatting()
|
auto usage_df = clipp::doc_formatting().first_column(4).doc_column(30);
|
||||||
.first_column(4)
|
|
||||||
.doc_column(30);
|
|
||||||
|
|
||||||
auto options_df = clipp::doc_formatting()
|
auto options_df = clipp::doc_formatting().first_column(4).doc_column(30);
|
||||||
.first_column(4)
|
|
||||||
.doc_column(30);
|
|
||||||
|
|
||||||
u8cout
|
u8cout << "Usage:\n"
|
||||||
<< "Usage:\n" << clipp::usage_lines(g, "mob", usage_df)
|
<< clipp::usage_lines(g, "mob", usage_df) << "\n\n"
|
||||||
<< "\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";
|
||||||
|
|
||||||
@@ -49,49 +41,42 @@ void help(const clipp::group& g, const std::string& more)
|
|||||||
u8cout << "\n" << more << "\n";
|
u8cout << "\n" << more << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
command::common_options command::common;
|
command::common_options command::common;
|
||||||
|
|
||||||
command::command(flags f)
|
command::command(flags f) : picked_(false), help_(false), flags_(f), code_() {}
|
||||||
: picked_(false), help_(false), flags_(f), code_()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
clipp::group command::common_options_group()
|
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";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,17 +107,13 @@ void command::convert_cl_to_conf()
|
|||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,22 +131,18 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,14 +168,12 @@ int command::prepare_options(bool 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;
|
||||||
@@ -232,20 +207,14 @@ int command::load_options()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
command::meta_t version_command::meta() const
|
command::meta_t version_command::meta() const
|
||||||
{
|
{
|
||||||
return
|
return {"version", "shows the version"};
|
||||||
{
|
|
||||||
"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()
|
||||||
@@ -254,14 +223,9 @@ int version_command::do_run()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
command::meta_t help_command::meta() const
|
command::meta_t help_command::meta() const
|
||||||
{
|
{
|
||||||
return
|
return {"help", "shows this message"};
|
||||||
{
|
|
||||||
"help",
|
|
||||||
"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)
|
||||||
@@ -276,8 +240,7 @@ void help_command::set_commands(const std::vector<std::shared_ptr<command>>& v)
|
|||||||
|
|
||||||
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()
|
||||||
@@ -288,8 +251,7 @@ int help_command::do_run()
|
|||||||
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"
|
||||||
@@ -309,29 +273,19 @@ int help_command::do_run()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options_command::options_command() : command(requires_options) {}
|
||||||
options_command::options_command()
|
|
||||||
: command(requires_options)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
command::meta_t options_command::meta() const
|
command::meta_t options_command::meta() const
|
||||||
{
|
{
|
||||||
return
|
return {"options", "lists all options and their values from the inis"};
|
||||||
{
|
|
||||||
"options",
|
|
||||||
"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()
|
||||||
@@ -347,24 +301,17 @@ std::string options_command::do_doc()
|
|||||||
return "Lists the final value of all options found by loading the INIs.";
|
return "Lists the final value of all options found by loading the INIs.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
command::meta_t inis_command::meta() const
|
command::meta_t inis_command::meta() const
|
||||||
{
|
{
|
||||||
return
|
return {"inis", "lists the INIs used by mob"};
|
||||||
{
|
|
||||||
"inis",
|
|
||||||
"lists the INIs used by mob"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clipp::group inis_command::do_group()
|
clipp::group inis_command::do_group()
|
||||||
{
|
{
|
||||||
return clipp::group(
|
return clipp::group(clipp::command("inis").set(picked_),
|
||||||
clipp::command("inis").set(picked_),
|
|
||||||
|
|
||||||
(clipp::option("-h", "--help") >> help_)
|
(clipp::option("-h", "--help") >> help_) %
|
||||||
% ("shows this message")
|
("shows this message"));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int inis_command::do_run()
|
int inis_command::do_run()
|
||||||
@@ -377,4 +324,4 @@ std::string inis_command::do_doc()
|
|||||||
return "Shows which INIs are found.";
|
return "Shows which INIs are found.";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+31
-87
@@ -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,7 +60,6 @@ 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;
|
||||||
@@ -74,8 +67,7 @@ public:
|
|||||||
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,14 +79,12 @@ 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
|
||||||
@@ -140,17 +130,14 @@ 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;
|
||||||
|
|
||||||
@@ -159,11 +146,9 @@ protected:
|
|||||||
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);
|
||||||
@@ -176,11 +161,9 @@ 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;
|
||||||
@@ -191,11 +174,9 @@ protected:
|
|||||||
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();
|
||||||
|
|
||||||
@@ -225,18 +206,15 @@ 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();
|
||||||
|
|
||||||
@@ -248,27 +226,24 @@ protected:
|
|||||||
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);
|
||||||
|
|
||||||
@@ -277,11 +252,9 @@ private:
|
|||||||
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;
|
||||||
|
|
||||||
@@ -298,11 +271,9 @@ private:
|
|||||||
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;
|
||||||
@@ -320,13 +291,7 @@ protected:
|
|||||||
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;
|
||||||
@@ -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,19 +319,17 @@ 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;
|
||||||
@@ -378,14 +340,7 @@ protected:
|
|||||||
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_;
|
||||||
@@ -412,11 +367,9 @@ private:
|
|||||||
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;
|
||||||
@@ -434,11 +387,9 @@ private:
|
|||||||
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;
|
||||||
|
|
||||||
@@ -448,11 +399,9 @@ protected:
|
|||||||
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;
|
||||||
@@ -464,12 +413,7 @@ protected:
|
|||||||
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_;
|
||||||
@@ -482,4 +426,4 @@ private:
|
|||||||
void do_build();
|
void do_build();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+54
-92
@@ -1,23 +1,15 @@
|
|||||||
#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
|
return {"git", "manages the git repos"};
|
||||||
{
|
|
||||||
"git",
|
|
||||||
"manages the git repos"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clipp::group git_command::do_group()
|
clipp::group git_command::do_group()
|
||||||
@@ -25,101 +17,82 @@ 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_)
|
switch (mode_) {
|
||||||
{
|
case modes::set_remotes: {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -135,8 +108,7 @@ int git_command::do_run()
|
|||||||
|
|
||||||
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"
|
||||||
@@ -160,15 +132,13 @@ std::string git_command::do_doc()
|
|||||||
|
|
||||||
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_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,25 +149,22 @@ void git_command::do_set_remotes(const fs::path& r)
|
|||||||
|
|
||||||
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_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,15 +182,13 @@ void git_command::do_ignore_ts()
|
|||||||
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_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,8 +203,7 @@ 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;
|
||||||
@@ -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;
|
||||||
|
|
||||||
@@ -282,4 +244,4 @@ std::vector<fs::path> git_command::get_repos() const
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+18
-35
@@ -1,19 +1,14 @@
|
|||||||
#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
|
return {"list", "lists available tasks"};
|
||||||
{
|
|
||||||
"list",
|
|
||||||
"lists available tasks"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clipp::group list_command::do_group()
|
clipp::group list_command::do_group()
|
||||||
@@ -21,35 +16,28 @@ 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,27 +47,22 @@ 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))
|
||||||
@@ -97,4 +80,4 @@ void list_command::dump_aliases() const
|
|||||||
u8cout << " - " << k << ": " << join(patterns, ", ") << "\n";
|
u8cout << " - " << k << ": " << join(patterns, ", ") << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+70
-115
@@ -1,12 +1,11 @@
|
|||||||
#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)
|
||||||
{
|
{
|
||||||
@@ -14,25 +13,16 @@ std::string read_file(const fs::path& 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(requires_options | handle_sigint)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
command::meta_t pr_command::meta() const
|
command::meta_t pr_command::meta() const
|
||||||
{
|
{
|
||||||
return
|
return {"pr", "applies changes from PRs"};
|
||||||
{
|
|
||||||
"pr",
|
|
||||||
"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"
|
||||||
@@ -48,21 +38,19 @@ std::string pr_command::do_doc()
|
|||||||
|
|
||||||
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()
|
||||||
@@ -82,15 +70,14 @@ int pr_command::do_run()
|
|||||||
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,8 +90,7 @@ 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 {};
|
||||||
}
|
}
|
||||||
@@ -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,8 +131,7 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -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,15 +167,14 @@ 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)
|
||||||
@@ -214,18 +192,19 @@ 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;
|
||||||
|
|
||||||
@@ -233,10 +212,8 @@ std::vector<pr_command::pr_info> pr_command::search_prs(
|
|||||||
"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 {};
|
||||||
}
|
}
|
||||||
@@ -334,42 +297,35 @@ pr_command::pr_info pr_command::get_pr_info(
|
|||||||
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,13 +346,13 @@ 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";
|
||||||
@@ -406,4 +361,4 @@ std::vector<pr_command::pr_info> pr_command::validate_prs(
|
|||||||
return okay_prs;
|
return okay_prs;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+113
-175
File diff suppressed because it is too large
Load Diff
+41
-66
@@ -1,27 +1,19 @@
|
|||||||
#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
|
return {"tx", "manages transifex translations"};
|
||||||
{
|
|
||||||
"tx",
|
|
||||||
"manages transifex translations"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clipp::group tx_command::do_group()
|
clipp::group tx_command::do_group()
|
||||||
@@ -29,50 +21,43 @@ 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()
|
||||||
@@ -100,8 +85,7 @@ void tx_command::convert_cl_to_conf()
|
|||||||
|
|
||||||
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;
|
||||||
@@ -121,8 +105,7 @@ int tx_command::do_run()
|
|||||||
|
|
||||||
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"
|
||||||
@@ -137,17 +120,14 @@ std::string tx_command::do_doc()
|
|||||||
|
|
||||||
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)
|
||||||
@@ -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)
|
||||||
@@ -210,4 +185,4 @@ void tx_command::do_build()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+117
-177
File diff suppressed because it is too large
Load Diff
+61
-63
@@ -3,37 +3,37 @@
|
|||||||
// 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
|
// reads options from the given inis and option strings, resolves all the paths
|
||||||
// and necessary tools, also adds a couple of things to PATH
|
// and necessary tools, also adds a couple of things to PATH
|
||||||
//
|
//
|
||||||
void init_options(
|
void init_options(const std::vector<fs::path>& inis,
|
||||||
const std::vector<fs::path>& inis, const std::vector<std::string>& opts);
|
const std::vector<std::string>& opts);
|
||||||
|
|
||||||
// checks some of the options once everything is loaded, returns false if
|
// checks some of the options once everything is loaded, returns false if
|
||||||
// something's wrong
|
// something's wrong
|
||||||
@@ -44,32 +44,36 @@ bool verify_options();
|
|||||||
//
|
//
|
||||||
std::vector<std::string> format_options();
|
std::vector<std::string> format_options();
|
||||||
|
|
||||||
|
|
||||||
// base class for all conf structs
|
// base class for all conf structs
|
||||||
//
|
//
|
||||||
template <class DefaultType>
|
template <class DefaultType>
|
||||||
class conf_section
|
class conf_section {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
DefaultType get(std::string_view key) const
|
DefaultType get(std::string_view key,
|
||||||
|
std::optional<DefaultType> default_ = {}) 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)
|
||||||
@@ -78,10 +82,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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_; }
|
||||||
|
|
||||||
@@ -89,11 +90,9 @@ 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();
|
||||||
|
|
||||||
@@ -112,11 +111,9 @@ public:
|
|||||||
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);
|
||||||
|
|
||||||
@@ -144,8 +141,14 @@ 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_;
|
||||||
@@ -153,11 +156,9 @@ private:
|
|||||||
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_;
|
||||||
@@ -173,7 +174,6 @@ public:
|
|||||||
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)
|
||||||
{
|
{
|
||||||
return lhs.is_equivalent(rhs.value());
|
return lhs.is_equivalent(rhs.value());
|
||||||
@@ -182,14 +182,12 @@ 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();
|
||||||
|
|
||||||
@@ -205,55 +203,57 @@ 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);
|
||||||
@@ -288,18 +287,17 @@ public:
|
|||||||
#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();
|
||||||
@@ -309,4 +307,4 @@ public:
|
|||||||
void set_log_file();
|
void set_log_file();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+73
-100
@@ -1,12 +1,11 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "conf.h"
|
|
||||||
#include "../utility.h"
|
|
||||||
#include "../tasks/task.h"
|
#include "../tasks/task.h"
|
||||||
#include "../tools/tools.h"
|
#include "../tools/tools.h"
|
||||||
|
#include "../utility.h"
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
namespace mob::details
|
namespace mob::details {
|
||||||
{
|
|
||||||
|
|
||||||
std::string converter<std::wstring>::convert(const std::wstring& s)
|
std::string converter<std::wstring>::convert(const std::wstring& s)
|
||||||
{
|
{
|
||||||
@@ -23,11 +22,9 @@ std::string converter<url>::convert(const url& u)
|
|||||||
return u.string();
|
return u.string();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob::details
|
||||||
|
|
||||||
|
namespace mob {
|
||||||
namespace mob
|
|
||||||
{
|
|
||||||
|
|
||||||
// timestamps are relative to this
|
// timestamps are relative to this
|
||||||
static hr_clock::time_point g_start_time = hr_clock::now();
|
static hr_clock::time_point g_start_time = hr_clock::now();
|
||||||
@@ -42,13 +39,11 @@ static handle_ptr g_log_file;
|
|||||||
// global output mutex to avoid interleaving, but also mixing colors
|
// global output mutex to avoid interleaving, but also mixing colors
|
||||||
static std::mutex g_mutex;
|
static std::mutex g_mutex;
|
||||||
|
|
||||||
|
|
||||||
// returns the color associated with the given level
|
// returns the color associated with the given level
|
||||||
//
|
//
|
||||||
console_color level_color(context::level lv)
|
console_color level_color(context::level lv)
|
||||||
{
|
{
|
||||||
switch (lv)
|
switch (lv) {
|
||||||
{
|
|
||||||
case context::level::dump:
|
case context::level::dump:
|
||||||
case context::level::trace:
|
case context::level::trace:
|
||||||
case context::level::debug:
|
case context::level::debug:
|
||||||
@@ -70,21 +65,33 @@ console_color level_color(context::level lv)
|
|||||||
//
|
//
|
||||||
const char* reason_string(context::reason r)
|
const char* reason_string(context::reason r)
|
||||||
{
|
{
|
||||||
switch (r)
|
switch (r) {
|
||||||
{
|
case context::bypass:
|
||||||
case context::bypass: return "bypass";
|
return "bypass";
|
||||||
case context::redownload: return "re-dl";
|
case context::redownload:
|
||||||
case context::rebuild: return "re-bd";
|
return "re-dl";
|
||||||
case context::reextract: return "re-ex";
|
case context::rebuild:
|
||||||
case context::interruption: return "int";
|
return "re-bd";
|
||||||
case context::cmd: return "cmd";
|
case context::reextract:
|
||||||
case context::std_out: return "stdout";
|
return "re-ex";
|
||||||
case context::std_err: return "stderr";
|
case context::interruption:
|
||||||
case context::fs: return (conf().global().dry() ? "fs-dry" : "fs");
|
return "int";
|
||||||
case context::net: return "net";
|
case context::cmd:
|
||||||
case context::generic: return "";
|
return "cmd";
|
||||||
case context::conf: return "conf";
|
case context::std_out:
|
||||||
default: return "?";
|
return "stdout";
|
||||||
|
case context::std_err:
|
||||||
|
return "stderr";
|
||||||
|
case context::fs:
|
||||||
|
return (conf().global().dry() ? "fs-dry" : "fs");
|
||||||
|
case context::net:
|
||||||
|
return "net";
|
||||||
|
case context::generic:
|
||||||
|
return "";
|
||||||
|
case context::conf:
|
||||||
|
return "conf";
|
||||||
|
default:
|
||||||
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,15 +101,11 @@ std::string error_message(DWORD id)
|
|||||||
{
|
{
|
||||||
wchar_t* message = nullptr;
|
wchar_t* message = nullptr;
|
||||||
|
|
||||||
const auto ret = FormatMessageW(
|
const auto ret =
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
NULL,
|
NULL, id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
id,
|
reinterpret_cast<LPWSTR>(&message), 0, NULL);
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
reinterpret_cast<LPWSTR>(&message),
|
|
||||||
0, NULL);
|
|
||||||
|
|
||||||
std::wstring s;
|
std::wstring s;
|
||||||
|
|
||||||
@@ -114,7 +117,8 @@ std::string error_message(DWORD id)
|
|||||||
if (ret == 0 || !message) {
|
if (ret == 0 || !message) {
|
||||||
// error message not found, just use the hex error code
|
// error message not found, just use the hex error code
|
||||||
s = oss.str();
|
s = oss.str();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// FormatMessage() includes a newline, trim it and put the hex code too
|
// FormatMessage() includes a newline, trim it and put the hex code too
|
||||||
s = trim_copy(message) + L" (" + oss.str() + L")";
|
s = trim_copy(message) + L" (" + oss.str() + L")";
|
||||||
}
|
}
|
||||||
@@ -141,8 +145,7 @@ std::string_view timestamp_string()
|
|||||||
const auto frac = static_cast<float>(ms.count()) / 1000.0;
|
const auto frac = static_cast<float>(ms.count()) / 1000.0;
|
||||||
|
|
||||||
// to string with 2 digits precision
|
// to string with 2 digits precision
|
||||||
const auto r = std::to_chars(
|
const auto r = std::to_chars(std::begin(buffer), std::end(buffer), frac,
|
||||||
std::begin(buffer), std::end(buffer), frac,
|
|
||||||
std::chars_format::fixed, 2);
|
std::chars_format::fixed, 2);
|
||||||
|
|
||||||
if (r.ec != std::errc())
|
if (r.ec != std::errc())
|
||||||
@@ -159,8 +162,7 @@ std::string_view timestamp_string()
|
|||||||
//
|
//
|
||||||
bool log_enabled(context::level lv, int conf_lv)
|
bool log_enabled(context::level lv, int conf_lv)
|
||||||
{
|
{
|
||||||
switch (lv)
|
switch (lv) {
|
||||||
{
|
|
||||||
case context::level::dump:
|
case context::level::dump:
|
||||||
return conf_lv > 5;
|
return conf_lv > 5;
|
||||||
|
|
||||||
@@ -192,12 +194,9 @@ bool log_enabled(context::level lv, int conf_lv)
|
|||||||
//
|
//
|
||||||
bool should_dump_logs()
|
bool should_dump_logs()
|
||||||
{
|
{
|
||||||
return log_enabled(
|
return log_enabled(context::level::debug, conf().global().output_log_level());
|
||||||
context::level::debug,
|
|
||||||
conf().global().output_log_level());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
context::context(std::string task_name)
|
context::context(std::string task_name)
|
||||||
: task_(std::move(task_name)), tool_(nullptr)
|
: task_(std::move(task_name)), tool_(nullptr)
|
||||||
{
|
{
|
||||||
@@ -218,8 +217,7 @@ bool context::enabled(level lv)
|
|||||||
{
|
{
|
||||||
// a log level is enabled if it's included in either the console or the log
|
// a log level is enabled if it's included in either the console or the log
|
||||||
// file, which have independent levels
|
// file, which have independent levels
|
||||||
const int minimum_log_level = std::max(
|
const int minimum_log_level = std::max(mob::conf().global().output_log_level(),
|
||||||
mob::conf().global().output_log_level(),
|
|
||||||
mob::conf().global().file_log_level());
|
mob::conf().global().file_log_level());
|
||||||
|
|
||||||
return log_enabled(lv, minimum_log_level);
|
return log_enabled(lv, minimum_log_level);
|
||||||
@@ -227,21 +225,18 @@ bool context::enabled(level lv)
|
|||||||
|
|
||||||
void context::set_log_file(const fs::path& p)
|
void context::set_log_file(const fs::path& p)
|
||||||
{
|
{
|
||||||
if (!mob::conf().global().dry() && !p.empty())
|
if (!mob::conf().global().dry() && !p.empty()) {
|
||||||
{
|
|
||||||
// creating directory
|
// creating directory
|
||||||
if (!exists(p.parent_path()))
|
if (!exists(p.parent_path()))
|
||||||
op::create_directories(gcx(), mob::conf().path().prefix());
|
op::create_directories(gcx(), mob::conf().path().prefix());
|
||||||
|
|
||||||
HANDLE h = CreateFileW(
|
HANDLE h = CreateFileW(p.native().c_str(), GENERIC_WRITE, FILE_SHARE_READ,
|
||||||
p.native().c_str(), GENERIC_WRITE, FILE_SHARE_READ,
|
|
||||||
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
{
|
|
||||||
const auto e = GetLastError();
|
const auto e = GetLastError();
|
||||||
gcx().bail_out(context::generic,
|
gcx().bail_out(context::generic, "failed to open log file {}, {}", p,
|
||||||
"failed to open log file {}, {}", p, error_message(e));
|
error_message(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_log_file.reset(h);
|
g_log_file.reset(h);
|
||||||
@@ -261,21 +256,19 @@ void context::log_string(reason r, level lv, std::string_view s) const
|
|||||||
do_log_impl(false, r, lv, s);
|
do_log_impl(false, r, lv, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::do_log_impl(
|
void context::do_log_impl(bool bail, reason r, level lv,
|
||||||
bool bail, reason r, level lv, std::string_view utf8) const
|
std::string_view utf8) const
|
||||||
{
|
{
|
||||||
std::string_view sv = make_log_string(r, lv, utf8);
|
std::string_view sv = make_log_string(r, lv, utf8);
|
||||||
|
|
||||||
if (bail)
|
if (bail) {
|
||||||
{
|
|
||||||
// log the string with "(bailing out)" at the end, but throw the
|
// log the string with "(bailing out)" at the end, but throw the
|
||||||
// original, it's prettier that way
|
// original, it's prettier that way
|
||||||
const std::string s(sv);
|
const std::string s(sv);
|
||||||
emit_log(lv, s + " (bailing out)");
|
emit_log(lv, s + " (bailing out)");
|
||||||
throw bailed(s);
|
throw bailed(s);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
emit_log(lv, sv);
|
emit_log(lv, sv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,28 +278,24 @@ void context::emit_log(level lv, std::string_view utf8) const
|
|||||||
std::scoped_lock lock(g_mutex);
|
std::scoped_lock lock(g_mutex);
|
||||||
|
|
||||||
// console
|
// console
|
||||||
if (log_enabled(lv, mob::conf().global().output_log_level()))
|
if (log_enabled(lv, mob::conf().global().output_log_level())) {
|
||||||
{
|
|
||||||
// will revert color in dtor
|
// will revert color in dtor
|
||||||
console_color c = level_color(lv);
|
console_color c = level_color(lv);
|
||||||
u8cout.write_ln(utf8);
|
u8cout.write_ln(utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// log file
|
// log file
|
||||||
if (g_log_file && log_enabled(lv, mob::conf().global().file_log_level()))
|
if (g_log_file && log_enabled(lv, mob::conf().global().file_log_level())) {
|
||||||
{
|
|
||||||
DWORD written = 0;
|
DWORD written = 0;
|
||||||
|
|
||||||
::WriteFile(
|
::WriteFile(g_log_file.get(), utf8.data(), static_cast<DWORD>(utf8.size()),
|
||||||
g_log_file.get(), utf8.data(), static_cast<DWORD>(utf8.size()),
|
|
||||||
&written, nullptr);
|
&written, nullptr);
|
||||||
|
|
||||||
::WriteFile(g_log_file.get(), "\r\n", 2, &written, nullptr);
|
::WriteFile(g_log_file.get(), "\r\n", 2, &written, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remember warnings and errors
|
// remember warnings and errors
|
||||||
if (should_dump_logs())
|
if (should_dump_logs()) {
|
||||||
{
|
|
||||||
if (lv == level::error)
|
if (lv == level::error)
|
||||||
g_errors.emplace_back(utf8);
|
g_errors.emplace_back(utf8);
|
||||||
else if (lv == level::warning)
|
else if (lv == level::warning)
|
||||||
@@ -319,12 +308,10 @@ void context::emit_log(level lv, std::string_view utf8) const
|
|||||||
//
|
//
|
||||||
void append(std::string& s, std::string_view what, std::size_t max_length)
|
void append(std::string& s, std::string_view what, std::size_t max_length)
|
||||||
{
|
{
|
||||||
if (what.empty())
|
if (what.empty()) {
|
||||||
{
|
|
||||||
s.append(max_length, ' ');
|
s.append(max_length, ' ');
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
s.append(what);
|
s.append(what);
|
||||||
|
|
||||||
// padding
|
// padding
|
||||||
@@ -339,15 +326,13 @@ void append(std::string& s, std::string_view what, std::size_t max_length)
|
|||||||
//
|
//
|
||||||
// avoids unnecessary memory allocations by appending the brackets directly
|
// avoids unnecessary memory allocations by appending the brackets directly
|
||||||
//
|
//
|
||||||
void append_with_brackets(
|
void append_with_brackets(std::string& s, std::string_view what,
|
||||||
std::string& s, std::string_view what, std::size_t max_length)
|
std::size_t max_length)
|
||||||
{
|
|
||||||
if (what.empty())
|
|
||||||
{
|
{
|
||||||
|
if (what.empty()) {
|
||||||
s.append(max_length, ' ');
|
s.append(max_length, ' ');
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
s.append(1, '[');
|
s.append(1, '[');
|
||||||
s.append(what);
|
s.append(what);
|
||||||
s.append(1, ']');
|
s.append(1, ']');
|
||||||
@@ -363,22 +348,18 @@ void append_with_brackets(
|
|||||||
//
|
//
|
||||||
void append_context(std::string& ls, context::reason r)
|
void append_context(std::string& ls, context::reason r)
|
||||||
{
|
{
|
||||||
switch (r)
|
switch (r) {
|
||||||
{
|
case context::redownload: {
|
||||||
case context::redownload:
|
|
||||||
{
|
|
||||||
ls.append(" (happened because of --redownload)");
|
ls.append(" (happened because of --redownload)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case context::rebuild:
|
case context::rebuild: {
|
||||||
{
|
|
||||||
ls.append(" (happened because of --rebuild)");
|
ls.append(" (happened because of --rebuild)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case context::reextract:
|
case context::reextract: {
|
||||||
{
|
|
||||||
ls.append(" (happened because of --reextract)");
|
ls.append(" (happened because of --reextract)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -416,34 +397,28 @@ std::string_view context::make_log_string(reason r, level, std::string_view s) c
|
|||||||
const std::size_t longest_reason = 7;
|
const std::size_t longest_reason = 7;
|
||||||
const std::size_t reason_max_length = longest_reason + 3;
|
const std::size_t reason_max_length = longest_reason + 3;
|
||||||
|
|
||||||
|
|
||||||
// keep a thread local string to avoid memory allocations
|
// keep a thread local string to avoid memory allocations
|
||||||
static thread_local std::string ls;
|
static thread_local std::string ls;
|
||||||
|
|
||||||
// clear previous log
|
// clear previous log
|
||||||
ls.clear();
|
ls.clear();
|
||||||
|
|
||||||
|
|
||||||
// a full log line might look like:
|
// a full log line might look like:
|
||||||
// "2.77 [cmake_common] [git] [cmd] creating process"
|
// "2.77 [cmake_common] [git] [cmd] creating process"
|
||||||
|
|
||||||
|
|
||||||
// timestamp
|
// timestamp
|
||||||
append(ls, timestamp_string(), timestamp_max_length);
|
append(ls, timestamp_string(), timestamp_max_length);
|
||||||
|
|
||||||
// task name
|
// task name
|
||||||
append_with_brackets(
|
append_with_brackets(ls, task_.substr(0, longest_task_name),
|
||||||
ls, task_.substr(0, longest_task_name), task_name_max_length);
|
task_name_max_length);
|
||||||
|
|
||||||
// tool
|
// tool
|
||||||
if (tool_)
|
if (tool_) {
|
||||||
{
|
append_with_brackets(ls, tool_->name().substr(0, longest_tool_name),
|
||||||
append_with_brackets(
|
|
||||||
ls, tool_->name().substr(0, longest_tool_name),
|
|
||||||
tool_name_max_length);
|
tool_name_max_length);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
ls.append(tool_name_max_length, ' ');
|
ls.append(tool_name_max_length, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +431,6 @@ std::string_view context::make_log_string(reason r, level, std::string_view s) c
|
|||||||
// context
|
// context
|
||||||
append_context(ls, r);
|
append_context(ls, r);
|
||||||
|
|
||||||
|
|
||||||
return ls;
|
return ls;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,8 +439,7 @@ void dump_logs()
|
|||||||
if (!should_dump_logs())
|
if (!should_dump_logs())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!g_warnings.empty() || !g_errors.empty())
|
if (!g_warnings.empty() || !g_errors.empty()) {
|
||||||
{
|
|
||||||
u8cout << "\n\nthere were problems:\n";
|
u8cout << "\n\nthere were problems:\n";
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -483,4 +456,4 @@ void dump_logs()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+19
-41
@@ -7,52 +7,41 @@
|
|||||||
// 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;
|
||||||
|
|
||||||
@@ -60,7 +49,6 @@ class tool;
|
|||||||
//
|
//
|
||||||
std::string error_message(DWORD e);
|
std::string error_message(DWORD e);
|
||||||
|
|
||||||
|
|
||||||
// a logger with some context, this is passed around everywhere and knows which
|
// 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
|
// task and tool is currently running to get better context when logging
|
||||||
//
|
//
|
||||||
@@ -74,13 +62,11 @@ std::string error_message(DWORD e);
|
|||||||
//
|
//
|
||||||
// cx.log(context::generic, "eat more {}", "potatoes");
|
// cx.log(context::generic, "eat more {}", "potatoes");
|
||||||
//
|
//
|
||||||
class context
|
class context {
|
||||||
{
|
|
||||||
public:
|
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);
|
||||||
@@ -239,7 +223,6 @@ private:
|
|||||||
// 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,8 +274,7 @@ 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
|
||||||
@@ -304,7 +283,6 @@ private:
|
|||||||
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()
|
||||||
@@ -317,4 +295,4 @@ inline const context& gcx()
|
|||||||
//
|
//
|
||||||
void dump_logs();
|
void dump_logs();
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+46
-80
@@ -1,14 +1,13 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "env.h"
|
#include "env.h"
|
||||||
#include "conf.h"
|
|
||||||
#include "process.h"
|
|
||||||
#include "op.h"
|
|
||||||
#include "context.h"
|
|
||||||
#include "../utility.h"
|
|
||||||
#include "../tools/tools.h"
|
#include "../tools/tools.h"
|
||||||
|
#include "../utility.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "op.h"
|
||||||
|
#include "process.h"
|
||||||
|
|
||||||
namespace mob
|
namespace mob {
|
||||||
{
|
|
||||||
|
|
||||||
// retrieves the Visual Studio environment variables for the given architecture;
|
// retrieves the Visual Studio environment variables for the given architecture;
|
||||||
// this is pretty expensive, so it's called on demand and only once, and is
|
// this is pretty expensive, so it's called on demand and only once, and is
|
||||||
@@ -19,8 +18,7 @@ env get_vcvars_env(arch a)
|
|||||||
// translate arch to the string needed by vcvars
|
// translate arch to the string needed by vcvars
|
||||||
std::string arch_s;
|
std::string arch_s;
|
||||||
|
|
||||||
switch (a)
|
switch (a) {
|
||||||
{
|
|
||||||
case arch::x86:
|
case arch::x86:
|
||||||
arch_s = "x86";
|
arch_s = "x86";
|
||||||
break;
|
break;
|
||||||
@@ -36,7 +34,6 @@ env get_vcvars_env(arch a)
|
|||||||
|
|
||||||
gcx().trace(context::generic, "looking for vcvars for {}", arch_s);
|
gcx().trace(context::generic, "looking for vcvars for {}", arch_s);
|
||||||
|
|
||||||
|
|
||||||
// the only way to get these variables is to
|
// the only way to get these variables is to
|
||||||
// 1) run vcvars in a cmd instance,
|
// 1) run vcvars in a cmd instance,
|
||||||
// 2) call `set`, which outputs all the variables to stdout, and
|
// 2) call `set`, which outputs all the variables to stdout, and
|
||||||
@@ -50,14 +47,11 @@ env get_vcvars_env(arch a)
|
|||||||
const fs::path tmp = make_temp_file();
|
const fs::path tmp = make_temp_file();
|
||||||
|
|
||||||
// runs `"vcvarsall.bat" amd64 && set > temp_file`
|
// runs `"vcvarsall.bat" amd64 && set > temp_file`
|
||||||
const std::string cmd =
|
const std::string cmd = "\"" + path_to_utf8(vs::vcvars()) + "\" " + arch_s +
|
||||||
"\"" + path_to_utf8(vs::vcvars()) + "\" " + arch_s +
|
|
||||||
" && set > \"" + path_to_utf8(tmp) + "\"";
|
" && set > \"" + path_to_utf8(tmp) + "\"";
|
||||||
|
|
||||||
// cmd_unicode() is necessary so `set` outputs in utf16 instead of codepage
|
// cmd_unicode() is necessary so `set` outputs in utf16 instead of codepage
|
||||||
process::raw(gcx(), cmd)
|
process::raw(gcx(), cmd).cmd_unicode(true).run();
|
||||||
.cmd_unicode(true)
|
|
||||||
.run();
|
|
||||||
|
|
||||||
gcx().trace(context::generic, "reading from {}", tmp);
|
gcx().trace(context::generic, "reading from {}", tmp);
|
||||||
|
|
||||||
@@ -71,8 +65,7 @@ env get_vcvars_env(arch a)
|
|||||||
|
|
||||||
gcx().trace(context::generic, "parsing variables");
|
gcx().trace(context::generic, "parsing variables");
|
||||||
|
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(ss, line);
|
std::getline(ss, line);
|
||||||
if (!ss)
|
if (!ss)
|
||||||
@@ -93,7 +86,6 @@ env get_vcvars_env(arch a)
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
env env::vs_x86()
|
env env::vs_x86()
|
||||||
{
|
{
|
||||||
static env e = get_vcvars_env(arch::x86);
|
static env e = get_vcvars_env(arch::x86);
|
||||||
@@ -108,8 +100,7 @@ env env::vs_x64()
|
|||||||
|
|
||||||
env env::vs(arch a)
|
env env::vs(arch a)
|
||||||
{
|
{
|
||||||
switch (a)
|
switch (a) {
|
||||||
{
|
|
||||||
case arch::x86:
|
case arch::x86:
|
||||||
return vs_x86();
|
return vs_x86();
|
||||||
|
|
||||||
@@ -124,21 +115,17 @@ env env::vs(arch a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env::env() : own_(false)
|
||||||
env::env()
|
|
||||||
: own_(false)
|
|
||||||
{
|
{
|
||||||
// empty env, does not own
|
// empty env, does not own
|
||||||
}
|
}
|
||||||
|
|
||||||
env::env(const env& e)
|
env::env(const env& e) : data_(e.data_), own_(false)
|
||||||
: data_(e.data_), own_(false)
|
|
||||||
{
|
{
|
||||||
// copy data, does not own
|
// copy data, does not own
|
||||||
}
|
}
|
||||||
|
|
||||||
env::env(env&& e)
|
env::env(env&& e) : data_(std::move(e.data_)), own_(e.own_)
|
||||||
: data_(std::move(e.data_)), own_(e.own_)
|
|
||||||
{
|
{
|
||||||
// move data, owns if `e` did
|
// move data, owns if `e` did
|
||||||
}
|
}
|
||||||
@@ -189,28 +176,25 @@ env& env::change_path(const std::vector<fs::path>& v, flags f)
|
|||||||
|
|
||||||
std::wstring path;
|
std::wstring path;
|
||||||
|
|
||||||
switch (f)
|
switch (f) {
|
||||||
{
|
case replace: {
|
||||||
case replace:
|
|
||||||
{
|
|
||||||
// convert to utf16 strings, join with ;
|
// convert to utf16 strings, join with ;
|
||||||
const auto strings =
|
const auto strings = mob::map(v, [&](auto&& p) {
|
||||||
mob::map(v, [&](auto&& p){ return p.native(); });
|
return p.native();
|
||||||
|
});
|
||||||
|
|
||||||
path = join(strings, L";");
|
path = join(strings, L";");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case append:
|
case append: {
|
||||||
{
|
|
||||||
auto current = find(L"PATH");
|
auto current = find(L"PATH");
|
||||||
if (current)
|
if (current)
|
||||||
path = *current;
|
path = *current;
|
||||||
|
|
||||||
// append all paths as utf16 strings to the current value, if any
|
// append all paths as utf16 strings to the current value, if any
|
||||||
for (auto&& p : v)
|
for (auto&& p : v) {
|
||||||
{
|
|
||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
path += L";";
|
path += L";";
|
||||||
|
|
||||||
@@ -220,15 +204,13 @@ env& env::change_path(const std::vector<fs::path>& v, flags f)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case prepend:
|
case prepend: {
|
||||||
{
|
|
||||||
auto current = find(L"PATH");
|
auto current = find(L"PATH");
|
||||||
if (current)
|
if (current)
|
||||||
path = *current;
|
path = *current;
|
||||||
|
|
||||||
// prepend all paths as utf16 strings to the current value, if any
|
// prepend all paths as utf16 strings to the current value, if any
|
||||||
for (auto&& p : v)
|
for (auto&& p : v) {
|
||||||
{
|
|
||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
path = L";" + path;
|
path = L";" + path;
|
||||||
|
|
||||||
@@ -262,14 +244,12 @@ void env::set_impl(std::wstring k, std::wstring v, flags f)
|
|||||||
{
|
{
|
||||||
auto current = find(k);
|
auto current = find(k);
|
||||||
|
|
||||||
if (!current)
|
if (!current) {
|
||||||
{
|
|
||||||
data_->vars.emplace(std::move(k), std::move(v));
|
data_->vars.emplace(std::move(k), std::move(v));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (f)
|
switch (f) {
|
||||||
{
|
|
||||||
case replace:
|
case replace:
|
||||||
*current = std::move(v);
|
*current = std::move(v);
|
||||||
break;
|
break;
|
||||||
@@ -313,8 +293,7 @@ void env::create_sys() const
|
|||||||
|
|
||||||
data_->sys.clear();
|
data_->sys.clear();
|
||||||
|
|
||||||
for (auto&& v : data_->vars)
|
for (auto&& v : data_->vars) {
|
||||||
{
|
|
||||||
data_->sys += v.first + L"=" + v.second;
|
data_->sys += v.first + L"=" + v.second;
|
||||||
data_->sys.append(1, L'\0');
|
data_->sys.append(1, L'\0');
|
||||||
}
|
}
|
||||||
@@ -332,8 +311,7 @@ const std::wstring* env::find(std::wstring_view name) const
|
|||||||
if (!data_)
|
if (!data_)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
for (auto itor=data_->vars.begin(); itor!=data_->vars.end(); ++itor)
|
for (auto itor = data_->vars.begin(); itor != data_->vars.end(); ++itor) {
|
||||||
{
|
|
||||||
if (_wcsicmp(itor->first.c_str(), name.data()) == 0)
|
if (_wcsicmp(itor->first.c_str(), name.data()) == 0)
|
||||||
return &itor->second;
|
return &itor->second;
|
||||||
}
|
}
|
||||||
@@ -358,8 +336,7 @@ void* env::get_unicode_pointers() const
|
|||||||
|
|
||||||
void env::copy_for_write()
|
void env::copy_for_write()
|
||||||
{
|
{
|
||||||
if (own_)
|
if (own_) {
|
||||||
{
|
|
||||||
// this is called every time something is about to change; if this
|
// this is called every time something is about to change; if this
|
||||||
// instance already owns the data, the sys strings must still be cleared
|
// instance already owns the data, the sys strings must still be cleared
|
||||||
// out so they're recreated if get_unicode_pointers() is every called
|
// out so they're recreated if get_unicode_pointers() is every called
|
||||||
@@ -369,8 +346,7 @@ void env::copy_for_write()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_)
|
if (data_) {
|
||||||
{
|
|
||||||
// remember the shared data
|
// remember the shared data
|
||||||
auto shared = data_;
|
auto shared = data_;
|
||||||
|
|
||||||
@@ -381,8 +357,7 @@ void env::copy_for_write()
|
|||||||
std::scoped_lock lock(shared->m);
|
std::scoped_lock lock(shared->m);
|
||||||
data_->vars = shared->vars;
|
data_->vars = shared->vars;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// creating own, empty data
|
// creating own, empty data
|
||||||
data_.reset(new data);
|
data_.reset(new data);
|
||||||
}
|
}
|
||||||
@@ -391,37 +366,34 @@ void env::copy_for_write()
|
|||||||
own_ = true;
|
own_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// mob's environment variables are only retrieved once and are kept in sync
|
// mob's environment variables are only retrieved once and are kept in sync
|
||||||
// after that; this must also be thread-safe
|
// after that; this must also be thread-safe
|
||||||
static std::mutex g_sys_env_mutex;
|
static std::mutex g_sys_env_mutex;
|
||||||
static env g_sys_env;
|
static env g_sys_env;
|
||||||
static bool g_sys_env_inited;
|
static bool g_sys_env_inited;
|
||||||
|
|
||||||
|
|
||||||
env this_env::get()
|
env this_env::get()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(g_sys_env_mutex);
|
std::scoped_lock lock(g_sys_env_mutex);
|
||||||
|
|
||||||
if (g_sys_env_inited)
|
if (g_sys_env_inited) {
|
||||||
{
|
|
||||||
// already done
|
// already done
|
||||||
return g_sys_env;
|
return g_sys_env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// first time, get the variables from the system
|
// first time, get the variables from the system
|
||||||
|
|
||||||
auto free = [](wchar_t* p) { FreeEnvironmentStringsW(p); };
|
auto free = [](wchar_t* p) {
|
||||||
|
FreeEnvironmentStringsW(p);
|
||||||
|
};
|
||||||
|
|
||||||
auto env_block = std::unique_ptr<wchar_t, decltype(free)>{
|
auto env_block =
|
||||||
GetEnvironmentStringsW(), free};
|
std::unique_ptr<wchar_t, decltype(free)>{GetEnvironmentStringsW(), free};
|
||||||
|
|
||||||
// GetEnvironmentStringsW() returns a string where each variable=value
|
// GetEnvironmentStringsW() returns a string where each variable=value
|
||||||
// is separated by a null character
|
// is separated by a null character
|
||||||
|
|
||||||
for (const wchar_t* name = env_block.get(); *name != L'\0'; )
|
for (const wchar_t* name = env_block.get(); *name != L'\0';) {
|
||||||
{
|
|
||||||
// equal sign
|
// equal sign
|
||||||
const wchar_t* equal = std::wcschr(name, '=');
|
const wchar_t* equal = std::wcschr(name, '=');
|
||||||
|
|
||||||
@@ -452,24 +424,20 @@ void this_env::set(const std::string& k, const std::string& v, env::flags f)
|
|||||||
const std::wstring wk = utf8_to_utf16(k);
|
const std::wstring wk = utf8_to_utf16(k);
|
||||||
std::wstring wv = utf8_to_utf16(v);
|
std::wstring wv = utf8_to_utf16(v);
|
||||||
|
|
||||||
switch (f)
|
switch (f) {
|
||||||
{
|
case env::replace: {
|
||||||
case env::replace:
|
|
||||||
{
|
|
||||||
::SetEnvironmentVariableW(wk.c_str(), wv.c_str());
|
::SetEnvironmentVariableW(wk.c_str(), wv.c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case env::append:
|
case env::append: {
|
||||||
{
|
|
||||||
const std::wstring current = get_impl(k).value_or(L"");
|
const std::wstring current = get_impl(k).value_or(L"");
|
||||||
wv = current + wv;
|
wv = current + wv;
|
||||||
::SetEnvironmentVariableW(wk.c_str(), wv.c_str());
|
::SetEnvironmentVariableW(wk.c_str(), wv.c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case env::prepend:
|
case env::prepend: {
|
||||||
{
|
|
||||||
const std::wstring current = get_impl(k).value_or(L"");
|
const std::wstring current = get_impl(k).value_or(L"");
|
||||||
wv = wv + current;
|
wv = wv + current;
|
||||||
::SetEnvironmentVariableW(wk.c_str(), wv.c_str());
|
::SetEnvironmentVariableW(wk.c_str(), wv.c_str());
|
||||||
@@ -500,10 +468,9 @@ void this_env::append_to_path(const fs::path& p)
|
|||||||
std::string this_env::get(const std::string& name)
|
std::string this_env::get(const std::string& name)
|
||||||
{
|
{
|
||||||
auto v = get_impl(name);
|
auto v = get_impl(name);
|
||||||
if (!v)
|
if (!v) {
|
||||||
{
|
gcx().bail_out(context::generic, "environment variable {} doesn't exist",
|
||||||
gcx().bail_out(context::generic,
|
name);
|
||||||
"environment variable {} doesn't exist", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return utf16_to_utf8(*v);
|
return utf16_to_utf8(*v);
|
||||||
@@ -522,8 +489,7 @@ std::optional<std::wstring> this_env::get_impl(const std::string& k)
|
|||||||
{
|
{
|
||||||
const std::wstring wk = utf8_to_utf16(k);
|
const std::wstring wk = utf8_to_utf16(k);
|
||||||
|
|
||||||
const std::size_t buffer_size = GetEnvironmentVariableW(
|
const std::size_t buffer_size = GetEnvironmentVariableW(wk.c_str(), nullptr, 0);
|
||||||
wk.c_str(), nullptr, 0);
|
|
||||||
|
|
||||||
if (buffer_size == 0)
|
if (buffer_size == 0)
|
||||||
return {};
|
return {};
|
||||||
@@ -542,4 +508,4 @@ std::optional<std::wstring> this_env::get_impl(const std::string& k)
|
|||||||
return std::wstring(buffer.get(), buffer.get() + written);
|
return std::wstring(buffer.get(), buffer.get() + written);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+7
-21
@@ -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();
|
||||||
@@ -77,8 +69,7 @@ public:
|
|||||||
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;
|
||||||
@@ -117,16 +107,12 @@ private:
|
|||||||
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,
|
|
||||||
const std::string& v,
|
|
||||||
env::flags f = env::replace);
|
env::flags f = env::replace);
|
||||||
|
|
||||||
// changes PATH
|
// changes PATH
|
||||||
@@ -152,4 +138,4 @@ private:
|
|||||||
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
|
||||||
|
|||||||
+49
-92
@@ -1,30 +1,25 @@
|
|||||||
#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,
|
gcx().bail_out(context::conf, "{}:{}: {}", path_to_utf8(ini.path), (line + 1),
|
||||||
"{}:{}: {}",
|
|
||||||
path_to_utf8(ini.path), (line + 1),
|
|
||||||
fmt::format(f, std::forward<Args>(args)...));
|
fmt::format(f, std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ini_data::kv_map& ini_data::get_section(std::string_view name)
|
ini_data::kv_map& ini_data::get_section(std::string_view name)
|
||||||
{
|
{
|
||||||
for (auto itor=sections.begin(); itor!=sections.end(); ++itor)
|
for (auto itor = sections.begin(); itor != sections.end(); ++itor) {
|
||||||
{
|
|
||||||
if (itor->first == name)
|
if (itor->first == name)
|
||||||
return itor->second;
|
return itor->second;
|
||||||
}
|
}
|
||||||
@@ -39,27 +34,22 @@ void ini_data::set(std::string_view section, std::string key, std::string value)
|
|||||||
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,20 +108,16 @@ 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";
|
||||||
|
|
||||||
@@ -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,21 +149,18 @@ 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) << " ("
|
||||||
u8cout
|
<< v[i].first << ")\n";
|
||||||
<< " " << (i + 1) << ") "
|
|
||||||
<< path_to_utf8(v[i].second) << " (" << v[i].first << ")\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return map(v, [&](auto&& p) {
|
||||||
return map(v, [&](auto&& p){ return p.second; });
|
return p.second;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> read_ini(const fs::path& ini)
|
std::vector<std::string> read_ini(const fs::path& ini)
|
||||||
@@ -198,8 +169,7 @@ std::vector<std::string> read_ini(const fs::path& 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);
|
||||||
@@ -216,8 +186,7 @@ std::vector<std::string> read_ini(const fs::path& 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();
|
||||||
@@ -232,16 +201,13 @@ 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);
|
||||||
|
|
||||||
@@ -249,37 +215,32 @@ void parse_line(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -299,27 +260,23 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,4 +284,4 @@ ini_data parse_ini(const fs::path& path)
|
|||||||
return ini;
|
return ini;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace mob
|
||||||
|
|||||||
+5
-9
@@ -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>;
|
||||||
|
|
||||||
@@ -29,4 +25,4 @@ struct ini_data
|
|||||||
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