#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration |
# \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
# \\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
#-------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, licensed under GNU General Public License
# .
#
# Script
# foamEtcFile
#
# Description
# Locate user/group/other file as per '#includeEtc'.
#
# The -mode option is used within etc/{bashrc,cshrc} to ensure
# that system prefs are respected:
# \code
# eval $(foamEtcFile -sh -mode=o prefs.sh)
# eval $(foamEtcFile -sh -mode=ug prefs.sh)
# \endcode
#
# The -mode option can also be used when chaining settings.
# For example, in the user ~/.OpenFOAM//config.sh/compiler
# \code
# eval $(foamEtcFile -sh -mode=go config.sh/compiler)
# \endcode
#
# Environment
# - WM_PROJECT (unset defaults to OpenFOAM)
# - WM_PROJECT_VERSION (unset defaults to detect from path)
# - WM_PROJECT_SITE (unset defaults to PREFIX/site)
#
# Note
# This script must exist in one of these locations:
# - PREFIX/OpenFOAM-/bin
# - PREFIX/openfoam-/bin
# - PREFIX/openfoam/bin
#
#-------------------------------------------------------------------------------
printHelp() {
cat<&2
echo
echo "Error encountered:"
while [ "$#" -ge 1 ]; do echo " $1"; shift; done
echo
echo "See 'foamEtcFile -help' for usage"
echo
exit 1
}
#-------------------------------------------------------------------------------
binDir="${0%/*}" # The bin dir
projectDir="${binDir%/bin}" # The project dir
prefixDir="${projectDir%/*}" # The prefix dir (same as $WM_PROJECT_INST_DIR)
# Could not resolve projectDir, prefixDir? (eg, called as ./bin/foamEtcFile)
if [ "$prefixDir" = "$projectDir" ]
then
binDir="$(cd $binDir && pwd -L)"
projectDir="${binDir%/bin}"
prefixDir="${projectDir%/*}"
fi
projectDirName="${projectDir##*/}" # The project directory name
projectVersion="$WM_PROJECT_VERSION" # Empty? - will be treated later
userDir="$HOME/.OpenFOAM" # Hard-coded as per foamVersion.H
#-------------------------------------------------------------------------------
# Guess project version or simply get the stem part of the projectDirName.
# Handle standard naming conventions:
#
# * OpenFOAM-[-extra...]
# * openfoam-[-extra...]
# * openfoam
#
# - projectVersion: update unless already set
#
# Helper variables:
# - dirBase (for reassembling name) == projectDirName without the version
unset dirBase
guessVersion()
{
local version
case "$projectDirName" in
(OpenFOAM-* | openfoam-*)
# Dashed naming: OpenFOAM- or openfoam-
dirBase="${projectDirName%%-*}-"
version="${projectDirName#*-}"
version="${version%%*-}" # Extra safety, eg openfoam-version-packager
;;
(openfoam[0-9]*)
# Debian-style naming: openfoam
dirBase="openfoam"
version="${projectDirName#openfoam}"
;;
(*)
die "unknown/unsupported naming convention for '$projectDirName'"
;;
esac
# Set projectVersion if required
: ${projectVersion:=$version}
}
# Set projectVersion and update versionNum, projectDirName accordingly
setVersion()
{
projectVersion="$1"
# Need dirBase when reassembling projectDirName
[ -n "$dirBase" ] || guessVersion
projectDirName="$dirBase$projectVersion"
}
#-------------------------------------------------------------------------------
optMode=ugo # Default mode is always 'ugo'
unset shellOutput verboseOutput
unset optAll optConfig optList optVersion
# Parse options
while [ "$#" -gt 0 ]
do
case "$1" in
-h | -help*)
printHelp
;;
-a | -all)
optAll=true
unset shellOutput verboseOutput
;;
-l | -list)
optList=true
;;
-list-test)
optList='test'
;;
-csh | -sh)
shellOutput="${1#-}"
unset verboseOutput
;;
-csh-verbose | -sh-verbose)
shellOutput="${1#-}"
verboseOutput="source " # Report: "source FILE"
;;
-config)
optConfig=true
;;
-mode=[ugo]*)
optMode="${1#*=}"
;;
-prefix=/*)
prefixDir="${1#*=}"
prefixDir="${prefixDir%/}"
;;
-version=*)
optVersion="${1#*=}"
;;
-m | -mode)
optMode="$2"
shift
# Sanity check. Handles missing argument too.
case "$optMode" in
([ugo]*)
;;
(*)
die "invalid mode '$optMode'"
;;
esac
;;
-p | -prefix)
[ "$#" -ge 2 ] || die "'$1' option requires an argument"
prefixDir="${2%/}"
shift
;;
-q | -quiet)
optQuiet=true
;;
-s | -silent)
optSilent=true
;;
-v | -version)
[ "$#" -ge 2 ] || die "'$1' option requires an argument"
optVersion="$2"
shift
;;
--)
shift
break
;;
-*)
die "unknown option: '$1'"
;;
*)
break
;;
esac
shift
done
#-------------------------------------------------------------------------------
# Split arguments into filename (for searching) and trailing bits for shell eval
# Silently remove leading ~OpenFOAM/ (as per Foam::findEtcFile)
nArgs=$#
fileName="${1#~OpenFOAM/}"
unset evalArgs
if [ "$nArgs" -eq 1 ]
then
if [ "$1" = "--" ]
then
nArgs=0
unset fileName
fi
elif [ "$nArgs" -ge 2 ]
then
if [ "$2" = "--" ]
then
nArgs=1
shift 2
evalArgs="$@"
fi
fi
# Get version information
if [ -n "$optVersion" ]
then
setVersion $optVersion
elif [ -z "$projectVersion" ]
then
guessVersion
fi
# Updates:
# - projectDir for changes via -prefix or -version
# - groupDir for changes via -prefix
projectDir="$prefixDir/$projectDirName"
groupDir="${WM_PROJECT_SITE:-$prefixDir/site}"
# Debugging:
# echo "Installed locations:" 1>&2
# for i in projectDir prefixDir projectDirName projectVersion
# do
# eval echo "$i=\$$i" 1>&2
# done
# Define the various places to be searched:
unset dirList
case "$optMode" in (*u*) # (U)ser
dirList="$dirList $userDir/$projectVersion $userDir"
;;
esac
case "$optMode" in (*g*) # (G)roup == site
dirList="$dirList $groupDir/$projectVersion $groupDir"
;;
esac
case "$optMode" in (*o*) # (O)ther == shipped
dirList="$dirList $projectDir/etc"
;;
esac
set -- $dirList
[ "$#" -ge 1 ] || die "No directories to scan. Programming error?"
exitCode=2 # Fallback is a FileNotFound error
#
# Preliminaries
#
# Special handling of config.sh/ , config.csh/ directories
if [ -n "$optConfig" -a -n "$shellOutput" -a -n "$fileName" ]
then
case "$shellOutput" in
csh*)
optConfig="config.csh/"
;;
sh*)
optConfig="config.sh/"
;;
*)
unset optConfig
;;
esac
if [ -n "$optConfig" ]
then
case "$fileName" in
/* | config.csh* | config.sh*)
# Does not need or cannot add a prefix
unset optConfig
;;
*)
fileName="$optConfig$fileName"
;;
esac
fi
fi
#
# The main routine
#
if [ -n "$optList" ]
then
# List directories, or potential file locations
[ "$nArgs" -le 1 ] || \
die "-list options expect 0 or 1 filename, but $nArgs provided"
# A silly combination, but -quiet has absolute precedence
[ -n "$optQuiet" ] && exit 0
# Test for directory or file too?
if [ "$optList" = "test" ]
then
if [ "$nArgs" -eq 1 ]
then
for dir
do
resolved="$dir/$fileName"
if [ -f "$resolved" ]
then
echo "$resolved"
exitCode=0 # OK
fi
done
else
for dir
do
if [ -d "$dir" ]
then
echo "$dir"
exitCode=0 # OK
fi
done
fi
else
exitCode=0 # OK, already verified that $# != 0
for dir
do
echo "$dir${fileName:+/}$fileName"
done
fi
else
[ "$nArgs" -eq 1 ] || die "One filename expected - $nArgs provided"
# Output for sourcing files ("source" for csh, "." for POSIX shell)
# Only allow sourcing a single file (disallow combination with -all)
case "$shellOutput" in
csh*)
shellOutput="source " # eg, "source FILE"
;;
sh*)
shellOutput=". " # eg, ". FILE"
;;
esac
# Anti-pattern: -all disables shell commands
if [ -n "$optAll" ]
then
unset shellOutput verboseOutput
fi
for dir
do
resolved="$dir/$fileName"
if [ -f "$resolved" ]
then
exitCode=0 # OK
if [ -n "$optQuiet" ]
then
break
elif [ -n "$verboseOutput" ]
then
echo "$verboseOutput$resolved" 1>&2
fi
if [ -n "$shellOutput" ]
then
echo "$shellOutput$resolved $evalArgs"
else
echo "$resolved"
fi
[ -n "$optAll" ] || break
fi
done
fi
exit $exitCode
#------------------------------------------------------------------------------