[keel] Add ability to log UUID duplication
All checks were successful
Build / build (push) Successful in 1m14s

This commit is contained in:
Gary Talent 2025-05-05 21:54:24 -05:00
parent 640ac85de4
commit 7cab133127
5 changed files with 96 additions and 27 deletions

View File

@ -15,7 +15,18 @@
namespace keel { namespace keel {
ox::Error init( ox::Error init(
keel::Context &ctx, Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName,
DuplicateSet &duplicateSet) noexcept;
ox::Result<ox::UPtr<Context>> init(
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName,
DuplicateSet &duplicateSet) noexcept;
ox::Error init(
Context &ctx,
ox::UPtr<ox::FileSystem> &&fs, ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName) noexcept; ox::StringViewCR appName) noexcept;

View File

@ -29,13 +29,14 @@ OX_MODEL_BEGIN(PreloadPtr)
OX_MODEL_FIELD(preloadAddr) OX_MODEL_FIELD(preloadAddr)
OX_MODEL_END() OX_MODEL_END()
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&addr) noexcept; ox::Result<std::size_t> getPreloadAddr(Context &ctx, ox::FileAddress const&addr) noexcept;
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::StringViewCR path) noexcept; ox::Result<std::size_t> getPreloadAddr(Context &ctx, ox::StringViewCR path) noexcept;
void createUuidMapping(Context &ctx, ox::StringViewCR filePath, ox::UUID const&uuid) noexcept; void createUuidMapping(Context &ctx, ox::StringViewCR filePath, ox::UUID const&uuid) noexcept;
ox::Error buildUuidMap(Context &ctx) noexcept; // map of UUIDs to paths
using DuplicateSet = ox::HashMap<ox::UUID, ox::Vector<ox::String>>;
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::StringViewCR path) noexcept; ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::StringViewCR path) noexcept;
@ -87,8 +88,8 @@ constexpr auto makeLoader(Context &ctx) {
} }
template<typename T> template<typename T>
ox::Result<keel::AssetRef<T>> readObjFile( ox::Result<AssetRef<T>> readObjFile(
keel::Context &ctx, Context &ctx,
ox::StringViewCR assetId, ox::StringViewCR assetId,
bool const forceLoad) noexcept { bool const forceLoad) noexcept {
static constexpr auto load = []( static constexpr auto load = [](
@ -135,11 +136,11 @@ ox::Result<keel::AssetRef<T>> readObjNoCache(
#endif #endif
ox::Error reloadAsset(keel::Context &ctx, ox::StringViewCR assetId) noexcept; ox::Error reloadAsset(Context &ctx, ox::StringViewCR assetId) noexcept;
template<typename T> template<typename T>
ox::Result<keel::AssetRef<T>> readObj( ox::Result<AssetRef<T>> readObj(
keel::Context &ctx, Context &ctx,
ox::StringViewCR assetId, ox::StringViewCR assetId,
[[maybe_unused]] bool forceLoad = false) noexcept { [[maybe_unused]] bool forceLoad = false) noexcept {
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
@ -150,8 +151,8 @@ ox::Result<keel::AssetRef<T>> readObj(
} }
template<typename T> template<typename T>
ox::Result<keel::AssetRef<T>> readObj( ox::Result<AssetRef<T>> readObj(
keel::Context &ctx, Context &ctx,
ox::FileAddress const&file, ox::FileAddress const&file,
[[maybe_unused]] bool forceLoad = false) noexcept { [[maybe_unused]] bool forceLoad = false) noexcept {
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
@ -169,7 +170,7 @@ ox::Result<keel::AssetRef<T>> readObj(
template<typename T> template<typename T>
ox::Error writeObj( ox::Error writeObj(
keel::Context &ctx, Context &ctx,
ox::FileAddress const&file, ox::FileAddress const&file,
T const&obj, T const&obj,
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept { ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
@ -177,6 +178,8 @@ ox::Error writeObj(
return ctx.rom->write(file, objBuff.data(), objBuff.size()); return ctx.rom->write(file, objBuff.data(), objBuff.size());
} }
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs, DuplicateSet &duplicateSet) noexcept;
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept; ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept;
ox::Result<ox::UPtr<ox::FileSystem>> loadRomFs(ox::StringViewCR path) noexcept; ox::Result<ox::UPtr<ox::FileSystem>> loadRomFs(ox::StringViewCR path) noexcept;

View File

@ -6,21 +6,24 @@
namespace keel { namespace keel {
ox::Error init( static ox::Error init(
keel::Context &ctx, Context &ctx,
ox::UPtr<ox::FileSystem> &&fs, ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName) noexcept { ox::StringViewCR appName,
DuplicateSet *duplicateSet) noexcept {
ctx.appName = appName; ctx.appName = appName;
std::ignore = setRomFs(ctx, std::move(fs)); std::ignore = duplicateSet ?
setRomFs(ctx, std::move(fs), *duplicateSet) :
setRomFs(ctx, std::move(fs));
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
auto const&mods = modules(); auto const&mods = modules();
for (auto &mod : mods) { for (auto &mod : mods) {
// register type converters // register type converters
for (auto c : mod->converters()) { for (auto const c : mod->converters()) {
ctx.converters.emplace_back(c); ctx.converters.emplace_back(c);
} }
// register pack transforms // register pack transforms
for (auto c : mod->packTransforms()) { for (auto const c : mod->packTransforms()) {
ctx.packTransforms.emplace_back(c); ctx.packTransforms.emplace_back(c);
} }
} }
@ -28,6 +31,30 @@ ox::Error init(
return {}; return {};
} }
ox::Error init(
Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName,
DuplicateSet &duplicateSet) noexcept {
return init(ctx, std::move(fs), appName, &duplicateSet);
}
ox::Result<ox::UPtr<Context>> init(
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName,
DuplicateSet &duplicateSet) noexcept {
auto ctx = ox::make_unique<Context>();
OX_RETURN_ERROR(keel::init(*ctx, std::move(fs), appName, &duplicateSet));
return ctx;
}
ox::Error init(
Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName) noexcept {
return init(ctx, std::move(fs), appName, nullptr);
}
ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept { ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept {
auto ctx = ox::make_unique<Context>(); auto ctx = ox::make_unique<Context>();
OX_RETURN_ERROR(keel::init(*ctx, std::move(fs), appName)); OX_RETURN_ERROR(keel::init(*ctx, std::move(fs), appName));

View File

@ -47,7 +47,7 @@ void createUuidMapping(Context &ctx, ox::StringViewCR filePath, ox::UUID const&u
ctx.uuidToPath[uuid.toString()] = filePath; ctx.uuidToPath[uuid.toString()] = filePath;
} }
static ox::Error buildUuidMap(Context &ctx, ox::StringViewCR path) noexcept { static ox::Error buildUuidMap(Context &ctx, ox::StringViewCR path, DuplicateSet *duplicates) noexcept {
OX_REQUIRE(files, ctx.rom->ls(path)); OX_REQUIRE(files, ctx.rom->ls(path));
for (auto const&f : files) { for (auto const&f : files) {
OX_REQUIRE_M(filePath, ox::join("/", ox::Array<ox::StringView, 2>{path, f})); OX_REQUIRE_M(filePath, ox::join("/", ox::Array<ox::StringView, 2>{path, f}));
@ -58,22 +58,31 @@ static ox::Error buildUuidMap(Context &ctx, ox::StringViewCR path) noexcept {
ctx.rom->read(filePath, 0, buff.size(), buff)); ctx.rom->read(filePath, 0, buff.size(), buff));
auto const [uuid, err] = readUuidHeader(buff); auto const [uuid, err] = readUuidHeader(buff);
if (!err) { if (!err) {
// check for duplication
if (duplicates && ctx.uuidToPath[uuid.toString()].len()) {
auto &dl = (*duplicates)[uuid];
if (dl.empty()) {
dl.emplace_back(ctx.uuidToPath[uuid.toString()]);
}
dl.emplace_back(filePath);
} else {
createUuidMapping(ctx, filePath, uuid); createUuidMapping(ctx, filePath, uuid);
} }
}
} else if (stat.fileType == ox::FileType::Directory) { } else if (stat.fileType == ox::FileType::Directory) {
if (!beginsWith(f, ".")) { if (!beginsWith(f, ".")) {
OX_RETURN_ERROR(buildUuidMap(ctx, filePath)); OX_RETURN_ERROR(buildUuidMap(ctx, filePath, duplicates));
} }
} }
} }
return {}; return {};
} }
ox::Error buildUuidMap(Context &ctx) noexcept { static ox::Error buildUuidMap(Context &ctx, DuplicateSet *duplicates) noexcept {
if (!ctx.rom) { if (!ctx.rom) {
return ox::Error(1, "No ROM FS"); return ox::Error{1, "No ROM FS"};
} }
return buildUuidMap(ctx, ""); return buildUuidMap(ctx, "", duplicates);
} }
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::StringViewCR path) noexcept { ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::StringViewCR path) noexcept {
@ -199,7 +208,7 @@ namespace keel {
static void clearUuidMap(Context&) noexcept { static void clearUuidMap(Context&) noexcept {
} }
ox::Error buildUuidMap(Context&) noexcept { static ox::Error buildUuidMap(Context&, DuplicateSet*) noexcept {
return {}; return {};
} }
@ -249,10 +258,16 @@ ox::Error reloadAsset(keel::Context&, ox::StringView) noexcept {
namespace keel { namespace keel {
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs, DuplicateSet &duplicateSet) noexcept {
ctx.rom = std::move(fs);
clearUuidMap(ctx);
return buildUuidMap(ctx, &duplicateSet);
}
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept { ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept {
ctx.rom = std::move(fs); ctx.rom = std::move(fs);
clearUuidMap(ctx); clearUuidMap(ctx);
return buildUuidMap(ctx); return buildUuidMap(ctx, nullptr);
} }
ox::Result<ox::UPtr<ox::FileSystem>> loadRomFs(ox::StringViewCR path) noexcept { ox::Result<ox::UPtr<ox::FileSystem>> loadRomFs(ox::StringViewCR path) noexcept {

View File

@ -55,7 +55,20 @@ static ox::Error pack(
ox::Buffer dstBuff(32 * ox::units::MB); ox::Buffer dstBuff(32 * ox::units::MB);
OX_RETURN_ERROR(ox::FileSystem32::format(dstBuff.data(), dstBuff.size())); OX_RETURN_ERROR(ox::FileSystem32::format(dstBuff.data(), dstBuff.size()));
ox::FileSystem32 dst(dstBuff); ox::FileSystem32 dst(dstBuff);
OX_REQUIRE(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack")); keel::DuplicateSet duplicateSet;
OX_REQUIRE(ctx, keel::init(
ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack", duplicateSet));
if (duplicateSet.size()) {
oxErr("Multiple files have the same UUID:\n");
for (auto const &k : duplicateSet.keys()) {
oxErrf("\n\t{}:\n", k.toString());
for (auto const &v : duplicateSet[k]) {
oxErrf("\t\t{}\n", v);
}
}
oxErr("\n");
std::exit(1);
}
keel::TypeStore ts(*ctx->rom, ox::sfmt("{}/type_descriptors", projectDataDir)); keel::TypeStore ts(*ctx->rom, ox::sfmt("{}/type_descriptors", projectDataDir));
OX_RETURN_ERROR(generateTypes(ts)); OX_RETURN_ERROR(generateTypes(ts));
keel::Manifest manifest; keel::Manifest manifest;