Commit 172c36c2 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: support search modes for etcFiles()

- similar to the foamEtcFile script -mode=... option, the specific
  search location (user/group/other) can now also specified for
  string expansions and as a numerical value for etcFile()

  For example, if searching for group or other (project) controlDict,
  but not wishing to see the user controlDict:

    1.  foamEtcFile -mode=go controlDict

    2.  fileName dictFile("<etc:go>/controlDict");
        dictFile.expand();

    3.  etcFile(controlDict, false, 0077);

  The default behaviour for searching all contexts is unchanged.

    1.  foamEtcFile controlDict

    2.  fileName dictFile("<etc>/controlDict");
        dictFile.expand();

    3.  etcFile(controlDict);
parent 67140f6b
......@@ -102,6 +102,12 @@ int main(int argc, char *argv[])
}
}
// This should and will fail:
//// Info<<"find bad file:" << nl
//// << findEtcFile("##BadName##", true) << "FAIL" << endl;
const bool listAll = (args.found("all") || args.found("list"));
int error = 0;
......
......@@ -102,6 +102,13 @@ int main(int argc, char *argv[])
:
{
"~OpenFOAM/controlDict", "<etc>/controlDict",
"<etc:ugo>/controlDict",
"<etc:u>/controlDict",
"<etc:ug>/controlDict",
"<etc:go>/controlDict",
"<etc:o>/controlDict",
"<etc:JUNK>/controlDict", // rubbish input
"<etc:>/controlDict", // rubbish input
"$FOAM_CASE/xyz", "<case>/xyz",
"$FOAM_CASE/constant/xyz", "<constant>/xyz",
"$FOAM_CASE/system/xyz", "<system>/xyz",
......
......@@ -240,12 +240,13 @@ int main(int argc, char *argv[])
fileName baseDir
(
"${WM_PROJECT_DIR}/etc/caseDicts/createZeroDirectoryTemplates"
args.opt<fileName>
(
"templateDir",
// Default is from PROJECT/etc directory
"<etc:o>/caseDicts/createZeroDirectoryTemplates"
)
);
if (args.found("templateDir"))
{
baseDir = args["templateDir"];
}
baseDir.expand();
baseDir.toAbsolute();
......
......@@ -30,12 +30,32 @@ License
// * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * * //
//
// These could be exposed too (if required), but are fairly special purpose.
// Some of these could be exposed too (if required),
// but are fairly special purpose.
//
namespace
{
// Return the file location mode as a string.
//
// - u : location mask 0700
// - g : location mask 0070
// - o : location mask 0007
//
static inline std::string locationToString(unsigned short location)
{
std::string mode;
if (location & 0700) { mode += 'u'; } // User
if (location & 0070) { mode += 'g'; } // Group
if (location & 0007) { mode += 'o'; } // Other
if (mode.empty()) { mode = "???"; }
return mode;
}
// Assign 'queried' parameter to the user resource directory.
// Return true if this directory exists.
//
......@@ -64,6 +84,7 @@ static inline bool userResourceDir(Foam::fileName& queried)
// Assign 'queried' parameter to the group resource directory.
// Return true if this directory exists.
// Otherwise clears the parameter and returns false.
//
// Corresponds to foamEtcFile -mode=g
// Looks for
......@@ -102,6 +123,7 @@ static inline bool groupResourceDir(Foam::fileName& queried)
// Assign 'queried' parameter to the OpenFOAM etc/ resource directory.
// Return true if it exists.
// Otherwise clears the parameter and returns false.
//
// Corresponds to foamEtcFile -mode=o
// Looks for
......@@ -122,6 +144,7 @@ static inline bool projectResourceDir(Foam::fileName& queried)
Foam::fileNameList searchEtc
(
const Foam::fileName& name,
unsigned short location,
const bool findFirst,
bool (*accept)(const Foam::fileName&)
)
......@@ -131,13 +154,23 @@ Foam::fileNameList searchEtc
const Foam::fileName version(std::to_string(Foam::foamVersion::api));
Foam::fileNameList list;
Foam::fileName dir, candidate;
Foam::fileName queried, candidate;
if (!(location & 0777))
{
// Warn about bad location (mode) ... or make it FATAL?
std::cerr
<< "--> FOAM Error :\n "
"No user/group/other location specified for 'etc' file"
" or directory\n '"
<< name.c_str() << "'\n\n" << std::endl;
}
// User resource directories
if (userResourceDir(dir))
if ((location & 0700) && userResourceDir(queried))
{
candidate = dir/version/name;
candidate = queried/version/name;
if (accept(candidate))
{
list.append(std::move(candidate));
......@@ -147,7 +180,7 @@ Foam::fileNameList searchEtc
}
}
candidate = dir/name;
candidate = queried/name;
if (accept(candidate))
{
list.append(std::move(candidate));
......@@ -159,9 +192,9 @@ Foam::fileNameList searchEtc
}
// Group (site) resource directories
if (groupResourceDir(dir))
if ((location & 0070) && groupResourceDir(queried))
{
candidate = dir/version/name;
candidate = queried/version/name;
if (accept(candidate))
{
list.append(std::move(candidate));
......@@ -171,7 +204,7 @@ Foam::fileNameList searchEtc
}
}
candidate = dir/name;
candidate = queried/name;
if (accept(candidate))
{
list.append(std::move(candidate));
......@@ -183,9 +216,9 @@ Foam::fileNameList searchEtc
}
// Other (project) resource directory
if (projectResourceDir(dir))
if ((location & 0007) && projectResourceDir(queried))
{
candidate = dir/name;
candidate = queried/name;
if (accept(candidate))
{
list.append(std::move(candidate));
......@@ -207,27 +240,27 @@ Foam::fileNameList Foam::etcDirs(bool test)
const Foam::fileName version(std::to_string(Foam::foamVersion::api));
Foam::fileNameList list(5);
Foam::fileName dir;
Foam::fileName queried;
label nDirs = 0;
// User resource directories
if (userResourceDir(dir) || (!test && dir.size()))
if (userResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = dir/version;
list[nDirs++] = dir;
list[nDirs++] = queried/version;
list[nDirs++] = queried;
}
// Group (site) resource directories
if (groupResourceDir(dir) || (!test && dir.size()))
if (groupResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = dir/version;
list[nDirs++] = dir;
list[nDirs++] = queried/version;
list[nDirs++] = queried;
}
// Other (project) resource directory
if (projectResourceDir(dir) || (!test && dir.size()))
if (projectResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = dir;
list[nDirs++] = queried;
}
list.resize(nDirs);
......@@ -239,13 +272,15 @@ Foam::fileNameList Foam::etcDirs(bool test)
Foam::fileNameList Foam::findEtcDirs
(
const fileName& name,
const bool findFirst
const bool findFirst,
unsigned short location
)
{
return
searchEtc
(
name,
location,
findFirst,
[](const fileName& f){ return Foam::isDir(f); }
);
......@@ -256,7 +291,8 @@ Foam::fileNameList Foam::findEtcFiles
(
const fileName& name,
const bool mandatory,
const bool findFirst
const bool findFirst,
unsigned short location
)
{
fileNameList list;
......@@ -267,6 +303,7 @@ Foam::fileNameList Foam::findEtcFiles
list = searchEtc
(
name,
location,
findFirst,
[](const fileName& f){ return Foam::isFile(f); }
);
......@@ -274,11 +311,16 @@ Foam::fileNameList Foam::findEtcFiles
if (mandatory && list.empty())
{
// Abort if file is mandatory but not found
// Abort if file is mandatory but not found.
// Use a direct exit, since this could occur before anything is
// setup at all.
std::cerr
<< "--> FOAM FATAL ERROR in Foam::findEtcFiles()"
" : could not find mandatory file\n '"
<< name.c_str() << "'\n\n" << std::endl;
<< "--> FOAM FATAL ERROR :\n "
"Could not find mandatory etc file (mode="
<< locationToString(location) << ")\n '"
<< name.c_str() << "'\n"
<< std::endl;
::exit(1);
}
......@@ -286,16 +328,42 @@ Foam::fileNameList Foam::findEtcFiles
}
Foam::fileName Foam::findEtcFile(const fileName& name, const bool mandatory)
Foam::fileName Foam::findEtcDir
(
const fileName& name,
unsigned short location
)
{
fileNameList list(findEtcFiles(name, mandatory, true));
fileNameList list(findEtcDirs(name, true, location));
fileName found;
if (list.size())
{
found = std::move(list.first());
}
return found;
}
Foam::fileName Foam::findEtcFile
(
const fileName& name,
const bool mandatory,
unsigned short location
)
{
fileNameList list(findEtcFiles(name, mandatory, true, location));
fileName found;
if (list.size())
{
return list.first();
found = std::move(list.first());
}
return fileName();
return found;
}
......
......@@ -60,25 +60,38 @@ fileNameList etcDirs(bool test=true);
fileNameList findEtcDirs
(
const fileName& name, //!< The directory to search for
const bool findFirst=false //!< Stop after locating the first directory
const bool findFirst=false, //!< Stop after locating the first directory
unsigned short location=0777 //!< User/group/other location
);
//- Search for a single directory using findEtcDirs().
//
// \return The full path name of the first directory found in the
// search hierarchy or an empty fileName if the name cannot be found.
fileName findEtcDir
(
const fileName& name, //!< The directory to search for
unsigned short location=0777 //!< User/group/other location
);
//- Search for files from user/group/other directories.
//
// The search hierarchy corresponds to that of the foamEtcFile script,
// which allows for version-specific and version-independent files:
// -# \b user settings
// The search hierarchy corresponds to that of the \c foamEtcFile script,
// which allows for version-specific and version-independent files.
//
// -# \b user settings (\c location=0700)
// - ~/.OpenFOAM/{PROJECT_API}
// - ~/.OpenFOAM/
// -# \b group settings
// -# \b group settings (\c location=0070)
// - $WM_PROJECT_SITE/{PROJECT_API}/etc/
// - $WM_PROJECT_SITE/etc/
// -# \b other (shipped) settings
// -# \b other (shipped) settings (\c location=0007)
// - $WM_PROJECT_DIR/etc/
//
// Where {PROJECT_API} is the value of the OPENFOAM define.
// - \b \$WM_PROJECT_SITE : If unset, uses $WM_PROJECT_DIR/site
// Where {PROJECT_API} corresponds to the foamVersion::api value.
//
// \note When \c \$WM_PROJECT_SITE is unset, uses \c $WM_PROJECT_DIR/site
//
// \return The list of full paths of all the matching files or
// an empty list if the name cannot be found.
......@@ -86,7 +99,8 @@ fileNameList findEtcFiles
(
const fileName& name, //!< The file to search for
const bool mandatory=false, //!< Abort if the file cannot be found
const bool findFirst=false //!< Stop after locating the first directory
const bool findFirst=false, //!< Stop after locating the first directory
unsigned short location=0777 //!< User/group/other location
);
......@@ -97,7 +111,8 @@ fileNameList findEtcFiles
fileName findEtcFile
(
const fileName& name, //!< The file to search for
const bool mandatory=false //!< Abort if the file cannot be found
const bool mandatory=false, //!< Abort if the file cannot be found
unsigned short location=0777 //!< User/group/other location
);
......
......@@ -37,10 +37,33 @@ License
namespace Foam
{
// Return the file location mode (string) as a numerical value.
//
// - u : location mask 0700
// - g : location mask 0070
// - o : location mask 0007
//
static inline unsigned short modeToLocation
(
const std::string& mode,
std::size_t pos = 0
)
{
unsigned short where(0);
if (std::string::npos != mode.find('u', pos)) { where |= 0700; } // User
if (std::string::npos != mode.find('g', pos)) { where |= 0070; } // Group
if (std::string::npos != mode.find('o', pos)) { where |= 0007; } // Other
return where;
}
// Expand a leading <tag>/
// Convenient for frequently used directories
//
// <etc>/ => user/group/other OpenFOAM directory
// <etc>/ => user/group/other etc - findEtcFile()
// <etc(:[ugo]+)?>/ => user/group/other etc - findEtcFile()
// <case>/ => FOAM_CASE directory
// <constant>/ => FOAM_CASE/constant directory
// <system>/ => FOAM_CASE/system directory
......@@ -52,7 +75,7 @@ static void expandLeadingTag(std::string& s, const char b, const char e)
}
auto delim = s.find(e);
if (delim == std::string::npos)
if (std::string::npos == delim)
{
return; // Error: no closing delim - ignore expansion
}
......@@ -73,6 +96,7 @@ static void expandLeadingTag(std::string& s, const char b, const char e)
}
const std::string tag(s, 1, delim-2);
const auto tagLen = tag.length();
// Note that file is also allowed to be an empty string.
......@@ -88,6 +112,12 @@ static void expandLeadingTag(std::string& s, const char b, const char e)
{
s = fileName(Foam::getEnv("FOAM_CASE"))/tag/file;
}
else if (tagLen >= 4 && tag.compare(0, 4, "etc:") == 0)
{
// <etc:ugo> type of tag - convert "ugo" to numeric
s = findEtcFile(file, false, modeToLocation(tag, 4));
}
}
......
......@@ -219,30 +219,45 @@ namespace stringOps
// -# environment variables
// - "$VAR", "${VAR}"
// -# current directory
// - leading "./" : the current directory
// - leading "./"
// : the current directory - Foam::cwd()
// -# leading tag expansion for commonly used directories
// - \<etc\>/ : user/group/other OpenFOAM directory
// - \<case\>/ : FOAM_CASE directory
// - \<constant\>/ : FOAM_CASE/constant directory
// - \<system\>/ : FOAM_CASE/system directory
// - <b> \<etc\>/ </b>
// : user/group/other OpenFOAM etc directory
// - <b> \<etc:</b><em>[ugo]+</em>)<b>\>/ </b>
// : user/group/other etc with specified location mode
// - <b> \<case\>/ </b>
// : The \c $FOAM_CASE directory
// - <b> \<constant\>/ </b>
// : The \c $FOAM_CASE/constant directory
// - <b> \<system\>/ </b>
// : The \c $FOAM_CASE/system directory
// -# tilde expansion
// - leading "~/" : home directory
// - leading "~user" : home directory for specified user
//
// Supports default and alternative values as per the POSIX shell.
// \code
// a) "${parameter:-defValue}"
// b) "${parameter:+altValue}"
// 1. "${parameter:-defValue}"
// 2. "${parameter:+altValue}"
// \endcode
// a) If parameter is unset or null, the \c defValue is substituted.
// Otherwise, the value of parameter is substituted.
//
// b) If parameter is unset or null, nothing is substituted.
// Otherwise the \c altValue is substituted.
// -# If parameter is unset or null, the \c defValue is substituted.
// Otherwise, the value of parameter is substituted.
// -# If parameter is unset or null, nothing is substituted.
// Otherwise the \c altValue is substituted.
// .
//
// General behavior:
// - Any unknown entries are removed silently, if allowEmpty is true.
// - Malformed entries (eg, brace mismatch, sigil followed by bad chars)
// are left as is.
// are left as is.
//
// An example of using the specified location mode
// \code
// fileName controlDict(stringOps::expand("<etc:o>/controlDict"));
// // OR
// fileName controlDict(findEtcFile("controlDict", false, 0007));
// \endcode
//
// \note Deprecated(2018-11) Use "<etc>" instead of the rarely used
// "~OpenFOAM" expansion
......@@ -263,28 +278,35 @@ namespace stringOps
// -# current directory
// - leading "./" : the current directory
// -# leading tag expansion for commonly used directories
// - \<etc\>/ : user/group/other OpenFOAM directory
// - \<case\>/ : FOAM_CASE directory
// - \<constant\>/ : FOAM_CASE/constant directory
// - \<system\>/ : FOAM_CASE/system directory
// - <b> \<etc\>/ </b>
// : user/group/other OpenFOAM etc directory
// - <b> \<etc:</b><em>[ugo]+</em>)<b>\>/ </b>
// : user/group/other etc with specified location mode
// - <b> \<case\>/ </b>
// : The \c $FOAM_CASE directory
// - <b> \<constant\>/ </b>
// : The \c $FOAM_CASE/constant directory
// - <b> \<system\>/ </b>
// : The \c $FOAM_CASE/system directory
// -# tilde expansion
// - leading "~/" : home directory
// - leading "~user" : home directory for specified user
//
// Supports default and alternative values as per the POSIX shell.
// \code
// a) "${parameter:-defValue}"
// b) "${parameter:+altValue}"
// 1. "${parameter:-defValue}"
// 2. "${parameter:+altValue}"
// \endcode
// a) If parameter is unset or null, the \c defValue is substituted.
// Otherwise, the value of parameter is substituted.
//
// b) If parameter is unset or null, nothing is substituted.
// Otherwise the \c altValue is substituted.
// -# If parameter is unset or null, the \c defValue is substituted.
// Otherwise, the value of parameter is substituted.
// -# If parameter is unset or null, nothing is substituted.
// Otherwise the \c altValue is substituted.
// .
//
// General behavior:
// - Any unknown entries are removed silently if allowEmpty is true.
// - Malformed entries (eg, brace mismatch, sigil followed by bad chars)
// are left as is.
// are left as is.
//
// \note Deprecated(2018-11) Use "<etc>" instead of the rarely used
// "~OpenFOAM" expansion
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment