https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Classes | Enumerations | Functions
Moose::DataFileUtils Namespace Reference

Classes

struct  GetPathOptions
 Options to be passed to getPath(). More...
 
struct  Path
 Representation of a data file path. More...
 

Enumerations

enum class  Context {
  RELATIVE , ABSOLUTE , DATA , RELATIVE_NOT_FOUND ,
  ABSOLUTE_NOT_FOUND , INVALID
}
 Context for where a data file came from. More...
 

Functions

Path getPath (std::string path, const GetPathOptions &options={})
 Get the data path for a given path, searching the registered data.
 
Path getPathExplicit (const std::string &data_name, const std::string &path, const std::optional< std::string > &base=std::optional< std::string >())
 Get the data path for a given path, searching the registered data given an explicit data search path.
 

Enumeration Type Documentation

◆ Context

enum class Moose::DataFileUtils::Context
strong

Context for where a data file came from.

Enumerator
RELATIVE 

Relative to the base (typically an input file)

ABSOLUTE 

An absolute path.

DATA 

From installed/in-tree data.

RELATIVE_NOT_FOUND 

Relative to the base, but not found.

ABSOLUTE_NOT_FOUND 

Absolute, but not found.

INVALID 

Unused for default.

Definition at line 21 of file DataFileUtils.h.

22{
28 DATA,
34 INVALID
35};
@ ABSOLUTE
An absolute path.
@ RELATIVE_NOT_FOUND
Relative to the base, but not found.
@ RELATIVE
Relative to the base (typically an input file)
@ DATA
From installed/in-tree data.
@ ABSOLUTE_NOT_FOUND
Absolute, but not found.

Function Documentation

◆ getPath()

Moose::DataFileUtils::Path Moose::DataFileUtils::getPath ( std::string  path,
const GetPathOptions options = {} 
)

Get the data path for a given path, searching the registered data.

Parameters
pathThe path; can be prefixed with <name>: to search only data from <name>
optionsSearch options; see docstring for GetPathOptions for more info

Definition at line 22 of file DataFileUtils.C.

