metaforce/hecl/driver/ToolPackage.hpp

217 lines
8.2 KiB
C++
Raw Normal View History

2018-10-07 03:38:44 +00:00
#pragma once
2015-06-10 02:40:03 +00:00
#include <vector>
#include <string>
#include "ToolBase.hpp"
2017-12-29 07:56:31 +00:00
#include <cstdio>
2015-06-10 02:40:03 +00:00
class ToolPackage final : public ToolBase
{
2017-10-25 07:46:32 +00:00
std::vector<hecl::ProjectPath> m_selectedItems;
std::unique_ptr<hecl::Database::Project> m_fallbackProj;
hecl::Database::Project* m_useProj;
2018-03-23 21:40:12 +00:00
const hecl::Database::DataSpecEntry* m_spec = nullptr;
2017-10-25 07:46:32 +00:00
bool m_fast = false;
void AddSelectedItem(const hecl::ProjectPath& path)
{
for (const hecl::ProjectPath& item : m_selectedItems)
if (item == path)
return;
m_selectedItems.push_back(path);
}
2017-10-27 10:10:08 +00:00
void CheckFile(const hecl::ProjectPath& path)
{
2018-10-14 20:09:15 +00:00
if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!world.blend")))
2017-10-27 10:10:08 +00:00
AddSelectedItem(path);
#if RUNTIME_ORIGINAL_IDS
2018-10-14 20:09:15 +00:00
else if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!original_ids.yaml")))
2017-10-27 10:10:08 +00:00
{
auto pathComps = path.getPathComponents();
2018-10-14 20:09:15 +00:00
if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out"))
2017-10-27 10:10:08 +00:00
AddSelectedItem(path);
}
#endif
2017-10-27 10:10:08 +00:00
}
2017-10-25 07:46:32 +00:00
void FindSelectedItems(const hecl::ProjectPath& path, bool checkGeneral)
{
2017-10-27 10:10:08 +00:00
if (path.isFile())
{
CheckFile(path);
return;
}
2017-10-25 07:46:32 +00:00
2017-10-27 10:10:08 +00:00
size_t origSize = m_selectedItems.size();
2017-10-25 07:46:32 +00:00
hecl::DirectoryEnumerator dEnum(path.getAbsolutePath(),
hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const auto& ent : dEnum)
{
hecl::ProjectPath childPath(path, ent.m_name);
if (ent.m_isDir)
FindSelectedItems(childPath, checkGeneral && childPath.getPathComponents().size() <= 2);
2017-10-27 10:10:08 +00:00
else
CheckFile(childPath);
2017-10-25 07:46:32 +00:00
}
2018-01-12 02:31:25 +00:00
/* Directory with 2 components not "Shared" or macOS app bundle
2018-01-12 01:31:25 +00:00
* and no nested !world.blend files == General PAK */
2017-10-27 10:10:08 +00:00
if (checkGeneral && origSize == m_selectedItems.size())
2017-10-25 07:46:32 +00:00
{
auto pathComps = path.getPathComponents();
2018-10-14 20:09:15 +00:00
if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out") &&
pathComps[1] != _SYS_STR("Shared") && pathComps[0].find(_SYS_STR(".app")) == hecl::SystemString::npos)
2017-10-25 07:46:32 +00:00
AddSelectedItem(path);
}
}
2015-06-10 02:40:03 +00:00
public:
ToolPackage(const ToolPassInfo& info)
2017-10-25 07:46:32 +00:00
: ToolBase(info), m_useProj(info.project)
2015-06-10 02:40:03 +00:00
{
2015-07-08 04:26:29 +00:00
if (!info.project)
2016-03-04 23:02:44 +00:00
LogModule.report(logvisor::Fatal, "hecl package must be ran within a project directory");
2017-10-25 07:46:32 +00:00
/* Scan args */
if (info.args.size())
{
/* See if project path is supplied via args and use that over the getcwd one */
m_selectedItems.reserve(info.args.size());
for (const hecl::SystemString& arg : info.args)
{
if (arg.empty())
continue;
2018-10-14 20:09:15 +00:00
else if (!arg.compare(_SYS_STR("--fast")))
2017-10-25 07:46:32 +00:00
{
m_fast = true;
continue;
}
2018-10-14 20:09:15 +00:00
else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec=")))
2018-03-23 21:40:12 +00:00
{
hecl::SystemString specName(arg.begin() + 7, arg.end());
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY)
{
if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str()))
{
m_spec = spec;
break;
}
}
if (!m_spec)
LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str());
continue;
}
2018-10-14 20:09:15 +00:00
else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-'))
2017-10-25 07:46:32 +00:00
continue;
hecl::SystemString subPath;
hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath);
if (root)
{
if (!m_fallbackProj)
{
m_fallbackProj.reset(new hecl::Database::Project(root));
m_useProj = m_fallbackProj.get();
}
else if (m_fallbackProj->getProjectRootPath() != root)
LogModule.report(logvisor::Fatal,
2018-10-14 20:09:15 +00:00
_SYS_STR("hecl package can only process multiple items in the same project; ")
_SYS_STR("'%s' and '%s' are different projects"),
2017-11-13 06:13:53 +00:00
m_fallbackProj->getProjectRootPath().getAbsolutePath().data(),
root.getAbsolutePath().data());
2017-10-25 07:46:32 +00:00
FindSelectedItems({*m_useProj, subPath}, true);
}
}
}
if (!m_useProj)
LogModule.report(logvisor::Fatal,
"hecl package must be ran within a project directory or "
"provided a path within a project");
/* Default case: recursive at root */
if (m_selectedItems.empty())
2018-10-14 20:09:15 +00:00
FindSelectedItems({*m_useProj, _SYS_STR("")}, true);
2015-06-10 02:40:03 +00:00
}
static void Help(HelpOutput& help)
{
2018-10-14 20:09:15 +00:00
help.secHead(_SYS_STR("NAME"));
2015-06-10 02:40:03 +00:00
help.beginWrap();
2018-10-14 20:09:15 +00:00
help.wrap(_SYS_STR("hecl-pack\n")
_SYS_STR("hecl-package - Package objects within the project database\n"));
2015-06-10 02:40:03 +00:00
help.endWrap();
2018-10-14 20:09:15 +00:00
help.secHead(_SYS_STR("SYNOPSIS"));
2015-06-10 02:40:03 +00:00
help.beginWrap();
2018-10-14 20:09:15 +00:00
help.wrap(_SYS_STR("hecl package [--spec=<spec>] [<input-dir>]\n"));
2015-06-10 02:40:03 +00:00
help.endWrap();
2018-10-14 20:09:15 +00:00
help.secHead(_SYS_STR("DESCRIPTION"));
2015-06-10 02:40:03 +00:00
help.beginWrap();
2018-10-14 20:09:15 +00:00
help.wrap(_SYS_STR("This command initiates a packaging pass on the project database. Packaging ")
_SYS_STR("is analogous to linking in software development. All objects necessary to ")
_SYS_STR("generate a complete package are gathered, grouped, and indexed within a .upak file.\n"));
2015-06-10 02:40:03 +00:00
help.endWrap();
2018-10-14 20:09:15 +00:00
help.secHead(_SYS_STR("OPTIONS"));
help.optionHead(_SYS_STR("--spec=<spec>"), _SYS_STR("data specification"));
2015-06-10 02:40:03 +00:00
help.beginWrap();
2018-10-14 20:09:15 +00:00
help.wrap(_SYS_STR("Specifies a DataSpec to use when cooking and generating the package. ")
_SYS_STR("This build of hecl supports the following values of <spec>:\n"));
2018-03-23 21:40:12 +00:00
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY)
{
if (!spec->m_factory)
continue;
2018-10-14 20:09:15 +00:00
help.wrap(_SYS_STR(" "));
2018-03-23 21:40:12 +00:00
help.wrapBold(spec->m_name.data());
2018-10-14 20:09:15 +00:00
help.wrap(_SYS_STR("\n"));
2018-03-23 21:40:12 +00:00
}
2015-06-10 02:40:03 +00:00
help.endWrap();
2018-10-14 20:09:15 +00:00
help.secHead(_SYS_STR("OPTIONS"));
help.optionHead(_SYS_STR("<input-dir>"), _SYS_STR("input directory"));
2015-06-10 02:40:03 +00:00
help.beginWrap();
2018-10-14 20:09:15 +00:00
help.wrap(_SYS_STR("Specifies a project subdirectory to root the resulting package from. ")
_SYS_STR("If any dependent files fall outside this subdirectory, they will be implicitly ")
_SYS_STR("gathered and packaged.\n"));
2015-06-10 02:40:03 +00:00
help.endWrap();
}
2018-10-14 20:09:15 +00:00
hecl::SystemString toolName() const {return _SYS_STR("package");}
2015-06-10 02:40:03 +00:00
int run()
{
2017-10-25 07:46:32 +00:00
if (XTERM_COLOR)
2018-10-14 20:09:15 +00:00
hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO PACKAGE:" NORMAL "\n"));
2017-10-25 07:46:32 +00:00
else
2018-10-14 20:09:15 +00:00
hecl::Printf(_SYS_STR("ABOUT TO PACKAGE:\n"));
2017-10-25 07:46:32 +00:00
for (auto& item : m_selectedItems)
2018-10-14 20:09:15 +00:00
hecl::Printf(_SYS_STR(" %s\n"), item.getRelativePath().data());
2018-01-21 22:03:48 +00:00
fflush(stdout);
2017-10-25 07:46:32 +00:00
if (continuePrompt())
{
2018-03-23 21:40:12 +00:00
hecl::MultiProgressPrinter printer(true);
2018-05-25 06:34:58 +00:00
hecl::ClientProcess cp(&printer);
2017-10-25 07:46:32 +00:00
for (const hecl::ProjectPath& path : m_selectedItems)
{
2018-03-23 21:40:12 +00:00
if (!m_useProj->packagePath(path, printer, m_fast, m_spec, &cp))
2018-10-14 20:09:15 +00:00
LogModule.report(logvisor::Error, _SYS_STR("Unable to package %s"), path.getAbsolutePath().data());
2017-10-25 07:46:32 +00:00
}
cp.waitUntilComplete();
}
2015-06-10 02:40:03 +00:00
return 0;
}
void cancel()
{
m_useProj->interruptCook();
}
2015-06-10 02:40:03 +00:00
};