Loading [MathJax]/extensions/tex2jax.js
https://mooseframework.inl.gov
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
Classes | Enumerations | Functions
Moose::DataFileUtils Namespace Reference

Classes

struct  Path
 Representation of a data file path. More...
 

Enumerations

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

Functions

Path getPath (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. More...
 
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. More...
 

Enumeration Type Documentation

◆ Context

Context for where a data file came from.

Enumerator
RELATIVE 
ABSOLUTE 
DATA 
INVALID 

Unused for default.

Definition at line 21 of file DataFileUtils.h.

22 {
23  // Relative to the base (typically an input file)
24  RELATIVE,
25  // An absolute path
26  ABSOLUTE,
27  // From installed/in-tree data
28  DATA,
30  INVALID
31 };
INVALID

Function Documentation

◆ getPath()

Moose::DataFileUtils::Path Moose::DataFileUtils::getPath ( 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.

Parameters
path- The path; can be prefixed with <name>: to search only data from <name>
base- The base by which to search for the file relative to (optional)

Definition at line 22 of file DataFileUtils.C.

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

23 {
24  const auto & data_paths = Registry::getRegistry().getDataFilePaths();
25 
26  // Search for "<name>:" prefix which is a data name to limit the search to
27  std::optional<std::string> data_name;
28  std::smatch match;
29  if (std::regex_search(path, match, std::regex("(?:(\\w+):)?(.*)")))
30  {
31  if (match[1].matched)
32  {
33  data_name = match[1];
34  if (!data_paths.count(*data_name))
35  mooseError("Data from '", *data_name, "' is not registered to be searched");
36  }
37  path = match[2];
38  }
39  else
40  mooseError("Failed to parse path '", path, "'");
41 
42  const std::filesystem::path value_path = std::filesystem::path(path);
43 
44  // File is absolute, no need to search
45  if (std::filesystem::path(path).is_absolute())
46  {
47  if (data_name)
48  mooseError("Should not specify an absolute path along with a data name to search (requested "
49  "to search in '",
50  *data_name,
51  "')");
52  if (MooseUtils::checkFileReadable(path, false, false, false))
53  return {MooseUtils::canonicalPath(path), Context::ABSOLUTE};
54  mooseError("The absolute path '", path, "' does not exist or is not readable.");
55  }
56 
57  // Keep track of what was was searched for error context
58  std::map<std::string, std::string> not_found;
59 
60  // Relative to the base, if provided
61  if (base)
62  {
63  const auto relative_to_base = MooseUtils::pathjoin(*base, path);
64  if (MooseUtils::checkFileReadable(relative_to_base, false, false, false))
65  return {MooseUtils::canonicalPath(relative_to_base), Context::RELATIVE};
66  not_found.emplace("working directory", MooseUtils::canonicalPath(*base));
67  }
68 
69  // See if we should skip searching data
70  std::optional<std::string> skip_data_reason;
71  // Path starts with ./ so don't search data
72  if (path.size() > 1 && path.substr(0, 2) == "./")
73  {
74  skip_data_reason = "begins with './'";
75  }
76  else
77  {
78  // Path resolves outside of . so don't search data
79  const std::string proximate = std::filesystem::proximate(path).c_str();
80  if (proximate.size() > 1 && proximate.substr(0, 2) == "..")
81  {
82  skip_data_reason = "resolves behind '.'";
83  }
84  }
85 
86  // Search data if we don't have a reason not to
87  std::map<std::string, std::string> found;
88  if (!skip_data_reason)
89  for (const auto & [name, data_path] : data_paths)
90  {
91  // Explicit search, name doesn't match requested name
92  if (data_name && name != *data_name) // explicit search
93  continue;
94  const auto file_path = MooseUtils::pathjoin(data_path, path);
95  if (MooseUtils::checkFileReadable(file_path, false, false, false))
96  found.emplace(name, MooseUtils::canonicalPath(file_path));
97  else
98  not_found.emplace(name + " data", data_path);
99  }
100 
101  // Found exactly one
102  if (found.size() == 1)
103  {
104  const auto & [name, data_path] = *found.begin();
105  return {MooseUtils::canonicalPath(data_path), Context::DATA, name};
106  }
107 
108  std::stringstream oss;
109  // Found multiple
110  if (found.size() > 1)
111  {
112  oss << "Multiple files were found when searching for the data file '" << path << "':\n\n";
113  for (const auto & [name, data_path] : found)
114  oss << " " << name << ": " << data_path << "\n";
115  const auto & first_name = found.begin()->first;
116  oss << "\nYou can resolve this ambiguity by appending a prefix with the desired data name, for "
117  "example:\n\n "
118  << first_name << ":" << path;
119  }
120  // Found none
121  else
122  {
123  oss << "Unable to find the data file '" << path << "' anywhere.\n";
124  if (not_found.size())
125  {
126  oss << "\nPaths searched:\n";
127  for (const auto & [name, data_path] : not_found)
128  oss << " " << name << ": " << data_path << "\n";
129  }
130  if (skip_data_reason)
131  oss << "\nData path(s) were not searched because search path " << *skip_data_reason << ".\n";
132  }
133 
134  mooseError(oss.str());
135 }
std::string name(const ElemQuality q)
static Registry & getRegistry()
Get the global Registry singleton.
Definition: Registry.C:23
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
std::string canonicalPath(const std::string &path)
Gets the canonical path of the given path.
Definition: MooseUtils.C:1266
bool checkFileReadable(const std::string &filename, bool check_line_endings=false, bool throw_on_unreadable=true, bool check_for_git_lfs_pointer=true)
Checks to see if a file is readable (exists and permissions)
Definition: MooseUtils.C:250
std::filesystem::path pathjoin(const std::filesystem::path &p)
Definition: MooseUtils.C:59
static const std::map< std::string, std::string > & getDataFilePaths()
Returns a map of all registered data file paths (name -> path)
Definition: Registry.h:243

◆ 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 138 of file DataFileUtils.C.

141 {
142  return getPath(data_name + ":" + path, base);
143 }
Path getPath(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.
Definition: DataFileUtils.C:22