#!/bin/sh #------------------------------------------------------------------------------ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | # \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------- # | Copyright (C) 2011-2016 OpenFOAM Foundation #------------------------------------------------------------------------------ # 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_SITE (unset defaults to PROJECT/site) # # Note # This script must exist in the project 'bin' directory # # The '-show-api' and '-show-patch' options implement partial logic # from wmake/wmakeBuildInfo. # Make sure that any changes there are also reflected here. # #------------------------------------------------------------------------------- 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="$(\cd $(dirname $binDir) && \pwd -L)" # Project dir userDir="$HOME/.OpenFOAM" # As per foamVersion.H groupDir="${WM_PROJECT_SITE:-$projectDir/site}" # As per foamVersion.H #------------------------------------------------------------------------------- # The API locations. See wmake/wmakeBuildInfo rulesFile="$projectDir/wmake/rules/General/general" metaInfoDir="$projectDir/META-INFO" # Get api from rules/General/general # # Failure modes: # - No api information (can't find file etc). # -> Fatal for building, but could be OK for a stripped down version # # Fallback. Get from api-info # getApi() { local value value="$(sed -ne '/^ *#/!{ /WM_VERSION.*OPENFOAM=/{ s@^.*OPENFOAM= *\([0-9][0-9]*\).*@\1@p; q }}' $rulesFile 2>/dev/null)" if [ -z "$value" ] && [ -f "$metaInfoDir/api-info" ] then # Fallback. Get from api-info value="$(sed -ne 's@^ *api *= *\([0-9][0-9]*\).*@\1@p' $metaInfoDir/api-info 2>/dev/null)" fi if [ -n "$value" ] then echo "$value" else return 1 fi } # Get patch from meta-info / api-info # # Failure modes: # - No patch information (can't find file etc). # getPatchLevel() { local value # Fallback. Get from api-info value="$(sed -ne 's@^ *patch *= *\([0-9][0-9]*\).*@\1@p' $metaInfoDir/api-info 2>/dev/null)" if [ -n "$value" ] then echo "$value" else return 1 fi } #------------------------------------------------------------------------------- optMode=ugo # Default mode is always 'ugo' unset shellOutput verboseOutput unset optAll optConfig optList projectApi # Parse options while [ "$#" -gt 0 ] do case "$1" in -h | -help*) printHelp ;; -show-api) # Show API and exit getApi exit $? ;; -show-patch) # Show patch level and exit getPatchLevel exit $? ;; -with-api=*) projectApi="${1#*=}" ;; -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=[ugoa]*) optMode="${1#*=}" ;; -m | -mode) optMode="$2" shift # Sanity check. Handles missing argument too. case "$optMode" in ([ugoa]*) ;; (*) die "invalid mode '$optMode'" ;; esac ;; -q | -quiet) optQuiet=true ;; -s | -silent) optSilent=true ;; -prefix=* | -version=*) echo "ignored defunct option '${1%%=*}'" 1>&2 ;; -p | -prefix | -v | -version) # Ignored, but still need to check/discard its argument [ "$#" -ge 2 ] || die "'$1' option requires an argument" echo "ignored defunct option '$1'" 1>&2 shift ;; --) shift break ;; -*) die "unknown option: '$1'" ;; *) break ;; esac shift done #------------------------------------------------------------------------------- # Establish the API value [ -n "$projectApi" ] || projectApi=$(getApi) # 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 # Debugging: # echo "Installed locations:" 1>&2 # for i in projectDir # do # eval echo "$i=\$$i" 1>&2 # done # Define the various places to be searched: unset dirList case "$optMode" in (*[au]*) # (A)ll or (U)ser dirList="$dirList $userDir/$projectApi $userDir" ;; esac case "$optMode" in (*[ag]*) # (A)ll or (G)roup == site dirList="$dirList $groupDir/$projectApi/etc $groupDir/etc" ;; esac case "$optMode" in (*[ao]*) # (A)ll or (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 #------------------------------------------------------------------------------