openfoam/wmake/scripts/wmake-build-info
Mark Olesen 2ba6243862 CONFIG: refine handling of git information for debian builds
- When OpenFOAM is under git control and a 'debian/' directory exists,
  this could mean two things:

  1) Additional debian control has been added to OpenFOAM
  2) OpenFOAM has been imported into a debian project

For the case that OpenFOAM has been imported into a debian project,
using the git information would be highly misleading. There will be no
OpenFOAM SHA1 correspondence.

However, if additional debian control has been added to OpenFOAM the
SHA1 will be valid.

The ad hoc solution is to use an additional "openfoam.debian"
directory to flag the addition of debian controls into openfoam.

When a "debian/" directory exists without a "openfoam.debian", assume
that the OpenFOAM has been imported into debian and do not use the SHA1.
2020-06-29 10:33:30 +02:00

635 lines
15 KiB
Bash
Executable File

#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration |
# \\ / A nd | www.openfoam.com
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2018-2020 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Script
# wmake/scripts/wmake-build-info
# Backend for "wmake -build-info"
#
# Description
# Print the api/version and other build information for the project.
#
# Environment
# - WM_PROJECT_DIR
# - WM_PROJECT_VERSION
# - WM_DIR (unset defaults to WM_PROJECT_DIR/wmake)
#
# Files
# - META-INFO/{api-info,build-info}
# - wmake/rules/General/general
# - debian : implicitly disables git queries
#
# Note
# There is a corner case when obtaining build information from git.
# It is possible that OpenFOAM has been imported into a debian form,
# in which case the '.git/' directory is most from debian and cannot
# be used to obtain an OpenFOAM sha1 value.
#
# Ad hoc logic (slightly messy):
# 1) Have an 'openfoam.debian/' directory.
# Assume that debian control has been added to OpenFOAM.
# Can use git to obtain build information.
# 2) Have a 'debian/' directory only.
# Assume OpenFOAM has been added into a debian project.
# Treat as '-no-git', which which has no effect
# when building from pristine sources.
#
# SeeAlso
# META-INFO/README.md for other routines that also use META-INFO.
#
#------------------------------------------------------------------------------
# Locations
rulesFile="${WM_DIR:-$WM_PROJECT_DIR/wmake}/rules/General/general"
META_INFO="$WM_PROJECT_DIR/META-INFO"
FOAM_GIT_DIR="$WM_PROJECT_DIR/.git"
printHelp() {
cat<<USAGE
Usage: ${0##*/} [OPTION]
${0##*/} [-update] -filter FILE
options:
-cmp, -check Compare make and meta information (exit 0 for no changes)
-diff Display differences between make and meta information
(exit code 0 for no changes)
-dry-run In combination with -update
-filter FILE Filter @API@, @BUILD@ tags in file with make information
-no-git Disable use of git for obtaining information
-remove Remove meta-info build information and exit
-update Update meta-info from make information
-query Report make-info and meta-info
-query-make Report make-info values (api, branch, build)
-query-meta Report meta-info values (api, branch, build)
-show-api Print api value from wmake/rules, or meta-info and exit
-show-patch Print patch value from meta-info and exit
-help Print the usage
Query/manage status of {api,branch,build} information.
Default without any arguments is the same as '-query-make'.
USAGE
exit 1
}
# Report error and exit
die()
{
exec 1>&2
echo
echo "Error encountered:"
while [ "$#" -ge 1 ]; do echo " $1"; shift; done
echo
echo "See '${0##*/} -help' for usage"
echo
exit 1
}
#------------------------------------------------------------------------------
# Parse arguments and options
#------------------------------------------------------------------------------
unset optCheck optDryRun optUpdate optQuery optFilter
while [ "$#" -gt 0 ]
do
case "$1" in
-h | -help*)
printHelp
;;
-cmp | -check)
optCheck=true
;;
-diff)
optCheck=verbose
;;
-dry-run)
optDryRun=true
;;
-remove)
optUpdate=remove
break # Stop now
;;
-update)
optUpdate=true
;;
-query)
optQuery="make:meta"
;;
-query-make | -query-meta)
optQuery="$optQuery:${1##*-}"
;;
-show-api)
optQuery="api"
;;
-show-patch)
optQuery="patch"
;;
-filter)
optFilter=true
shift # Stop here, a file name follows
break
;;
-no-git)
unset FOAM_GIT_DIR
;;
*)
die "Unknown option/argument: '$1'"
;;
esac
shift
done
# Check environment variables
[ -d "$WM_PROJECT_DIR" ] || \
die "Bad or unset environment variable: \$WM_PROJECT_DIR"
[ -d "$META_INFO" ] || \
die "No ${META_INFO##*/}/ directory for project"
# Debian handling (see notes above)
# - disable git queries if debian project and not internal "debianization"
if [ -d "$WM_PROJECT_DIR/debian" ] \
&& [ ! -e "$WM_PROJECT_DIR/openfoam.debian" ]
then
unset FOAM_GIT_DIR
fi
#------------------------------------------------------------------------------
if [ "$optUpdate" = remove ]
then
if [ -f "$META_INFO/build-info" ]
then
echo "Removing project ${META_INFO##*/}/build-info" 1>&2
rm -f "$META_INFO/build-info"
else
echo "Already removed project ${META_INFO##*/}/build-info" 1>&2
fi
exit 0
elif [ "$optFilter" = true ]
then
[ -f "$1" ] || {
echo "Error in ${0##*/}: file not found '$1'" 1>&2
exit 2
}
# Disable other methods that generate output to stdout
unset optCheck optQuery
else
[ "$#" -eq 0 ] || die "Unexpected option/arguments $*"
# Nothing specified? Default to -query-make
if [ -z "$optCheck$optUpdate$optQuery" ]
then
optQuery="make"
fi
fi
#------------------------------------------------------------------------------
# Variables - for portability, avoiding bash associative arrays
unset make_info meta_info
# Populate make_* variables
#
# - api : from rules/General/general
# - patch : cached value from previous make
# - branch : from git
# - build : from git
#
# Failure modes:
# - No api information (can't find file etc).
# -> FATAL: should never happen.
#
# - No git installed or no git repo
# -> branch and build are populated as empty strings
#
# - Working on detached head.
# -> branch has value "HEAD" instead of something more readable.
getMakeInfo()
{
if [ -n "$make_info" ]
then
##echo "use cached value for make info" 1>&2
return 0
fi
##echo "get make info" 1>&2
local api patch build branch
unset make_api make_patch make_branch make_build
# (api) from WM_DIR/rules/General/general
# - extract WM_VERSION = OPENFOAM=<digits>
api="$(sed -ne '/^ *#/!{ /WM_VERSION.*OPENFOAM=/{ s@^.*OPENFOAM= *\([0-9][0-9]*\).*@\1@p; q }}' "$rulesFile" 2>/dev/null)"
if [ -d "$META_INFO" ]
then
# (patch) from build-info - not from api-info
patch="$(sed -ne 's@^patch *= *\([0-9][0-9]*\).*@\1@p' "$META_INFO/build-info" 2>/dev/null)"
fi
# Build info from git. Use short date format (YYYY-MM-DD) and sed instead
# of the newer --date='format:%y%m%d'
if [ -d "$FOAM_GIT_DIR" ]
then
build="$(git --git-dir="$FOAM_GIT_DIR" log -1 --date=short --format='%h=%ad' 2>/dev/null|sed 's/-//g;s/=/-/')"
# Branch info from git
if [ -n "$build" ]
then
branch="$(git --git-dir="$FOAM_GIT_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null)"
fi
fi
make_api="$api"
make_patch="${patch:-0}" # Default is 0 (unpatched)
make_branch="$branch"
make_build="$build"
make_info=true
}
# Populate meta_* variables
#
# - api : from META-INFO/api-info
# - patch : from META-INFO/api-info
# - branch : from META-INFO/build-info
# - build : from META-INFO/build-info
#
# Failure modes:
# - Directory, file or entry not found.
# -> corresponding entries are empty strings
getMetaInfo()
{
if [ -n "$meta_info" ]
then
##echo "use cached value for meta info" 1>&2
return 0
fi
##echo "get meta info" 1>&2
local api patch build branch
unset meta_api meta_patch meta_branch meta_build
if [ -d "$META_INFO" ]
then
# (api, patch) from api-info
# (branch, build) from build-info
api="$(sed -ne 's@^api *= *\([0-9][0-9]*\).*@\1@p' "$META_INFO/api-info" 2>/dev/null)"
patch="$(sed -ne 's@^patch *= *\([0-9][0-9]*\).*@\1@p' "$META_INFO/api-info" 2>/dev/null)"
branch="$(sed -ne 's@^branch *= *\([^ ]*\).*@\1@p' "$META_INFO/build-info" 2>/dev/null)"
build="$(sed -ne 's@^build *= *\([^ ]*\).*@\1@p' "$META_INFO/build-info" 2>/dev/null)"
fi
meta_api="$api"
meta_patch="${patch:-0}" # Default is 0 (unpatched)
meta_branch="$branch"
meta_build="$build"
meta_info=true
}
# 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()
{
getMakeInfo
# Local copy
local api="${make_api}"
if [ -z "$api" ]
then
getMetaInfo
api="${meta_api}"
fi
if [ -n "$api" ]
then
echo "$api"
else
return 1
fi
}
# Get patch from meta-info / api-info
#
# Failure modes:
# - No patch information (can't find file etc).
getPatchLevel()
{
getMetaInfo
# Local copy
local patch="${meta_patch}"
if [ -n "$patch" ]
then
echo "$patch"
else
return 1
fi
}
#
# Report make info
#
reportMakeInfo()
{
getMakeInfo
getMetaInfo
echo "make"
echo " api = ${make_api}"
echo " patch = ${meta_patch:-0}" # <- From meta-info only
echo " branch = ${make_branch}"
echo " build = ${make_build}"
}
#
# Report meta info
#
reportMetaInfo()
{
getMetaInfo
echo "meta"
echo " api = ${meta_api}"
echo " patch = ${meta_patch:-0}" # <- From meta-info only
echo " branch = ${meta_branch}"
echo " build = ${meta_build}"
}
# Report diff between make and meta info (single key).
# Set diff_header prior to the first call.
# $1 == key
# $2 == make value
# $3 == meta value
unset diff_header
_reportDiff()
{
if [ -n "$diff_header" ]
then
echo "$diff_header"
unset diff_header
fi
echo "$1:"
echo " make $2"
echo " meta $3"
}
# Test make vs meta info.
# Return 0 for no differences, 1 otherwise
# $1 == verbose, print as diff. Silent otherwise
checkDiff()
{
local diff verbose
if [ "$1" = "verbose" ]
then
diff_header="Differences"
verbose=true
fi
getMakeInfo
getMetaInfo
# api
if [ "${make_api}" != "${meta_api}" ]
then
diff=true
if [ -n "$verbose" ]
then
_reportDiff "api" "${make_api}" "${meta_api}"
fi
fi
# patch
if [ "${make_patch}" != "${meta_patch}" ]
then
diff=true
if [ -n "$verbose" ]
then
_reportDiff "patch" "${make_patch}" "${meta_patch}"
fi
fi
# branch - only test when make info is non-empty
if [ -n "${make_branch}" ] && [ "${make_branch}" != "${meta_branch}" ]
then
diff=true
if [ -n "$verbose" ]
then
_reportDiff "branch" "${make_branch}" "${meta_branch}"
fi
fi
# build - only test when make info is non-empty
if [ -n "${make_build}" ] && [ "${make_build}" != "${meta_build}" ]
then
diff=true
if [ -n "$verbose" ]
then
_reportDiff "build" "${make_build}" "${meta_build}"
fi
fi
# No diffs, but never permit entirely empty values for build.
test -z "$diff" || test -z "${make_build}${meta_build}"
}
#
# Update meta info (on disk) based on the make info
#
performUpdate()
{
getMakeInfo
getMetaInfo
# Local copies of the make info
local api="${make_api}"
local branch="${make_branch}"
local build="${make_build}"
local patch="${make_patch}"
# If any of the make-info are empty (bad),
# use the meta-info to avoid spurious changes
[ -n "$api" ] || api="${meta_api}"
[ -n "$branch" ] || branch="${meta_branch}"
[ -n "$build" ] || build="${meta_build}"
# Fallback to WM_PROJECT_VERSION alone
[ -n "$build" ] || build="${WM_PROJECT_VERSION:-unknown}"
local outputFile
# build-info
outputFile="$META_INFO/build-info"
if [ "$branch" != "${meta_branch}" ] || \
[ "$build" != "${meta_build}" ] || \
[ "$patch" != "${meta_patch}" ]
then
patch="${meta_patch:-0}" # <- From meta-info only
if [ -n "$optDryRun" ]
then
echo "dry-run (update) ${outputFile##*/} branch=${branch}" 1>&2
echo "dry-run (update) ${outputFile##*/} build=${build}" 1>&2
echo "dry-run (update) ${outputFile##*/} patch=${patch}" 1>&2
else
echo "branch=${branch}" >| "$outputFile"
echo "build=${build}" >> "$outputFile"
echo "patch=${patch}" >> "$outputFile"
fi
fi
# api-info
outputFile="$META_INFO/api-info"
if [ "$api" != "${meta_api}" ]
then
patch="${meta_patch:-0}" # <- From meta-info only
if [ -n "$optDryRun" ]
then
echo "dry-run (update) ${outputFile##*/} api=${api}" 1>&2
echo "dry-run (update) ${outputFile##*/} patch=${patch}" 1>&2
else
echo "api=${api}" >| "$outputFile"
echo "patch=${patch}" >> "$outputFile"
fi
fi
return 0
}
#
# Update meta info (on disk) based on the make info
#
performFiltering()
{
local input="$1"
[ -f "$input" ] || {
echo "Error in ${0##*/}: file not found '$1'" 1>&2
exit 2
}
getMakeInfo
getMetaInfo
# Local copies of the make info
local api="${make_api}"
local branch="${make_branch}"
local build="${make_build}"
local patch="${meta_patch:-0}" # <- From meta-info only
# If any of the make-info are empty (bad),
# conjure up something from the meta-info
# api is not normally needed (available directly from -Ddefine)
# but we may wish to filter other types of files
if [ -z "$api" ]
then
api="${meta_api}"
api="${api:-0}" # integer value
fi
# branch/build could be missing for non-git
if [ -z "$branch" ]
then
branch="${meta_branch}"
branch="${branch:-unknown}"
fi
if [ -z "$build" ]
then
build="${meta_build}"
# Fallback to WM_PROJECT_VERSION
build="${build:-${WM_PROJECT_VERSION:-unknown}}"
fi
sed \
-e 's!@API@!'"${api}"'!g' \
-e 's!@PATCH@!'"${patch:-0}"'!g' \
-e 's!@BRANCH@!'"${branch}"'!g' \
-e 's!@BUILD@!'"${build}"'!g' \
-e 's!@VERSION@!'"${WM_PROJECT_VERSION}"'!g' \
"$input"
return 0
}
#------------------------------------------------------------------------------
# Dispatch
if [ -n "$optCheck" ]
then
checkDiff $optCheck
exit $?
elif [ "$optQuery" = api ]
then
# Show API and exit
getApi
exit $?
elif [ "$optQuery" = patch ]
then
# Show patch level and exit
getPatchLevel
exit $?
else
# Other queries
case "$optQuery" in (*make*) reportMakeInfo ;; esac
case "$optQuery" in (*meta*) reportMetaInfo ;; esac
fi
[ -n "$optUpdate" ] && performUpdate
if [ -n "$optFilter" ]
then
# Perform filter on file
performFiltering "$1"
fi
exit 0 # clean exit
#------------------------------------------------------------------------------