Author SHA1 Message Date
Mikaël Capelle 60eb00e04e Start working on extensions.
- Update translations task to put translations under extensions.
- Put translations in the right place.
- Remove INI bakery plugin.
- Use mo2- prefixed extensions for translations.
- Generate metadata for the translations extension.
2023-11-10 13:10:20 +01:00
99 changed files with 19158 additions and 20497 deletions
+26
View File
@@ -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
+7
View File
@@ -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
-6
View File
@@ -1,6 +0,0 @@
cmake_minimum_required(VERSION 3.16)
project(mob)
add_subdirectory(src)
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT mob)
+30 -9
View File
@@ -1,19 +1,40 @@
$root = $PSScriptRoot $root = $PSScriptRoot
if (!$root) { if (!$root) {
$root = "." $root = "."
} }
cmake -B build $root | Out-Null $installationPath = & $root\third-party\bin\vswhere.exe -products * -nologo -prerelease -latest -property installationPath
cmake --build $root/build --config Release -- ` if (! $?) {
"-p:UseMultiToolTask=true" ` Write-Error "vswhere returned $LastExitCode"
"-noLogo" ` exit $LastExitCode
"-p:EnforceProcessCountAcrossBuilds=true" ` }
"-clp:ErrorsOnly;Verbosity=minimal"
if (! $installationPath) {
Write-Error "Empty installation path"
exit 1
}
$opts = ""
$opts += " $root\vs\mob.sln"
$opts += " -m"
$opts += " -p:Configuration=Release"
$opts += " -noLogo"
$opts += " -p:UseMultiToolTask=true"
$opts += " -p:EnforceProcessCountAcrossBuilds=true"
$opts += " -clp:ErrorsOnly;Verbosity=minimal"
$vsDevCmd = "$installationPath\Common7\Tools\VsDevCmd.bat"
if (!(Test-Path "$vsDevCmd")) {
Write-Error "VdDevCmd.bat not found at $vsDevCmd"
exit 1
}
& "${env:COMSPEC}" /c "`"$vsDevCmd`" -no_logo -arch=amd64 -host_arch=amd64 && msbuild $opts"
if (! $?) { if (! $?) {
Write-Error "Build failed" Write-Error "Build failed"
exit $LastExitCode exit $LastExitCode
} }
Copy-Item "$root\build\src\Release\mob.exe" "$root\mob.exe" Copy-Item "$root\build\Release\x64\mob.exe" "$root\mob.exe"
Write-Output "run ``.\mob -d prefix/path build`` to start building" echo "run ``.\mob -d prefix/path build`` to start building"
+5 -1
View File
@@ -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 =
-22
View File
@@ -1,22 +0,0 @@
cmake_minimum_required(VERSION 3.16)
file(GLOB_RECURSE source_files *.cpp)
file(GLOB RECURSE header_files *.h)
add_executable(mob ${source_files})
set_target_properties(mob PROPERTIES CXX_STANDARD 20)
target_compile_definitions(mob PUBLIC NOMINMAX)
target_compile_options(mob PUBLIC "/MT")
target_include_directories(mob PUBLIC ${CMAKE_SOURCE_DIR}/third-party/include)
target_link_libraries(mob PUBLIC
wsock32 ws2_32 crypt32 wldap32 dbghelp shlwapi version
optimized ${CMAKE_SOURCE_DIR}/third-party/lib/libcurl.lib
debug ${CMAKE_SOURCE_DIR}/third-party/lib/libcurl-d.lib
optimized ${CMAKE_SOURCE_DIR}/third-party/lib/zlib.lib
debug ${CMAKE_SOURCE_DIR}/third-party/lib/zlibd.lib)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}
PREFIX src
FILES ${source_files} ${header_files})
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT mob)
+150 -155
View File
@@ -1,200 +1,195 @@
#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([&] {
"avoid merge errors; global override", revert_ts_ = false;
})) %
"whether to revert all the .ts files in a repo before pulling to "
"avoid merge errors; global override",
(clipp::option("--ignore-uncommitted-changes") >> ignore_uncommitted_) (clipp::option("--ignore-uncommitted-changes") >> ignore_uncommitted_) %
% "when --reextract is given, directories controlled by git will " "when --reextract is given, directories controlled by git will "
"be deleted even if they contain uncommitted changes", "be deleted even if they contain uncommitted changes",
(clipp::option("--keep-msbuild") >> keep_msbuild_) (clipp::option("--keep-msbuild") >> keep_msbuild_) %
% "don't terminate msbuild.exe instances after building", "don't terminate msbuild.exe instances after building",
(clipp::opt_values( (clipp::opt_values(clipp::match::prefix_not("-"), "task", tasks_)) %
clipp::match::prefix_not("-"), "task", tasks_)) "tasks to run; specify 'super' to only build modorganizer "
% "tasks to run; specify 'super' to only build modorganizer " "projects";
"projects"; }
}
void build_command::convert_cl_to_conf() void build_command::convert_cl_to_conf()
{ {
command::convert_cl_to_conf(); command::convert_cl_to_conf();
if (redownload_ || new_) if (redownload_ || new_)
common.options.push_back("global/redownload=true"); common.options.push_back("global/redownload=true");
if (reextract_ || new_) if (reextract_ || new_)
common.options.push_back("global/reextract=true"); common.options.push_back("global/reextract=true");
if (reconfigure_ || new_) if (reconfigure_ || new_)
common.options.push_back("global/reconfigure=true"); common.options.push_back("global/reconfigure=true");
if (rebuild_ || new_) if (rebuild_ || new_)
common.options.push_back("global/rebuild=true"); common.options.push_back("global/rebuild=true");
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 common.options.push_back("_override:task/revert_ts=false");
common.options.push_back("_override:task/revert_ts=false"); }
}
if (!tasks_.empty()) if (!tasks_.empty())
set_task_enabled_flags(tasks_); set_task_enabled_flags(tasks_);
} }
int build_command::do_run() int build_command::do_run()
{ {
try try {
{ create_prefix_ini();
create_prefix_ini();
task_manager::instance().run_all(); task_manager::instance().run_all();
if (!keep_msbuild_) if (!keep_msbuild_)
terminate_msbuild(); terminate_msbuild();
mob::gcx().info(mob::context::generic, "mob done"); mob::gcx().info(mob::context::generic, "mob done");
return 0; return 0;
} }
catch(bailed&) catch (bailed&) {
{ gcx().error(context::generic, "bailing out");
gcx().error(context::generic, "bailing out"); return 1;
return 1; }
} }
}
void build_command::create_prefix_ini() void build_command::create_prefix_ini()
{ {
const auto prefix = conf().path().prefix(); const auto prefix = conf().path().prefix();
// creating prefix // creating prefix
if (!exists(prefix)) if (!exists(prefix))
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) << "prefix = .\n";
<< "[paths]\n" }
<< "prefix = .\n"; }
}
}
void build_command::terminate_msbuild() void build_command::terminate_msbuild()
{ {
if (conf().global().dry()) if (conf().global().dry())
return; return;
system("taskkill /im msbuild.exe /f > NUL 2>&1"); system("taskkill /im msbuild.exe /f > NUL 2>&1");
} }
} // namespace } // namespace mob
+45 -63
View File
@@ -1,83 +1,65 @@
#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()
{ {
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 pass \"-A Win32\" or \"-A x64\" for the default "
% "whether to use the x64 or x86 vcvars; if -G is not set, " "VS generator [default: x64]",
"whether to pass \"-A Win32\" or \"-A x64\" for the default "
"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_);
t.prefix(prefix_); t.prefix(prefix_);
t.output(path_); t.output(path_);
if (!x64_) if (!x64_)
t.architecture(arch::x86); t.architecture(arch::x86);
// copy the global context, the tool will modify it // copy the global context, the tool will modify it
context cxcopy(gcx()); context cxcopy(gcx());
t.run(cxcopy); t.run(cxcopy);
return 0; return 0;
} }
std::string cmake_command::do_doc() std::string cmake_command::do_doc()
{ {
return return "Runs `cmake ..` in the given directory with the same command line\n"
"Runs `cmake ..` in the given directory with the same command line\n" "as the one used for modorganizer projects.";
"as the one used for modorganizer projects."; }
}
} // namespace } // namespace mob
+319 -372
View File
File diff suppressed because it is too large Load Diff
+423 -479
View File
File diff suppressed because it is too large Load Diff
+191 -229
View File
@@ -1,285 +1,247 @@
#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()
{ {
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();
{ break;
do_set_remotes(); }
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; }
}
case modes::none: case modes::none:
default: default:
u8cerr << "bad git mode " << static_cast<int>(mode_) << "\n"; u8cerr << "bad git mode " << static_cast<int>(mode_) << "\n";
throw bailed(); throw bailed();
} }
return 0; return 0;
} }
std::string git_command::do_doc() std::string git_command::do_doc()
{ {
return return "All the commands will go through all modorganizer repos, plus usvfs\n"
"All the commands will go through all modorganizer repos, plus usvfs\n" "and NCC.\n"
"and NCC.\n" "\n"
"\n" "Commands:\n"
"Commands:\n" "set-remotes\n"
"set-remotes\n" " For each repo, this first sets the username and email. Then, it\n"
" For each repo, this first sets the username and email. Then, it\n" " will rename the remote 'origin' to 'upstream' and create a new\n"
" will rename the remote 'origin' to 'upstream' and create a new\n" " remote 'origin' with the given information. If the remote\n"
" remote 'origin' with the given information. If the remote\n" " 'upstream' already exists in a repo, nothing happens.\n"
" 'upstream' already exists in a repo, nothing happens.\n" "\n"
"\n" "add-remote\n"
"add-remote\n" " For each repo, adds a new remote with the given information. If a\n"
" For each repo, adds a new remote with the given information. If a\n" " remote with the same name already exists, nothing happens.\n"
" remote with the same name already exists, nothing happens.\n" "\n"
"\n" "ignore-ts\n"
"ignore-ts\n" " Toggles the --assume-changed status of all .ts files in all repos.\n"
" Toggles the --assume-changed status of all .ts files in all repos.\n" "\n"
"\n" "branches\n"
"branches\n" " Lists all git repos that are not on master. With -a, show all \n"
" Lists all git repos that are not on master. With -a, show all \n" " repos and their current branch.";
" repos and their current branch."; }
}
void git_command::do_set_remotes() void git_command::do_set_remotes()
{ {
if (path_.empty()) if (path_.empty()) {
{ const auto repos = get_repos();
const auto repos = get_repos();
for (auto&& r : repos) for (auto&& r : repos)
do_set_remotes(r); do_set_remotes(r);
} }
else else {
{ do_set_remotes(path_);
do_set_remotes(path_); }
} }
}
void git_command::do_set_remotes(const fs::path& r) void git_command::do_set_remotes(const fs::path& r)
{ {
u8cout << "setting up " << path_to_utf8(r.filename()) << "\n"; u8cout << "setting up " << path_to_utf8(r.filename()) << "\n";
git_wrap(r).set_credentials(username_, email_); git_wrap(r).set_credentials(username_, email_);
git_wrap(r).set_origin_and_upstream_remotes( git_wrap(r).set_origin_and_upstream_remotes(username_, key_, nopush_,
username_, key_, nopush_, push_default_); push_default_);
} }
void git_command::do_add_remote() void git_command::do_add_remote()
{ {
u8cout u8cout << "adding remote '" << remote_ << "' "
<< "adding remote '" << remote_ << "' " << "from '" << username_ << "' to repos\n";
<< "from '" << username_ << "' to repos\n";
if (path_.empty()) if (path_.empty()) {
{ const auto repos = get_repos();
const auto repos = get_repos();
for (auto&& r : repos) for (auto&& r : repos)
do_add_remote(r); do_add_remote(r);
} }
else else {
{ do_add_remote(path_);
do_add_remote(path_); }
} }
}
void git_command::do_add_remote(const fs::path& r) void git_command::do_add_remote(const fs::path& r)
{ {
u8cout << path_to_utf8(r.filename()) << "\n"; u8cout << path_to_utf8(r.filename()) << "\n";
git_wrap(r).add_remote(remote_, username_, key_, push_default_); git_wrap(r).add_remote(remote_, username_, key_, push_default_);
} }
void git_command::do_ignore_ts() void git_command::do_ignore_ts()
{ {
if (tson_) if (tson_)
u8cout << "ignoring .ts files\n"; u8cout << "ignoring .ts files\n";
else else
u8cout << "un-ignoring .ts files\n"; u8cout << "un-ignoring .ts files\n";
if (path_.empty()) if (path_.empty()) {
{ const auto repos = get_repos();
const auto repos = get_repos();
for (auto&& r : repos) for (auto&& r : repos)
do_ignore_ts(r); do_ignore_ts(r);
} }
else else {
{ do_ignore_ts(path_);
do_ignore_ts(path_); }
} }
}
void git_command::do_ignore_ts(const fs::path& r) void git_command::do_ignore_ts(const fs::path& r)
{ {
u8cout << path_to_utf8(r.filename()) << "\n"; u8cout << path_to_utf8(r.filename()) << "\n";
git_wrap(r).ignore_ts(tson_); git_wrap(r).ignore_ts(tson_);
} }
void git_command::do_branches() void git_command::do_branches()
{ {
std::vector<std::pair<std::string, std::string>> v; std::vector<std::pair<std::string, std::string>> v;
for (auto&& r : get_repos()) for (auto&& r : get_repos()) {
{ const auto b = git_wrap(r).current_branch();
const auto b = git_wrap(r).current_branch(); if (b == "master" && !all_branches_)
if (b == "master" && !all_branches_) continue;
continue;
if (b.empty()) if (b.empty())
v.push_back({r.filename().string(), "detached head"}); v.push_back({r.filename().string(), "detached head"});
else else
v.push_back({r.filename().string(), b}); v.push_back({r.filename().string(), b});
} }
u8cout << table(v, 0, 3) << "\n"; u8cout << table(v, 0, 3) << "\n";
} }
std::vector<fs::path> git_command::get_repos() const std::vector<fs::path> git_command::get_repos() const
{ {
std::vector<fs::path> v; std::vector<fs::path> v;
// usvfs // usvfs
if (fs::exists(tasks::usvfs::source_path())) if (fs::exists(tasks::usvfs::source_path()))
v.push_back(tasks::usvfs::source_path()); v.push_back(tasks::usvfs::source_path());
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())
{ continue;
if (!e.is_directory())
continue;
const auto p = e.path(); const auto p = e.path();
if (path_to_utf8(p.filename()).starts_with(".")) if (path_to_utf8(p.filename()).starts_with("."))
continue; continue;
v.push_back(p); v.push_back(p);
} }
} }
return v; return v;
} }
} // namespace } // namespace mob
+62 -79
View File
@@ -1,100 +1,83 @@
#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()
{ {
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 (!tasks_.empty())
if (all_) set_task_enabled_flags(tasks_);
{
if (!tasks_.empty())
set_task_enabled_flags(tasks_);
load_options(); load_options();
dump(tm.top_level(), 0); dump(tm.top_level(), 0);
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
} {
for (auto&& t : v) {
if (!t->enabled())
continue;
void list_command::dump(const std::vector<task*>& v, std::size_t indent) const u8cout << std::string(indent * 4, ' ') << " - " << join(t->names(), ",")
{ << "\n";
for (auto&& t : v)
{
if (!t->enabled())
continue;
u8cout if (auto* pt = dynamic_cast<parallel_tasks*>(t))
<< std::string(indent*4, ' ') dump(pt->children(), indent + 1);
<< " - " << join(t->names(), ",") }
<< "\n"; }
if (auto* pt=dynamic_cast<parallel_tasks*>(t)) void list_command::dump_aliases() const
dump(pt->children(), indent + 1); {
} const auto v = task_manager::instance().aliases();
} if (v.empty())
return;
void list_command::dump_aliases() const for (auto&& [k, patterns] : v)
{ u8cout << " - " << k << ": " << join(patterns, ", ") << "\n";
const auto v = task_manager::instance().aliases(); }
if (v.empty())
return;
for (auto&& [k, patterns] : v) } // namespace mob
u8cout << " - " << k << ": " << join(patterns, ", ") << "\n";
}
} // namespace
+358 -403
View File
File diff suppressed because it is too large Load Diff
+525 -587
View File
File diff suppressed because it is too large Load Diff
+141 -166
View File
@@ -1,213 +1,188 @@
#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()
{ {
return clipp::group( return clipp::group(
clipp::command("tx").set(picked_), clipp::command("tx").set(picked_),
(clipp::option("-h", "--help") >> help_) (clipp::option("-h", "--help") >> help_) % ("shows this message"),
% ("shows this message"),
"get" % "get" % (clipp::command("get").set(mode_, modes::get),
(clipp::command("get").set(mode_, modes::get), (clipp::option("-k", "--key") & clipp::value("APIKEY") >> key_) %
(clipp::option("-k", "--key") "API key",
& clipp::value("APIKEY") >> key_)
% "API key",
(clipp::option("-t", "--team") (clipp::option("-t", "--team") & clipp::value("TEAM") >> team_) %
& clipp::value("TEAM") >> team_) "team name",
% "team name",
(clipp::option("-p", "--project") (clipp::option("-p", "--project") &
& clipp::value("PROJECT") >> project_) clipp::value("PROJECT") >> project_) %
% "project name", "project name",
(clipp::option("-u", "--url") (clipp::option("-u", "--url") & clipp::value("URL") >> url_) %
& clipp::value("URL") >> url_) "project URL",
% "project URL",
(clipp::option("-m", "--minimum") (clipp::option("-m", "--minimum") &
& clipp::value("PERCENT").set(min_)) clipp::value("PERCENT").set(min_)) %
% "minimum translation threshold to download [0-100]", "minimum translation threshold to download [0-100]",
(clipp::option("-f", "--force").call([&]{ force_ = true; })) (clipp::option("-f", "--force").call([&] {
% "don't check timestamps, re-download all translation files", force_ = true;
})) %
"don't check timestamps, re-download all translation files",
(clipp::value("path") >> path_) (clipp::value("path") >> path_) %
% "path that will contain the .tx directory" "path that will contain the .tx directory")
)
| |
"build" % "build" % (clipp::command("build").set(mode_, modes::build),
(clipp::command("build").set(mode_, modes::build),
(clipp::value("source") >> path_) (clipp::value("source") >> path_) %
% "path that contains the translation directories", "path that contains the translation directories",
(clipp::value("destination") >> dest_) (clipp::value("destination") >> dest_) %
% "path that will contain the .qm files" "path that will contain the .qm files"));
) }
);
}
void tx_command::convert_cl_to_conf() void tx_command::convert_cl_to_conf()
{ {
command::convert_cl_to_conf(); command::convert_cl_to_conf();
if (!key_.empty()) if (!key_.empty())
common.options.push_back("transifex/key=" + key_); common.options.push_back("transifex/key=" + key_);
if (!team_.empty()) if (!team_.empty())
common.options.push_back("transifex/team=" + team_); common.options.push_back("transifex/team=" + team_);
if (!project_.empty()) if (!project_.empty())
common.options.push_back("transifex/project=" + project_); common.options.push_back("transifex/project=" + project_);
if (!url_.empty()) if (!url_.empty())
common.options.push_back("transifex/url=" + url_); common.options.push_back("transifex/url=" + url_);
if (min_ >= 0) if (min_ >= 0)
common.options.push_back("transifex/minimum=" + std::to_string(min_)); common.options.push_back("transifex/minimum=" + std::to_string(min_));
if (force_) if (force_)
common.options.push_back("transifex/force=" + std::to_string(*force_)); common.options.push_back("transifex/force=" + std::to_string(*force_));
} }
int tx_command::do_run() int tx_command::do_run()
{ {
switch (mode_) switch (mode_) {
{ case modes::get:
case modes::get: do_get();
do_get(); break;
break;
case modes::build: case modes::build:
do_build(); do_build();
break; break;
case modes::none: case modes::none:
default: default:
u8cerr << "bad tx mode " << static_cast<int>(mode_) << "\n"; u8cerr << "bad tx mode " << static_cast<int>(mode_) << "\n";
throw bailed(); throw bailed();
} }
return 0; return 0;
} }
std::string tx_command::do_doc() std::string tx_command::do_doc()
{ {
return return "Some values will be taken from the INI file if not specified.\n"
"Some values will be taken from the INI file if not specified.\n" "\n"
"\n" "Commands:\n"
"Commands:\n" "get\n"
"get\n" " Initializes a Transifex project in the given directory if\n"
" Initializes a Transifex project in the given directory if\n" " necessary and pulls all the translation files.\n"
" necessary and pulls all the translation files.\n" "\n"
"\n" "build\n"
"build\n" " Builds all .qm files. The path can either be the transifex\n"
" Builds all .qm files. The path can either be the transifex\n" " project (where .tx is) or the `translations` directory (where the\n"
" project (where .tx is) or the `translations` directory (where the\n" " individual translation directories are).";
" individual translation directories are)."; }
}
void tx_command::do_get() void tx_command::do_get()
{ {
const url u = const url u = conf().transifex().get("url") + "/" +
conf().transifex().get("url") + "/" + conf().transifex().get("team") + "/" +
conf().transifex().get("team") + "/" + conf().transifex().get("project");
conf().transifex().get("project");
const std::string key = conf().transifex().get("key"); const std::string key = conf().transifex().get("key");
if (key.empty() && !this_env::get_opt("TX_TOKEN")) if (key.empty() && !this_env::get_opt("TX_TOKEN")) {
{ u8cout << "(no key was in the INI, --key wasn't given and TX_TOKEN env\n"
u8cout << "variable doesn't exist, this will probably fail)\n\n";
"(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";
}
// copy the global context, the tools will modify it // copy the global context, the tools will modify it
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)
.stdout_level(context::level::info) .stdout_level(context::level::info)
.root(path_) .root(path_)
.api_key(key) .api_key(key)
.url(u) .url(u)
.run(cxcopy); .run(cxcopy);
u8cout << "pulling\n"; u8cout << "pulling\n";
transifex(transifex::pull) transifex(transifex::pull)
.stdout_level(context::level::info) .stdout_level(context::level::info)
.root(path_) .root(path_)
.api_key(key) .api_key(key)
.minimum(conf().transifex().get<int>("minimum")) .minimum(conf().transifex().get<int>("minimum"))
.force(conf().transifex().get<bool>("force")) .force(conf().transifex().get<bool>("force"))
.run(cxcopy); .run(cxcopy);
} }
void tx_command::do_build() void tx_command::do_build()
{ {
fs::path root = path_; fs::path root = path_;
if (fs::exists(root / ".tx") && fs::exists(root / "translations")) if (fs::exists(root / ".tx") && fs::exists(root / "translations"))
root = root / "translations"; root = root / "translations";
tasks::translations::projects ps(root); tasks::translations::projects ps(root);
fs::path dest = dest_; fs::path dest = dest_;
op::create_directories(gcx(), dest, op::unsafe); op::create_directories(gcx(), dest, op::unsafe);
for (auto&& w : ps.warnings()) for (auto&& w : ps.warnings())
u8cerr << w << "\n"; u8cerr << w << "\n";
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
{ tp.add([&, cxcopy = gcx()]() mutable {
// copy the global context, each thread must have its own lrelease()
tp.add([&, cxcopy=gcx()]() mutable .project(p.name)
{ .sources(lg.ts_files)
lrelease() .out(dest)
.project(p.name) .run(cxcopy);
.sources(lg.ts_files) });
.out(dest) }
.run(cxcopy); }
}); }
}
}
}
} // namespace } // namespace mob
+739 -799
View File
File diff suppressed because it is too large Load Diff
+251 -253
View File
File diff suppressed because it is too large Load Diff
+455 -482
View File
File diff suppressed because it is too large Load Diff
+237 -259
View File
File diff suppressed because it is too large Load Diff
+507 -541
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More