From 536b0b839e1879fc2703d77a14ed526d5422dd31 Mon Sep 17 00:00:00 2001 From: Logan Harbour Date: Tue, 26 Nov 2024 11:13:51 -0700 Subject: [PATCH] Add MooseUtils::absolutePath(), correct data file check refs #29141 --- framework/include/utils/MooseUtils.h | 4 +++ framework/src/base/Registry.C | 18 +++++++--- framework/src/interfaces/DataFileInterface.C | 6 ++-- framework/src/utils/MooseUtils.C | 6 ++++ unit/src/RegistryTest.C | 36 ++++++++++++++++---- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/framework/include/utils/MooseUtils.h b/framework/include/utils/MooseUtils.h index 15a32b7bb7ea..58a73733d999 100644 --- a/framework/include/utils/MooseUtils.h +++ b/framework/include/utils/MooseUtils.h @@ -1234,6 +1234,10 @@ isFloat(const std::string & str) return (*ptr) == '\0'; } +/** + * Gets the absolute path of the given path + */ +std::string absolutePath(const std::string & path); } // MooseUtils namespace namespace Moose diff --git a/framework/src/base/Registry.C b/framework/src/base/Registry.C index 0f3286b92bce..8f6271cd19dc 100644 --- a/framework/src/base/Registry.C +++ b/framework/src/base/Registry.C @@ -89,8 +89,18 @@ Registry::addKnownLabel(const std::string & label) void Registry::addDataFilePath(const std::string & name, const std::string & in_tree_path) { - mooseAssert(std::filesystem::path(in_tree_path).parent_path().filename() == "data", - "Must end with data"); + // Enforce that the folder is called "data", because we rely on the installed path + // to be within PREFIX/share//data (see determineDataFilePath()) + const auto abs_in_tree_path = MooseUtils::absolutePath(in_tree_path); + const std::string folder = std::filesystem::path(abs_in_tree_path).filename(); + if (folder != "data") + mooseError("While registering data file path '", + abs_in_tree_path, + "' for '", + name, + "': The folder must be named 'data' and it is named '", + folder, + "'"); // Find either the installed or in-tree path const auto path = determineDataFilePath(name, in_tree_path); @@ -159,12 +169,12 @@ Registry::determineDataFilePath(const std::string & name, const std::string & in // Installed data const auto installed_path = MooseUtils::pathjoin(Moose::getExecutablePath(), "..", "share", name, "data"); - const std::string abs_installed_path = std::filesystem::weakly_canonical(installed_path).c_str(); + const auto abs_installed_path = MooseUtils::absolutePath(installed_path); if (MooseUtils::checkFileReadable(abs_installed_path, false, false, false)) return installed_path; // In tree data - const std::string abs_in_tree_path = std::filesystem::weakly_canonical(in_tree_path).c_str(); + const auto abs_in_tree_path = MooseUtils::absolutePath(in_tree_path); if (MooseUtils::checkFileReadable(abs_in_tree_path, false, false, false)) return abs_in_tree_path; diff --git a/framework/src/interfaces/DataFileInterface.C b/framework/src/interfaces/DataFileInterface.C index 13ccc9ec94b8..f3f167233fce 100644 --- a/framework/src/interfaces/DataFileInterface.C +++ b/framework/src/interfaces/DataFileInterface.C @@ -11,6 +11,7 @@ #include "MooseError.h" #include "ParallelParamObject.h" #include "Registry.h" +#include "MooseUtils.h" #include @@ -33,8 +34,7 @@ DataFileInterface::getDataFileName(const std::string & param) const // Look relative to the input file const auto base = _parent.parameters().getParamFileBase(param); - const std::string relative_to_context = - std::filesystem::weakly_canonical(base / value_path).c_str(); + const auto relative_to_context = MooseUtils::absolutePath(base / value_path); if (MooseUtils::checkFileReadable(relative_to_context, false, false, false)) { _parent.paramInfo(param, "Data file '", value, "' found relative to the input file."); @@ -55,7 +55,7 @@ DataFileInterface::getDataFileNameByName(const std::string & relative_path, for (const auto & [name, path] : Registry::getRegistry().getDataFilePaths()) { const auto file_path = MooseUtils::pathjoin(path, relative_path); - const std::string abs_file_path = std::filesystem::weakly_canonical(file_path).c_str(); + const std::string abs_file_path = MooseUtils::absolutePath(file_path); if (MooseUtils::checkFileReadable(abs_file_path, false, false, false)) found.emplace(name, abs_file_path); else diff --git a/framework/src/utils/MooseUtils.C b/framework/src/utils/MooseUtils.C index 921e79d33b8d..60d21a55ef1c 100644 --- a/framework/src/utils/MooseUtils.C +++ b/framework/src/utils/MooseUtils.C @@ -1273,6 +1273,12 @@ prettyCppType(const std::string & cpp_type) return s; } +std::string +absolutePath(const std::string & path) +{ + return std::filesystem::weakly_canonical(path).c_str(); +} + } // MooseUtils namespace void diff --git a/unit/src/RegistryTest.C b/unit/src/RegistryTest.C index d41cdf0e4223..d8fff68be898 100644 --- a/unit/src/RegistryTest.C +++ b/unit/src/RegistryTest.C @@ -14,6 +14,7 @@ #include "Diffusion.h" #include "MaterialRealAux.h" #include "CheckOutputAction.h" +#include "MooseUtils.h" #include @@ -31,16 +32,39 @@ TEST(RegistryTest, getClassName) EXPECT_EQ(Registry::getClassName(), "CheckOutputAction"); } +TEST(RegistryTest, addDataFilePathNonDataFolder) +{ + const std::string name = "non_data_folder"; + const std::string path = "foo"; + const std::string abs_path = MooseUtils::absolutePath(path); + + EXPECT_THROW( + { + try + { + Registry::addDataFilePath(name, path); + } + catch (const std::exception & e) + { + EXPECT_EQ(std::string(e.what()), + "While registering data file path '" + abs_path + "' for '" + name + + "': The folder must be named 'data' and it is named '" + path + "'"); + throw; + } + }, + std::exception); +} + TEST(RegistryTest, addDataFilePathMismatch) { const std::string name = "data_mismatch"; const std::string path = "data"; - const std::string abs_path = std::filesystem::weakly_canonical(path).c_str(); + const std::string abs_path = MooseUtils::absolutePath(path); Registry::addDataFilePath(name, path); const std::string other_path = "other_data/data"; - const std::string other_abs_path = std::filesystem::weakly_canonical(other_path).c_str(); + const std::string other_abs_path = MooseUtils::absolutePath(other_path); EXPECT_THROW( { @@ -63,7 +87,7 @@ TEST(RegistryTest, getDataPath) { const std::string name = "data_working"; const std::string path = "data"; - const std::string abs_path = std::filesystem::weakly_canonical(path).c_str(); + const std::string abs_path = MooseUtils::absolutePath(path); Registry::addDataFilePath(name, path); EXPECT_EQ(Registry::getDataFilePath(name), abs_path); @@ -95,7 +119,7 @@ TEST(RegistryTest, getDataPathUnregistered) TEST(RegistryTest, determineFilePath) { const std::string path = "data"; - const std::string abs_path = std::filesystem::weakly_canonical(path).c_str(); + const std::string abs_path = MooseUtils::absolutePath(path); EXPECT_EQ(Registry::determineDataFilePath("unused", path), abs_path); } @@ -103,9 +127,9 @@ TEST(RegistryTest, determineFilePathFailed) { const std::string name = "unused"; const std::string path = "foo"; - const std::string abs_path = std::filesystem::weakly_canonical(path).c_str(); + const std::string abs_path = MooseUtils::absolutePath(path); const std::string installed_path = "../share/" + name + "/data"; - const std::string installed_abs_path = std::filesystem::weakly_canonical(installed_path).c_str(); + const std::string installed_abs_path = MooseUtils::absolutePath(installed_path); EXPECT_THROW( {