2020-11-09 02:46:33 -05:00
|
|
|
#include "pch.h"
|
|
|
|
|
#include "../core/conf.h"
|
|
|
|
|
#include "../core/context.h"
|
2021-02-06 17:11:22 -05:00
|
|
|
#include "../core/ini.h"
|
2020-11-09 02:46:33 -05:00
|
|
|
#include "../core/op.h"
|
2020-11-30 06:03:39 -05:00
|
|
|
#include "../tasks/task_manager.h"
|
|
|
|
|
#include "../tasks/tasks.h"
|
2020-11-09 02:46:33 -05:00
|
|
|
#include "../utility.h"
|
|
|
|
|
#include "../utility/threading.h"
|
|
|
|
|
#include "commands.h"
|
|
|
|
|
|
|
|
|
|
namespace mob {
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void set_sigint_handler();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
release_command::release_command() : command(requires_options) {}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
command::meta_t release_command::meta() const
|
|
|
|
|
{
|
|
|
|
|
return {"release", "creates a release"};
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void release_command::make_bin()
|
|
|
|
|
{
|
|
|
|
|
const auto out = out_ / make_filename("");
|
|
|
|
|
u8cout << "making binary archive " << path_to_utf8(out) << "\n";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-21 00:39:41 -05:00
|
|
|
op::archive_from_glob(gcx(), conf().path().install_bin() / "*", out,
|
|
|
|
|
{"__pycache__"});
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void release_command::make_pdbs()
|
|
|
|
|
{
|
|
|
|
|
const auto out = out_ / make_filename("pdbs");
|
|
|
|
|
u8cout << "making pdbs archive " << path_to_utf8(out) << "\n";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-21 00:39:41 -05:00
|
|
|
op::archive_from_glob(gcx(), conf().path().install_pdbs() / "*", out,
|
|
|
|
|
{"__pycache__"});
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void release_command::make_src()
|
|
|
|
|
{
|
|
|
|
|
const auto out = out_ / make_filename("src");
|
|
|
|
|
u8cout << "making src archive " << path_to_utf8(out) << "\n";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
const std::vector<std::string> ignore = {"\\..+", // dot files
|
|
|
|
|
".*\\.log", ".*\\.tlog", ".*\\.dll",
|
|
|
|
|
".*\\.exe", ".*\\.lib", ".*\\.obj",
|
|
|
|
|
".*\\.ts", ".*\\.aps", "vsbuild"};
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
const std::vector<std::regex> ignore_re(ignore.begin(), ignore.end());
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
std::vector<fs::path> files;
|
|
|
|
|
std::size_t total_size = 0;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!fs::exists(tasks::modorganizer::super_path())) {
|
|
|
|
|
gcx().bail_out(context::generic, "modorganizer super path not found: {}",
|
2020-11-18 00:42:43 -05:00
|
|
|
tasks::modorganizer::super_path());
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-18 00:42:43 -05:00
|
|
|
// build list list
|
|
|
|
|
walk_dir(tasks::modorganizer::super_path(), files, ignore_re, total_size);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
// should be below 20MB
|
2020-11-18 00:42:43 -05:00
|
|
|
const std::size_t max_expected_size = 20 * 1024 * 1024;
|
|
|
|
|
if (total_size >= max_expected_size) {
|
2020-11-09 02:46:33 -05:00
|
|
|
gcx().warning(context::generic,
|
|
|
|
|
"total size of source files would be {}, expected something "
|
|
|
|
|
"below {}, something might be wrong",
|
|
|
|
|
total_size, max_expected_size);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!force_) {
|
|
|
|
|
gcx().bail_out(context::generic, "bailing out, use --force to ignore");
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-18 00:42:43 -05:00
|
|
|
op::archive_from_files(gcx(), files, tasks::modorganizer::super_path(), out);
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void release_command::make_uibase()
|
2023-09-19 18:28:24 +02:00
|
|
|
{
|
2020-11-09 02:46:33 -05:00
|
|
|
const auto out = out_ / make_filename("uibase");
|
|
|
|
|
u8cout << "making uibase archive " << path_to_utf8(out) << "\n";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
std::vector<fs::path> files;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!fs::exists(tasks::modorganizer::super_path())) {
|
|
|
|
|
gcx().bail_out(context::generic, "modorganizer super path not found: {}",
|
2020-11-18 00:42:43 -05:00
|
|
|
tasks::modorganizer::super_path());
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-19 20:27:40 +02:00
|
|
|
op::archive_from_glob(
|
|
|
|
|
gcx(), tasks::modorganizer::super_path() / "uibase" / "src" / "*.h", out,
|
2023-09-19 18:28:24 +02:00
|
|
|
{});
|
2020-11-18 00:42:43 -05:00
|
|
|
op::archive_from_files(gcx(), {conf().path().install_libs() / "uibase.lib"},
|
|
|
|
|
conf().path().install_libs(), out);
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-07-19 20:27:40 +02:00
|
|
|
void release_command::make_installer()
|
|
|
|
|
{
|
|
|
|
|
const auto file = "Mod.Organizer-" + version_ + ".exe";
|
|
|
|
|
const auto src = conf().path().install_installer() / file;
|
|
|
|
|
const auto dest = out_;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-07-19 20:27:40 +02:00
|
|
|
u8cout << "copying installer " << file << "\n";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-07-19 20:27:40 +02:00
|
|
|
op::copy_file_to_dir_if_better(gcx(), src, dest);
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void release_command::walk_dir(const fs::path& dir, std::vector<fs::path>& files,
|
|
|
|
|
const std::vector<std::regex>& ignore_re,
|
|
|
|
|
std::size_t& total_size)
|
2023-09-19 18:28:24 +02:00
|
|
|
{
|
2020-11-09 02:46:33 -05:00
|
|
|
// adds all files that are not in the ignore list to `files`, recursive
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-21 00:39:41 -05:00
|
|
|
for (auto e : fs::directory_iterator(dir)) {
|
|
|
|
|
const auto p = e.path();
|
|
|
|
|
const auto filename = path_to_utf8(p.filename());
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
bool ignored = false;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
for (auto&& re : ignore_re) {
|
|
|
|
|
if (std::regex_match(filename, re)) {
|
2020-11-09 04:05:38 -05:00
|
|
|
ignored = true;
|
2023-09-19 18:28:24 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (ignored)
|
2020-11-09 04:05:38 -05:00
|
|
|
continue;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
if (e.is_directory()) {
|
|
|
|
|
walk_dir(e.path(), files, ignore_re, total_size);
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
|
|
|
|
else if (e.is_regular_file()) {
|
|
|
|
|
total_size += fs::file_size(p);
|
|
|
|
|
files.push_back(p);
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
fs::path release_command::make_filename(const std::string& what) const
|
|
|
|
|
{
|
|
|
|
|
std::string filename = "Mod.Organizer";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!version_.empty())
|
|
|
|
|
filename += "-" + version_;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!suffix_.empty())
|
|
|
|
|
filename += "-" + suffix_;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!what.empty())
|
|
|
|
|
filename += "-" + what;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
filename += ".7z";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
return filename;
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
clipp::group release_command::do_group()
|
|
|
|
|
{
|
|
|
|
|
return clipp::group(
|
|
|
|
|
clipp::command("release").set(picked_),
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
(clipp::option("-h", "--help") >> help_) % ("shows this message"),
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
"devbuild" %
|
|
|
|
|
(clipp::command("devbuild").set(mode_, modes::devbuild),
|
|
|
|
|
(clipp::option("--bin").set(bin_, true) |
|
|
|
|
|
clipp::option("--no-bin").set(bin_, false)) %
|
|
|
|
|
"sets whether the binary archive is created [default: yes]",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
(clipp::option("--pdbs").set(pdbs_, true) |
|
|
|
|
|
clipp::option("--no-pdbs").set(pdbs_, false)) %
|
|
|
|
|
"sets whether the PDBs archive is created [default: yes]",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
(clipp::option("--src").set(src_, true) |
|
|
|
|
|
clipp::option("--no-src").set(src_, false)) %
|
|
|
|
|
"sets whether the source archive is created [default: yes]",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
//(
|
|
|
|
|
// clipp::option("--uibase").set(uibase_, true) |
|
|
|
|
|
// clipp::option("--no-uibase").set(uibase_, false)
|
|
|
|
|
//) % "sets whether the uibase archive is created [default: yes]",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-07-19 20:27:40 +02:00
|
|
|
(clipp::option("--inst").set(installer_, true) |
|
|
|
|
|
clipp::option("--no-inst").set(installer_, false)) %
|
|
|
|
|
"sets whether the installer is copied [default: no]",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
clipp::option("--version-from-exe").set(version_exe_) %
|
|
|
|
|
"retrieves version information from ModOrganizer.exe "
|
|
|
|
|
"[default]",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
clipp::option("--version-from-rc").set(version_rc_) %
|
|
|
|
|
"retrieves version information from "
|
|
|
|
|
"modorganizer/src/version.rc",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
(clipp::option("--rc") & clipp::value("PATH") >> utf8_rc_path_) %
|
|
|
|
|
"overrides the path to version.rc",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
(clipp::option("--version") &
|
|
|
|
|
clipp::value("VERSION") >> version_) %
|
|
|
|
|
"overrides the version string",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
(clipp::option("--output-dir") &
|
|
|
|
|
clipp::value("PATH") >> utf8out_) %
|
|
|
|
|
"sets the output directory to use instead of "
|
|
|
|
|
"`$prefix/releases`",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
(clipp::option("--suffix") & clipp::value("SUFFIX") >> suffix_) %
|
|
|
|
|
"optional suffix to add to the archive filenames",
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
clipp::option("--force").set(force_) %
|
|
|
|
|
"ignores file size warnings and existing release directories")
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
|
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
"official" % (clipp::command("official").set(mode_, modes::official),
|
|
|
|
|
(clipp::value("branch") >> branch_) %
|
|
|
|
|
"use this branch in the super repos"));
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void release_command::convert_cl_to_conf()
|
2023-09-19 18:28:24 +02:00
|
|
|
{
|
2020-11-09 02:46:33 -05:00
|
|
|
command::convert_cl_to_conf();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (mode_ == modes::official) {
|
|
|
|
|
// force enable translations, installer and tx
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
common.options.push_back("task/mo_branch=" + branch_);
|
2020-11-09 04:05:38 -05:00
|
|
|
common.options.push_back("translations:task/enabled=true");
|
2020-11-09 02:46:33 -05:00
|
|
|
common.options.push_back("installer:task/enabled=true");
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
common.options.push_back("transifex/force=true");
|
|
|
|
|
common.options.push_back("transifex/configure=true");
|
|
|
|
|
common.options.push_back("transifex/pull=true");
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
int release_command::do_run()
|
2023-09-19 18:28:24 +02:00
|
|
|
{
|
2020-11-09 02:46:33 -05:00
|
|
|
switch (mode_) {
|
|
|
|
|
case modes::devbuild:
|
|
|
|
|
return do_devbuild();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
case modes::official:
|
|
|
|
|
return do_official();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
case modes::none:
|
|
|
|
|
default:
|
|
|
|
|
u8cerr << "bad release mode " << static_cast<int>(mode_) << "\n";
|
|
|
|
|
throw bailed();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
int release_command::do_devbuild()
|
|
|
|
|
{
|
|
|
|
|
prepare();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
u8cout
|
|
|
|
|
<< ">> don't forget to update the version number before making a release\n"
|
|
|
|
|
<< "\n"
|
|
|
|
|
<< "creating release for " << version_ << "\n";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (bin_)
|
|
|
|
|
make_bin();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (pdbs_)
|
|
|
|
|
make_pdbs();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (src_)
|
|
|
|
|
make_src();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-07-19 20:27:40 +02:00
|
|
|
if (uibase_)
|
|
|
|
|
make_uibase();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (installer_)
|
|
|
|
|
make_installer();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
return 0;
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
int release_command::do_official()
|
|
|
|
|
{
|
|
|
|
|
set_sigint_handler();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
// make sure the given branch exists in all repos, this avoids failure
|
|
|
|
|
// much later on in the process; throws on failure
|
|
|
|
|
check_repos_for_branch();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
// if the prefix exists, asks the user to delete it
|
|
|
|
|
if (!check_clean_prefix())
|
|
|
|
|
return 1;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-30 06:03:39 -05:00
|
|
|
task_manager::instance().run_all();
|
2020-11-09 04:05:38 -05:00
|
|
|
build_command::terminate_msbuild();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
prepare();
|
|
|
|
|
make_bin();
|
|
|
|
|
make_pdbs();
|
|
|
|
|
make_src();
|
2021-07-19 20:27:40 +02:00
|
|
|
make_uibase();
|
2020-11-09 04:05:38 -05:00
|
|
|
make_installer();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
return 0;
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
void release_command::check_repos_for_branch()
|
|
|
|
|
{
|
2020-11-09 02:46:33 -05:00
|
|
|
u8cout << "checking repos for branch " << branch_ << "...\n";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
thread_pool tp;
|
|
|
|
|
std::atomic<bool> failed = false;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-30 06:03:39 -05:00
|
|
|
for (const auto* t : task_manager::instance().find("super")) {
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!t->enabled())
|
|
|
|
|
continue;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
tp.add([this, t, &failed] {
|
2020-11-18 00:42:43 -05:00
|
|
|
const auto* o = dynamic_cast<const tasks::modorganizer*>(t);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-25 10:56:18 -05:00
|
|
|
if (!git_wrap::remote_branch_exists(o->git_url(), branch_)) {
|
2020-11-09 02:46:33 -05:00
|
|
|
gcx().error(context::generic,
|
|
|
|
|
"branch {} doesn't exist in the {} repo", branch_,
|
|
|
|
|
o->name());
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
failed = true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
tp.join();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (failed) {
|
|
|
|
|
gcx().bail_out(context::generic,
|
|
|
|
|
"either fix the branch name, create a remote branch for the "
|
|
|
|
|
"repos that don't have it, or disable tasks with "
|
|
|
|
|
"`-s TASKNAME:task/enabled=false`");
|
2023-09-19 18:28:24 +02:00
|
|
|
}
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
bool release_command::check_clean_prefix()
|
|
|
|
|
{
|
2020-11-21 00:39:41 -05:00
|
|
|
const auto prefix = conf().path().prefix();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-21 00:08:45 -05:00
|
|
|
if (!fs::exists(prefix))
|
2020-11-09 04:05:38 -05:00
|
|
|
return true;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
bool saw_file = false;
|
|
|
|
|
const fs::path log_file = conf().global().get("log_file");
|
|
|
|
|
const std::string ini_file = default_ini_filename();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
for (auto itor : fs::directory_iterator(prefix)) {
|
|
|
|
|
const auto name = itor.path().filename();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
// ignore ini and logs
|
|
|
|
|
if (name == log_file.filename() || name == ini_file)
|
|
|
|
|
continue;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
saw_file = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
if (!saw_file) {
|
|
|
|
|
// empty directory, that's fine
|
2020-11-09 04:05:38 -05:00
|
|
|
return true;
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
const auto q =
|
|
|
|
|
fmt::format("prefix {} already exists, delete?", path_to_utf8(prefix));
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
if (ask_yes_no(q, yn::no) != yn::yes)
|
|
|
|
|
return false;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
// the log file might be in this directory, close it now and reopen it
|
|
|
|
|
// when deletion is finished
|
|
|
|
|
context::close_log_file();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
build_command::terminate_msbuild();
|
|
|
|
|
op::delete_directory(gcx(), prefix);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
// reopen log file
|
|
|
|
|
conf().set_log_file();
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2021-02-06 17:11:22 -05:00
|
|
|
return true;
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void release_command::prepare()
|
|
|
|
|
{
|
2020-11-09 04:05:38 -05:00
|
|
|
// finding rc file
|
2020-11-09 02:46:33 -05:00
|
|
|
rc_path_ = fs::path(utf8_to_utf16(utf8_rc_path_));
|
|
|
|
|
if (rc_path_.empty()) {
|
2020-11-18 00:42:43 -05:00
|
|
|
rc_path_ = tasks::modorganizer::super_path() / "modorganizer" / "src" /
|
|
|
|
|
"version.rc";
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
// getting version from rc or exe
|
2020-11-09 02:46:33 -05:00
|
|
|
if (version_.empty()) {
|
|
|
|
|
if (version_rc_)
|
|
|
|
|
version_ = version_from_rc();
|
|
|
|
|
else
|
|
|
|
|
version_ = version_from_exe();
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 04:05:38 -05:00
|
|
|
// finding output path
|
2020-11-21 00:39:41 -05:00
|
|
|
const auto prefix = conf().path().prefix();
|
2020-11-09 02:46:33 -05:00
|
|
|
out_ = fs::path(utf8_to_utf16(utf8out_));
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (out_.empty())
|
2020-11-21 00:08:45 -05:00
|
|
|
out_ = prefix / "releases" / version_;
|
2020-11-09 02:46:33 -05:00
|
|
|
else if (out_.is_relative())
|
2020-11-21 00:08:45 -05:00
|
|
|
out_ = prefix / out_;
|
2020-11-09 02:46:33 -05:00
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
std::string release_command::do_doc()
|
|
|
|
|
{
|
|
|
|
|
return "Creates archives for an MO installation, PDBs and sources.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Commands:\n"
|
|
|
|
|
"devbuild\n"
|
|
|
|
|
" Can creates three archives in `$prefix/releases/version`: one from\n"
|
|
|
|
|
" `install/bin/*`, one from `install/pdbs/*` and another with the\n"
|
|
|
|
|
" sources of projects from modorganizer_super.\n"
|
|
|
|
|
" \n"
|
|
|
|
|
" The archive filename is `Mod.Organizer-version-suffix-what.7z`,\n"
|
|
|
|
|
" where:\n"
|
|
|
|
|
" - `version` is taken from `ModOrganizer.exe`, `version.rc`\n"
|
|
|
|
|
" or from --version;\n"
|
|
|
|
|
" - `suffix` is the optional `--suffix` argument;\n"
|
|
|
|
|
" - `what` is either nothing, `src` or `pdbs`.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"official\n"
|
|
|
|
|
" Creates a new full build in the prefix. Requires that directory\n"
|
|
|
|
|
" to be empty. Puts the binary archive, source, PDBs and installer\n"
|
|
|
|
|
" in `$prefix/releases/version`. Forces all tasks to be enabled,\n"
|
|
|
|
|
" including translations and installer. Make sure the transifex API\n"
|
|
|
|
|
" key is in the INI or TX_TOKEN is set.";
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
std::string release_command::version_from_exe() const
|
|
|
|
|
{
|
2020-11-21 00:39:41 -05:00
|
|
|
const auto exe = conf().path().install_bin() / "ModOrganizer.exe";
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
// getting version info size
|
|
|
|
|
DWORD dummy = 0;
|
|
|
|
|
const DWORD size = GetFileVersionInfoSizeW(exe.native().c_str(), &dummy);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (size == 0) {
|
|
|
|
|
const auto e = GetLastError();
|
|
|
|
|
gcx().bail_out(context::generic,
|
|
|
|
|
"can't get file version info size from {}, {}", exe,
|
|
|
|
|
error_message(e));
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
// getting version info
|
|
|
|
|
auto buffer = std::make_unique<std::byte[]>(size);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!GetFileVersionInfoW(exe.native().c_str(), 0, size, buffer.get())) {
|
|
|
|
|
const auto e = GetLastError();
|
|
|
|
|
gcx().bail_out(context::generic, "can't get file version info from {}, {}",
|
|
|
|
|
exe, error_message(e));
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
struct LANGANDCODEPAGE {
|
|
|
|
|
WORD wLanguage;
|
|
|
|
|
WORD wCodePage;
|
|
|
|
|
};
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
void* value_pointer = nullptr;
|
|
|
|
|
unsigned int value_size = 0;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
// getting list of available languages
|
|
|
|
|
auto ret = VerQueryValueW(buffer.get(), L"\\VarFileInfo\\Translation",
|
|
|
|
|
&value_pointer, &value_size);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!ret || !value_pointer || value_size == 0) {
|
|
|
|
|
const auto e = GetLastError();
|
|
|
|
|
gcx().bail_out(context::generic,
|
|
|
|
|
"VerQueryValueW() for translations failed on {}, {}", exe,
|
|
|
|
|
error_message(e));
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
// number of languages
|
|
|
|
|
const auto count = value_size / sizeof(LANGANDCODEPAGE);
|
|
|
|
|
if (count == 0)
|
|
|
|
|
gcx().bail_out(context::generic, "no languages found in {}", exe);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
// using the first language in the list to get FileVersion
|
|
|
|
|
const auto* lcp = static_cast<LANGANDCODEPAGE*>(value_pointer);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-18 00:42:43 -05:00
|
|
|
const auto sub_block =
|
2020-11-09 02:46:33 -05:00
|
|
|
fmt::format(L"\\StringFileInfo\\{:04x}{:04x}\\FileVersion", lcp->wLanguage,
|
|
|
|
|
lcp->wCodePage);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
ret = VerQueryValueW(buffer.get(), sub_block.c_str(), &value_pointer,
|
|
|
|
|
&value_size);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (!ret || !value_pointer || value_size == 0) {
|
|
|
|
|
gcx().bail_out(context::generic, "language {} not found in {}", sub_block,
|
|
|
|
|
exe);
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
// value_size includes the null terminator
|
|
|
|
|
return utf16_to_utf8(
|
|
|
|
|
std::wstring(static_cast<wchar_t*>(value_pointer), value_size - 1));
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
std::string release_command::version_from_rc() const
|
|
|
|
|
{
|
|
|
|
|
// matching: #define VER_FILEVERSION_STR "2.2.1\0"
|
|
|
|
|
std::regex re(R"(#define VER_FILEVERSION_STR "(.+)\\0")");
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
const std::string rc = op::read_text_file(gcx(), encodings::utf8, rc_path_);
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
std::smatch m;
|
|
|
|
|
std::string v;
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
for_each_line(rc, [&](std::string_view line) {
|
|
|
|
|
std::string line_s(line);
|
|
|
|
|
if (std::regex_match(line_s, m, re))
|
|
|
|
|
v = m[1];
|
|
|
|
|
});
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
if (v.empty()) {
|
|
|
|
|
gcx().bail_out(context::generic, "can't find version string in {}",
|
|
|
|
|
rc_path_);
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
return v;
|
|
|
|
|
}
|
2023-09-19 18:28:24 +02:00
|
|
|
|
2020-11-09 02:46:33 -05:00
|
|
|
} // namespace mob
|