From 7cab133127f464fe7ede3d2ef022328a07a1b1c3 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Mon, 5 May 2025 21:54:24 -0500 Subject: [PATCH] [keel] Add ability to log UUID duplication --- src/olympic/keel/include/keel/keel.hpp | 13 ++++++++- src/olympic/keel/include/keel/media.hpp | 25 +++++++++------- src/olympic/keel/src/keel.cpp | 39 +++++++++++++++++++++---- src/olympic/keel/src/media.cpp | 31 +++++++++++++++----- src/olympic/keel/src/pack-applib.cpp | 15 +++++++++- 5 files changed, 96 insertions(+), 27 deletions(-) diff --git a/src/olympic/keel/include/keel/keel.hpp b/src/olympic/keel/include/keel/keel.hpp index f03b2bbb..b2057039 100644 --- a/src/olympic/keel/include/keel/keel.hpp +++ b/src/olympic/keel/include/keel/keel.hpp @@ -15,7 +15,18 @@ namespace keel { ox::Error init( - keel::Context &ctx, + Context &ctx, + ox::UPtr &&fs, + ox::StringViewCR appName, + DuplicateSet &duplicateSet) noexcept; + +ox::Result> init( + ox::UPtr &&fs, + ox::StringViewCR appName, + DuplicateSet &duplicateSet) noexcept; + +ox::Error init( + Context &ctx, ox::UPtr &&fs, ox::StringViewCR appName) noexcept; diff --git a/src/olympic/keel/include/keel/media.hpp b/src/olympic/keel/include/keel/media.hpp index 789bfe67..cc725388 100644 --- a/src/olympic/keel/include/keel/media.hpp +++ b/src/olympic/keel/include/keel/media.hpp @@ -29,13 +29,14 @@ OX_MODEL_BEGIN(PreloadPtr) OX_MODEL_FIELD(preloadAddr) OX_MODEL_END() -ox::Result getPreloadAddr(keel::Context &ctx, ox::FileAddress const&addr) noexcept; -ox::Result getPreloadAddr(keel::Context &ctx, ox::StringViewCR path) noexcept; +ox::Result getPreloadAddr(Context &ctx, ox::FileAddress const&addr) noexcept; +ox::Result getPreloadAddr(Context &ctx, ox::StringViewCR path) 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::Result pathToUuid(Context &ctx, ox::StringViewCR path) noexcept; @@ -87,8 +88,8 @@ constexpr auto makeLoader(Context &ctx) { } template -ox::Result> readObjFile( - keel::Context &ctx, +ox::Result> readObjFile( + Context &ctx, ox::StringViewCR assetId, bool const forceLoad) noexcept { static constexpr auto load = []( @@ -135,11 +136,11 @@ ox::Result> readObjNoCache( #endif -ox::Error reloadAsset(keel::Context &ctx, ox::StringViewCR assetId) noexcept; +ox::Error reloadAsset(Context &ctx, ox::StringViewCR assetId) noexcept; template -ox::Result> readObj( - keel::Context &ctx, +ox::Result> readObj( + Context &ctx, ox::StringViewCR assetId, [[maybe_unused]] bool forceLoad = false) noexcept { #ifndef OX_BARE_METAL @@ -150,8 +151,8 @@ ox::Result> readObj( } template -ox::Result> readObj( - keel::Context &ctx, +ox::Result> readObj( + Context &ctx, ox::FileAddress const&file, [[maybe_unused]] bool forceLoad = false) noexcept { #ifndef OX_BARE_METAL @@ -169,7 +170,7 @@ ox::Result> readObj( template ox::Error writeObj( - keel::Context &ctx, + Context &ctx, ox::FileAddress const&file, T const&obj, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept { @@ -177,6 +178,8 @@ ox::Error writeObj( return ctx.rom->write(file, objBuff.data(), objBuff.size()); } +ox::Error setRomFs(Context &ctx, ox::UPtr &&fs, DuplicateSet &duplicateSet) noexcept; + ox::Error setRomFs(Context &ctx, ox::UPtr &&fs) noexcept; ox::Result> loadRomFs(ox::StringViewCR path) noexcept; diff --git a/src/olympic/keel/src/keel.cpp b/src/olympic/keel/src/keel.cpp index 9f857703..a6b07f94 100644 --- a/src/olympic/keel/src/keel.cpp +++ b/src/olympic/keel/src/keel.cpp @@ -6,21 +6,24 @@ namespace keel { -ox::Error init( - keel::Context &ctx, +static ox::Error init( + Context &ctx, ox::UPtr &&fs, - ox::StringViewCR appName) noexcept { + ox::StringViewCR appName, + DuplicateSet *duplicateSet) noexcept { 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 auto const&mods = modules(); for (auto &mod : mods) { // register type converters - for (auto c : mod->converters()) { + for (auto const c : mod->converters()) { ctx.converters.emplace_back(c); } // register pack transforms - for (auto c : mod->packTransforms()) { + for (auto const c : mod->packTransforms()) { ctx.packTransforms.emplace_back(c); } } @@ -28,6 +31,30 @@ ox::Error init( return {}; } +ox::Error init( + Context &ctx, + ox::UPtr &&fs, + ox::StringViewCR appName, + DuplicateSet &duplicateSet) noexcept { + return init(ctx, std::move(fs), appName, &duplicateSet); +} + +ox::Result> init( + ox::UPtr &&fs, + ox::StringViewCR appName, + DuplicateSet &duplicateSet) noexcept { + auto ctx = ox::make_unique(); + OX_RETURN_ERROR(keel::init(*ctx, std::move(fs), appName, &duplicateSet)); + return ctx; +} + +ox::Error init( + Context &ctx, + ox::UPtr &&fs, + ox::StringViewCR appName) noexcept { + return init(ctx, std::move(fs), appName, nullptr); +} + ox::Result> init(ox::UPtr &&fs, ox::StringViewCR appName) noexcept { auto ctx = ox::make_unique(); OX_RETURN_ERROR(keel::init(*ctx, std::move(fs), appName)); diff --git a/src/olympic/keel/src/media.cpp b/src/olympic/keel/src/media.cpp index c6982d21..2ff71502 100644 --- a/src/olympic/keel/src/media.cpp +++ b/src/olympic/keel/src/media.cpp @@ -47,7 +47,7 @@ void createUuidMapping(Context &ctx, ox::StringViewCR filePath, ox::UUID const&u 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)); for (auto const&f : files) { OX_REQUIRE_M(filePath, ox::join("/", ox::Array{path, f})); @@ -58,22 +58,31 @@ static ox::Error buildUuidMap(Context &ctx, ox::StringViewCR path) noexcept { ctx.rom->read(filePath, 0, buff.size(), buff)); auto const [uuid, err] = readUuidHeader(buff); if (!err) { - createUuidMapping(ctx, filePath, uuid); + // 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); + } } } else if (stat.fileType == ox::FileType::Directory) { if (!beginsWith(f, ".")) { - OX_RETURN_ERROR(buildUuidMap(ctx, filePath)); + OX_RETURN_ERROR(buildUuidMap(ctx, filePath, duplicates)); } } } return {}; } -ox::Error buildUuidMap(Context &ctx) noexcept { +static ox::Error buildUuidMap(Context &ctx, DuplicateSet *duplicates) noexcept { 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 pathToUuid(Context &ctx, ox::StringViewCR path) noexcept { @@ -199,7 +208,7 @@ namespace keel { static void clearUuidMap(Context&) noexcept { } -ox::Error buildUuidMap(Context&) noexcept { +static ox::Error buildUuidMap(Context&, DuplicateSet*) noexcept { return {}; } @@ -249,10 +258,16 @@ ox::Error reloadAsset(keel::Context&, ox::StringView) noexcept { namespace keel { +ox::Error setRomFs(Context &ctx, ox::UPtr &&fs, DuplicateSet &duplicateSet) noexcept { + ctx.rom = std::move(fs); + clearUuidMap(ctx); + return buildUuidMap(ctx, &duplicateSet); +} + ox::Error setRomFs(Context &ctx, ox::UPtr &&fs) noexcept { ctx.rom = std::move(fs); clearUuidMap(ctx); - return buildUuidMap(ctx); + return buildUuidMap(ctx, nullptr); } ox::Result> loadRomFs(ox::StringViewCR path) noexcept { diff --git a/src/olympic/keel/src/pack-applib.cpp b/src/olympic/keel/src/pack-applib.cpp index 08597cfe..5222e033 100644 --- a/src/olympic/keel/src/pack-applib.cpp +++ b/src/olympic/keel/src/pack-applib.cpp @@ -55,7 +55,20 @@ static ox::Error pack( ox::Buffer dstBuff(32 * ox::units::MB); OX_RETURN_ERROR(ox::FileSystem32::format(dstBuff.data(), dstBuff.size())); ox::FileSystem32 dst(dstBuff); - OX_REQUIRE(ctx, keel::init(ox::make_unique(argSrc), "keel-pack")); + keel::DuplicateSet duplicateSet; + OX_REQUIRE(ctx, keel::init( + ox::make_unique(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)); OX_RETURN_ERROR(generateTypes(ts)); keel::Manifest manifest;