Commit 2db0db30 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

BUG: stringOps etc expansion fails for directories (issue #1121)

- now use findEtcEntry() instead to handle file or directory.

  Added findEtcEntries(), which provides provides a common code basis
  for findEtcDirs(), findEtcFiles() ...
parent 3d95f565
......@@ -217,7 +217,7 @@ int main(int argc, char *argv[])
argList::addOption
(
"templateDir",
"file",
"dir",
"Read case set-up templates from specified location"
);
......@@ -238,25 +238,34 @@ int main(int argc, char *argv[])
)
);
// Template directory: default is from PROJECT/etc directory
//
// Can use
// - foamEtcDir("caseDicts/createZeroDirectory", 0007);
// - expand "<etc:o>/caseDicts/createZeroDirectory"
// - expand "${WM_PROJECT_DIR}/etc/caseDicts/createZeroDirectory"
//
// Use "${WM_PROJECT_DIR}/" version for nicer error message
fileName baseDir
(
args.opt<fileName>
(
"templateDir",
// Default is from PROJECT/etc directory
"<etc:o>/caseDicts/createZeroDirectoryTemplates"
"${WM_PROJECT_DIR}/etc/caseDicts/createZeroDirectoryTemplates"
)
);
baseDir.expand();
baseDir.toAbsolute();
if (!isDir(baseDir))
if (!Foam::isDir(baseDir))
{
FatalErrorInFunction
<< "templateDir " << baseDir
<< " should point to the folder containing the "
<< "case set-up templates" << exit(FatalError);
<< "templateDir " << baseDir << nl
<< "Does not point to a folder containing case set-up templates"
<< nl
<< exit(FatalError);
}
// Keep variable substitutions - delay until after creation of controlDict
......
......@@ -205,7 +205,7 @@ do
-config)
optConfig=true
;;
-mode=[ugo]*)
-mode=[ugoa]*)
optMode="${1#*=}"
;;
-m | -mode)
......@@ -213,7 +213,7 @@ do
shift
# Sanity check. Handles missing argument too.
case "$optMode" in
([ugo]*)
([ugoa]*)
;;
(*)
die "invalid mode '$optMode'"
......@@ -290,17 +290,17 @@ fi
# Define the various places to be searched:
unset dirList
case "$optMode" in (*u*) # (U)ser
case "$optMode" in (*[au]*) # (A)ll or (U)ser
dirList="$dirList $userDir/$projectApi $userDir"
;;
esac
case "$optMode" in (*g*) # (G)roup == site
case "$optMode" in (*[ag]*) # (A)ll or (G)roup == site
dirList="$dirList $groupDir/$projectApi/etc $groupDir/etc"
;;
esac
case "$optMode" in (*o*) # (O)ther == shipped
case "$optMode" in (*[ao]*) # (A)ll or (O)ther == shipped
dirList="$dirList $projectDir/etc"
;;
esac
......
......@@ -203,7 +203,7 @@ public:
// - $WM_PROJECT_DIR/etc/"caseDicts/postProcessing"
//
// Where {PROJECT_API} is the value of the OPENFOAM define.
// See further notes in Foam::findEtcFiles()
// See further notes in Foam::findEtcEntries()
static void list();
//- Find a functionObject dictionary file in the case
......
......@@ -42,7 +42,6 @@ namespace
// - u : location mask 0700
// - g : location mask 0070
// - o : location mask 0007
//
static inline std::string locationToString(unsigned short location)
{
std::string mode;
......@@ -56,6 +55,27 @@ static inline std::string locationToString(unsigned short location)
}
// Error handling when a mandatory entry is not found
static inline void errorMandatoryNotFound
(
const std::string& name,
unsigned short location
)
{
// Abort when mandatory entry was not found.
// Use a direct exit, since this could occur before anything is
// setup at all.
std::cerr
<< "--> FOAM FATAL ERROR :\n "
"Could not find mandatory etc entry (mode="
<< locationToString(location) << ")\n '"
<< name << "'\n"
<< std::endl;
::exit(1);
}
// Assign 'queried' parameter to the user resource directory.
// Return true if this directory exists.
//
......@@ -141,20 +161,87 @@ static inline bool projectResourceDir(Foam::fileName& queried)
}
Foam::fileNameList searchEtc
// Check if the named file/directory matches the type required.
//
// - typeRequired (UNDEFINED) => accept either FILE or DIRECTORY
// - typeRequired (FILE | DIRECTORY) => accept only that type
static inline bool accept
(
const Foam::fileName& name,
unsigned short location,
const bool findFirst,
bool (*accept)(const Foam::fileName&)
const Foam::fileName::Type typeRequired
)
{
// followLink(true), checkGzip(true)
// -> returns (UNDEFINED | FILE | DIRECTORY), no need to check for (LINK)
const auto t = name.type(true, true);
return
(
// Found something?
Foam::fileName::Type::UNDEFINED != t
&&
(
// Any particular type required?
Foam::fileName::Type::UNDEFINED == typeRequired
? (Foam::fileName::Type::UNDEFINED != t)
: (typeRequired == t)
)
);
}
} // End anonymous namespace
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::fileNameList Foam::etcDirs(bool test)
{
// Use foamVersion::api (instead of the OPENFOAM define) to ensure this
// stays properly synchronized with the build information
const Foam::fileName version(std::to_string(Foam::foamVersion::api));
Foam::fileNameList list;
Foam::fileName queried, candidate;
Foam::fileNameList list(5);
Foam::fileName queried;
label nDirs = 0;
// User resource directories
if (userResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = queried/version;
list[nDirs++] = queried;
}
// Group (site) resource directories
if (groupResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = queried/version;
list[nDirs++] = queried;
}
// Other (project) resource directory
if (projectResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = queried;
}
list.resize(nDirs);
return list;
}
Foam::fileNameList Foam::findEtcEntries
(
const Foam::fileName& name,
unsigned short location,
const Foam::fileName::Type typeRequired,
const bool findFirst
)
{
// Debug Tracing
// std::cerr
// << "search ("<< locationToString(location) << "): "
// << name.c_str() << '\n';
if (!(location & 0777))
{
......@@ -166,12 +253,25 @@ Foam::fileNameList searchEtc
<< name.c_str() << "'\n\n" << std::endl;
}
// Use foamVersion::api (instead of the OPENFOAM define) to ensure this
// stays properly synchronized with the build information
const Foam::fileName version(std::to_string(Foam::foamVersion::api));
Foam::fileNameList list;
Foam::fileName queried, candidate;
if (fileName::Type::FILE == typeRequired && name.empty())
{
// FILE must have a name to be found!
return list;
}
// User resource directories
if ((location & 0700) && userResourceDir(queried))
{
candidate = queried/version/name;
if (accept(candidate))
if (accept(candidate, typeRequired))
{
list.append(std::move(candidate));
if (findFirst)
......@@ -181,7 +281,7 @@ Foam::fileNameList searchEtc
}
candidate = queried/name;
if (accept(candidate))
if (accept(candidate, typeRequired))
{
list.append(std::move(candidate));
if (findFirst)
......@@ -191,11 +291,12 @@ Foam::fileNameList searchEtc
}
}
// Group (site) resource directories
if ((location & 0070) && groupResourceDir(queried))
{
candidate = queried/version/name;
if (accept(candidate))
if (accept(candidate, typeRequired))
{
list.append(std::move(candidate));
if (findFirst)
......@@ -205,7 +306,7 @@ Foam::fileNameList searchEtc
}
candidate = queried/name;
if (accept(candidate))
if (accept(candidate, typeRequired))
{
list.append(std::move(candidate));
if (findFirst)
......@@ -215,11 +316,12 @@ Foam::fileNameList searchEtc
}
}
// Other (project) resource directory
if ((location & 0007) && projectResourceDir(queried))
{
candidate = queried/name;
if (accept(candidate))
if (accept(candidate, typeRequired))
{
list.append(std::move(candidate));
}
......@@ -228,62 +330,15 @@ Foam::fileNameList searchEtc
return list;
}
} // End anonymous namespace
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::fileNameList Foam::etcDirs(bool test)
{
// Use foamVersion::api (instead of the OPENFOAM define) to ensure this
// stays properly synchronized with the build information
const Foam::fileName version(std::to_string(Foam::foamVersion::api));
Foam::fileNameList list(5);
Foam::fileName queried;
label nDirs = 0;
// User resource directories
if (userResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = queried/version;
list[nDirs++] = queried;
}
// Group (site) resource directories
if (groupResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = queried/version;
list[nDirs++] = queried;
}
// Other (project) resource directory
if (projectResourceDir(queried) || (!test && queried.size()))
{
list[nDirs++] = queried;
}
list.resize(nDirs);
return list;
}
Foam::fileNameList Foam::findEtcDirs
(
const fileName& name,
const bool findFirst,
unsigned short location
unsigned short location,
const bool findFirst
)
{
return
searchEtc
(
name,
location,
findFirst,
[](const fileName& f){ return Foam::isDir(f); }
);
return findEtcEntries(name, location, fileName::Type::DIRECTORY, findFirst);
}
......@@ -291,50 +346,34 @@ Foam::fileNameList Foam::findEtcFiles
(
const fileName& name,
const bool mandatory,
const bool findFirst,
unsigned short location
unsigned short location,
const bool findFirst
)
{
fileNameList list;
if (name.size())
{
// A file must have a name!
list = searchEtc
(
name,
location,
findFirst,
[](const fileName& f){ return Foam::isFile(f); }
);
}
// Note: findEtcEntries checks name.size() for FILE
fileNameList list
(
findEtcEntries(name, location, fileName::Type::FILE, findFirst)
);
if (mandatory && list.empty())
{
// 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 :\n "
"Could not find mandatory etc file (mode="
<< locationToString(location) << ")\n '"
<< name.c_str() << "'\n"
<< std::endl;
::exit(1);
errorMandatoryNotFound(name, location);
}
return list;
}
Foam::fileName Foam::findEtcDir
Foam::fileName Foam::findEtcEntry
(
const fileName& name,
unsigned short location
unsigned short location,
const Foam::fileName::Type typeRequired
)
{
fileNameList list(findEtcDirs(name, true, location));
// With findFirst(true)
fileNameList list(findEtcEntries(name, location, typeRequired, true));
fileName found;
......@@ -347,6 +386,16 @@ Foam::fileName Foam::findEtcDir
}
Foam::fileName Foam::findEtcDir
(
const fileName& name,
unsigned short location
)
{
return findEtcEntry(name, location, fileName::Type::DIRECTORY);
}
Foam::fileName Foam::findEtcFile
(
const fileName& name,
......@@ -354,13 +403,11 @@ Foam::fileName Foam::findEtcFile
unsigned short location
)
{
fileNameList list(findEtcFiles(name, mandatory, true, location));
fileName found(findEtcEntry(name, location, fileName::Type::FILE));
fileName found;
if (list.size())
if (mandatory && found.empty())
{
found = std::move(list.first());
errorMandatoryNotFound(name, location);
}
return found;
......
......@@ -52,30 +52,7 @@ namespace Foam
fileNameList etcDirs(bool test=true);
//- Search for directories from user/group/other directories.
// Uses search hierarchy as per findEtcFiles().
//
// \return The list of full paths of all the matching directories or
// an empty list if the name cannot be found.
fileNameList findEtcDirs
(
const fileName& name, //!< The directory to search for
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.
//- Search for files or directories from user/group/other etc locations.
//
// The search hierarchy corresponds to that of the \c foamEtcFile script,
// which allows for version-specific and version-independent files.
......@@ -90,29 +67,120 @@ fileName findEtcDir
// - $WM_PROJECT_DIR/etc/
//
// Where {PROJECT_API} corresponds to the foamVersion::api value.
// When \c \$WM_PROJECT_SITE is unset, uses \c $WM_PROJECT_DIR/site
//
// \param name The entry to search for. For a FILE search,
// this should be non-empty. For a DIRECTORY search or a general
// (UNDEFINED) search, this can be an empty string.
// \param location The search locations as a numerical mode.
// The default (0777) searches user/group/other locations.
// \param typeRequired restricts the search to the specified type.
// The default (UNDEFINED) accepts FILE or DIRECTORY entries.
// \param findFirst Optionally stop after locating the first entry.
//
// \return The list of full paths of all the matching files or directories
// or an empty list if the name cannot be resolved.
fileNameList findEtcEntries
(
const fileName& name,
unsigned short location=0777,
const fileName::Type typeRequired = fileName::Type::UNDEFINED,
const bool findFirst=false
);
//- Search for directories from user/group/other etc locations.
// The search hierarchy corresponds to that of the \c foamEtcFile script,
// which allows for version-specific and version-independent files.
//
// This function corresponds to using Foam::findEtcEntries()
// with (DIRECTORY) for the type required.
//
// \param name The directory to search for. This can be an empty string.
// \param location The search locations as a numerical mode.
// The default (0777) searches user/group/other locations.
// \param findFirst Optionally stop after locating the first entry.
//
// \return The list of full paths of all the matching directories or
// an empty list if the name cannot be found.
fileNameList findEtcDirs
(
const fileName& name,
unsigned short location=0777,
const bool findFirst=false
);
//- Search for files from user/group/other etc locations.
// The search hierarchy corresponds to that of the \c foamEtcFile script,
// which allows for version-specific and version-independent files.
//
// This function corresponds to using Foam::findEtcEntries()
// with (FILE) for the type required, but has an additional
// check for mandatory files.
//
// \note When \c \$WM_PROJECT_SITE is unset, uses \c $WM_PROJECT_DIR/site
// \param name The file to search for. If this is an empty string,
// nothing will be matched.
// \param mandatory Abort if the mandatory file cannot be found.
// \param location The search locations as a numerical mode.
// The default (0777) searches user/group/other locations.
// \param findFirst Optionally stop after locating the first entry.
//
// \return The list of full paths of all the matching files or
// an empty list if the name cannot be found.
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
unsigned short location=0777 //!< User/group/other location
const fileName& name,
const bool mandatory=false,
unsigned short location=0777,
const bool findFirst=false
);
//- Search for a single FILE or DIRECTORY within the etc directories
//
// \param name The entry to search for. For a FILE search,
// this should be non-empty. For a DIRECTORY search or a general
// (UNDEFINED) search, this can be an empty string.
// \param location The search locations as a numerical mode.
// The default (0777) searches user/group/other locations.
// \param typeRequired restricts the search to the specified type.
// The default (UNDEFINED) accepts FILE or DIRECTORY entries.
//
// \return The full path name of the first entry found in the
// search hierarchy or an empty fileName if the name cannot be found.
//
// \sa Foam::findEtcEntries()
fileName findEtcEntry
(
const fileName& name,
unsigned short location=0777,
const fileName::Type typeRequired = fileName::Type::UNDEFINED
);
//- Search for a single file using findEtcFiles().
//- Search for a single FILE within the etc directories
//
// \return The full path name of the first directory found in the
// search hierarchy or an empty fileName if the name cannot be found.
//
// \sa Foam::findEtcEntries(), Foam::findEtcDirs()
fileName findEtcDir
(
const fileName& name, //!< The directory to search for
unsigned short location=0777 //!< User/group/other location
);
//- Search for a single FILE within the etc directories
//
// \return The full path name of the first file found in the
// search hierarchy or an empty fileName if the name cannot be found.
//
// \sa Foam::findEtcEntries(), Foam::findEtcFiles()
fileName findEtcFile
(
const fileName& name, //!< The file to search for
const bool mandatory=false, //!< Abort if the file cannot be found
unsigned short location=0777 //!< User/group/other location
const fileName& name, //!< The file to search for
const bool mandatory=false, //!< Abort if the file cannot be found
unsigned short location=0777 //!< User/group/other location