23{
24 const auto & data_paths = Registry::getRegistry().getDataFilePaths();
25
26 // Search for "<name>:" prefix which is an explicit data name to search
27 std::optional<std::pair<std::string, std::string>> explicit_data;
28 if (std::smatch match; std::regex_search(path, match, std::regex("(?:([a-z0-9_]+):)?(.*)")))
29 {
30 // Has an explicit data name
31 if (match[1].matched)
32 {
33 if (const auto it = data_paths.find(match[1].str()); it != data_paths.end())
34 explicit_data = *it;
35 else
36 mooseError("Data from '", match[1], "' is not registered to be searched");
37 }
38 path = match[2];
39 }
40 else
41 mooseError("Failed to parse path '", path, "'");
42
43 const std::filesystem::path value_path = std::filesystem::path(path);
44
45 // Helper for erroring if the data name is explicitly set
46 const auto if_data_name_error = [&explicit_data](const auto & message)
47 {
48 if (explicit_data)
49 mooseError("Cannot use ",
50 message,
51 " along with a data name to search (requested "
52 "to search in '",
53 explicit_data->first,
54 "')");
55 };
56
57 // File is absolute, no need to search
58 if (std::filesystem::path(path).is_absolute())
59 {
60 // Shouldn't provide an absolute path and an explicit data name
61 if_data_name_error("an absolute path");
62
63 // File exists, we're good to go
64 if (MooseUtils::checkFileReadable(path, false, false, false))
65 return {MooseUtils::canonicalPath(path), Context::ABSOLUTE};
66
67 // If absolute and graceful, return the bad absolute path
68 if (options.graceful)
69 return {MooseUtils::canonicalPath(path), Context::ABSOLUTE_NOT_FOUND};
70
71 // If absolute and not graceful, nothing else to do
72 mooseError("The absolute path '", path, "' does not exist or is not readable.");
73 }
74
75 // Keep track of what was was searched for error context
76 std::map<std::string, std::string> not_found;
77
78 // Because no explicit data name is set, we always want to prefer
79 // checking relative paths first before searching the data
80 if (!explicit_data)
81 {
82 const std::string base = options.base ? *options.base : std::filesystem::current_path().c_str();
83 const auto relative_to_base = MooseUtils::pathjoin(base, path);
84
85 // Relative path exists
86 if (MooseUtils::checkFileReadable(relative_to_base, false, false, false))
87 return {MooseUtils::canonicalPath(relative_to_base), Context::RELATIVE};
88
89 // Without an explicit data name set, if we're set to not search all data
90 // there's nothing else to check here so we'll avoid the error at the bottom
91 // and exit immediately
92 if (!options.search_all_data && options.graceful)
93 return {MooseUtils::canonicalPath(relative_to_base), Context::RELATIVE_NOT_FOUND};
94
95 // Mark that we searched the working directory
96 not_found.emplace("working directory", MooseUtils::canonicalPath(base));
97 }
98
99 // See if we should skip searching data
100 std::optional<std::string> skip_data_reason;
101 // Path starts with ./ so don't search data
102 if (path.size() > 1 && path.substr(0, 2) == "./")
103 {
104 // Shouldn't provide a relative path and an explicit data name
105 if_data_name_error("a path that starts with './'");
106
107 // Mark that we're not checking data because it is a relative path
108 skip_data_reason = "begins with './'";
109 }
110 // Path resolves outside of . so don't search data
111 else if (const std::string proximate = std::filesystem::proximate(path).c_str();
112 (proximate.size() > 1 && proximate.substr(0, 2) == ".."))
113 {
114 // Shouldn't provide a relative path and an explicit data name
115 if_data_name_error("a relative path");
116
117 // Mark that we're not checking data because it's out of the cwd
118 skip_data_reason = "resolves behind '.'";
119 }
120
121 // Search the data if we found a reason not to and it's set
122 // to search data or we have an explicit data name to search
123 std::map<std::string, std::string> found;
124 if (!skip_data_reason && (options.search_all_data || explicit_data))
125 {
126 const auto check_data_path = [&found, &not_found, &path](const auto & entry)
127 {
128 const auto & [name, data_path] = entry;
129 const auto file_path = MooseUtils::pathjoin(data_path, path);
130 if (MooseUtils::checkFileReadable(file_path, false, false, false))
131 found.emplace(name, MooseUtils::canonicalPath(file_path));
132 else
133 not_found.emplace(name + " data", data_path);
134 };
135
136 // Explicit search, just searching one
137 if (explicit_data)
138 {
139 check_data_path(*explicit_data);
140 if (found.empty())
141 mooseError("The path '", path, "' was not found in data from '", explicit_data->first, "'");
142 }
143 // Search all data paths
144 else
145 {
146 for (const auto & entry : data_paths)
147 check_data_path(entry);
148 }
149 }
150
151 // Found exactly one
152 if (found.size() == 1)
153 {
154 const auto & [name, data_path] = *found.begin();
155 return {MooseUtils::canonicalPath(data_path), Context::DATA, name};
156 }
157
158 std::stringstream oss;
159 // Found multiple
160 if (found.size() > 1)
161 {
162 oss << "Multiple files were found when searching for the data file '" << path << "':\n\n";
163 for (const auto & [name, data_path] : found)
164 oss << " " << name << ": " << data_path << "\n";
165 const auto & first_name = found.begin()->first;
166 oss << "\nYou can resolve this ambiguity by appending a prefix with the desired data name, for "
167 "example:\n\n "
168 << first_name << ":" << path;
169 }
170 // Found none
171 else
172 {
173 oss << "Unable to find the data file '" << path << "'.\n";
174 if (not_found.size())
175 {
176 oss << "\nPaths searched:\n";
177 for (const auto & [name, data_path] : not_found)
178 oss << " " << name << ": " << data_path << "\n";
179 }
180 if (skip_data_reason)
181 oss << "\nData path(s) were not searched because search path " << *skip_data_reason << ".\n";
182 }
183
184 mooseError(oss.str());
185}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
static const std::map< std::string, std::string > & getDataFilePaths()
Returns a map of all registered data file paths (name -> path)
Definition Registry.h:271
static Registry & getRegistry()
Get the global Registry singleton.
Definition Registry.C:24
std::filesystem::path pathjoin(const std::filesystem::path &p)
Definition MooseUtils.C:70
std::string canonicalPath(const std::string &path)
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
Definition MooseUtils.C:265
std::string name(const ElemQuality q)
bool graceful
Whether or not to error whenever a path is not found.
std::optional< std::string > base
The base path by which to search for relative paths.
bool search_all_data
Whether or not to search all registered data.

Referenced by InputParameters::finalize(), DataFileInterface::getDataFilePath(), and getPathExplicit().

◆ getPathExplicit()

Moose::DataFileUtils::Path Moose::DataFileUtils::getPathExplicit ( const std::string &  data_name,
const std::string &  path,
const std::optional< std::string > &  base = std::optional<std::string>() 
)

Get the data path for a given path, searching the registered data given an explicit data search path.

This exists primarily so that you don't need to call getPath("moose:file").

Parameters
data_name- The registered data name
path- The path
base- The base by which to search for the file relative to (optional)

Definition at line 188 of file DataFileUtils.C.

191{
192 GetPathOptions options;
193 options.base = base;
194 return getPath(data_name + ":" + path, options);
195}
Path getPath(std::string path, const GetPathOptions &options={})
Get the data path for a given path, searching the registered data.
Options to be passed to getPath().