eole-gitea/scripts/skelton

222 lines
6.7 KiB
Bash
Executable File

#!/bin/sh
#------------------------------------------------------------------------
# ${SELF} (${SELF_VERSION}) - Display a message on standard output
# Copyright © 2014 Pôle de compétences EOLE <eole@ac-dijon.fr>
#
# License CeCILL:
# * in french: http://www.cecill.info/licences/Licence_CeCILL_V2-fr.html
# * in english http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
#------------------------------------------------------------------------
# Changes:
# 0.0.4 Add log utilities with a dedicated developper documentation
# 0.0.3 Add “--sources” option to write “${SELF}” code on standard output
# 0.0.2 Take care of DEBUG=yes environment variable
# 0.0.1 Initial release
#------------------------------------------------------------------------
# Usage: ${SELF} [--message <TEXT> | <OPTION>]
#
# Display a message on standard output.
#
# Options:
# --------
#
# -m, --message <TEXT> Display <TEXT> on standard output.
# Default: “${MESSAGE}"
# -d, --debug Enable debug messages
# -h, --help Show this message
# -v, --version Display version and copyright information
# -c, --copyright Display copyright information
# -l, --licence Display licence information
# --changes Display ChangeLog information
# -s, --sources Output software sources on standard output.
#
# Mandatory dependencies:
# -----------------------
# * “sh” like shell
# * “echo” with “-e” option
# * perl
#
# Optional dependencies:
# ----------------------
# None
#
# Bugs:
# ----
# Report bug to Équipe EOLE <eole@ac-dijon.fr>
# bugtracker: http://dev-eole.ac-dijon.fr/projects/<EOLE-SKELETOR>/issues
#------------------------------------------------------------------------
# Debug, first thing to do if something goes wrong, even in utilities
#
# “${DEBUG}” can be:
# - “all” to set “-x” option of the shell
# - “true” to enable the “debug()” function, set by “--debug” option
set -e
if [ "${DEBUG}" = 'all' ]
then
set -x
fi
#------------------------------------------------------------------------
# Utilities for developpers:
#
# log ($@): write all parameters on standard output and call “flog()” to
# write them in a file named “${LOG_FILE}” if it's:
# - defined
# - not a symlink
# - a file or a named pipe or a socket
# - writable or its parent directory is writable to create
# a regular file.
#
# warn($@): call “log()” with all parameters, output of log() is
# redirected to standard error.
#
# die($@): call “warn()” with all parameters, exit with code stored in
# “${EXIT_CODE}” or “1” if it does not exit.
#
# debug($@): call “warn()” with all parameters if “${DEBUG}" is
# “true”, the message is prefixed by the script name stored
# in “${SELF}”
#
# flog ($@): write all parameters prefixed by current date and time
# in a file named “${LOG_FILE}" if the variable is not empty.
# The caller is responsible of the writable check of “${LOG_FILE}”.
# Take care of “-e” option to echo
type shopt > /dev/null && ECHO=echo || ECHO=/bin/echo
## Logger functions
# Check if “log()” could write to “${LOG_FILE}”
log_writable() {
# First: check that filename is defined and not a symlink
# Second: check that filename is a file, a named pipe or a socket
# Thirt: if filename is writable or if its parent directory is writable
[ -n "${1}" -a ! -L "${1}" ] \
&& [ -f "${1}" -o -p "${1}" -o -S "${1}" ] \
&& [ -w "${1}" -o -w "$(dirname ${1})" ]
}
flog() { [ -z "${LOG_FILE}" ] || ${ECHO} -e "$(date "+%Y-%m-%d %H:%M:%S"): $@" >> "${LOG_FILE}"; }
log() { ${ECHO} -e "$@"; log_writable "${LOG_FILE}" && flog "$@" || true; }
warn() { log "$@" >&2; }
debug() { [ "${DEBUG}" = all -o "${DEBUG}" = true ] && warn "${SELF}: $@" || true; }
die() { warn "$@"; exit ${EXIT_CODE:-1}; }
## Common option functions
# Display list of changes
changes(){
${ECHO} -e "${SELF}\n"
perl -lne "s<\\$\\{([^\\}]+)\\}><\$ENV{\$1}>gxms;
print substr(\$_, 2) if (/^# Changes/ .. /^\$/) =~ /^\\d+\$/" < "${0}"
}
# Set SELF_VERSION variable
self_version() {
[ -z "${SELF_VERSION}" ] || return
export SELF_VERSION=$(changes 2>&1 \
| perl -lane 'if (m/^\s+\d+(?:\.\d+)*/) {print $F[0]; exit}')
}
# Display usage
usage() {
self_version
perl -lne "s<\\$\\{([^\\}]+)\\}><\$ENV{\$1}>gxms;
print substr(\$_, 2) if (/^# Usage/ .. /^\$/) =~ /^\\d+\$/" < "${0}"
}
# Display licence
licence() {
self_version
perl -lne "s<\\$\\{([^\\}]+)\\}><\$ENV{\$1}>gxms;
print substr(\$_, 2) if (/^# ${SELF} \(${SELF_VERSION}\)/ .. /^\$/) =~ /^\\d+\$/" < "${0}"
}
# Display sources making the software AGPL-3 ready
sources() {
cat < "${0}"
}
#------------------------------------------------------------------------
# Global variables:
#
# Use “export” to make them available to subprocesses
#
# Empty log file by default
LOG_FILE=
# Used by common options functions, do not unexport or they fail
export SELF=$(basename $(readlink -e "${0}"))
export SELF_VERSION= # Set by function, here for reference
# Program specific variables, export to use it in “usage()”
export MESSAGE="Hello World!"
#------------------------------------------------------------------------
# Options
TEMP=$(getopt -o m:dhvcls --long message:,debug,help,version,copyright,licence,changes,sources -- "$@")
test $? = 0 || exit 1
eval set -- "${TEMP}"
while true
do
case "${1}" in
# Default options for utilities
-h|--help)
usage
exit 0
;;
-v|--version)
licence | head -n 2
exit 0
;;
-c|--copyright)
licence | tail -n +2
exit 0
;;
-l|--licence)
licence
exit 0
;;
--changes)
changes
exit 0
;;
-s|--sources)
sources
exit 0
;;
-d|--debug)
DEBUG=true
shift
;;
# Program options
-m|--message)
[ -n "${2}" ] || die "Message must not be empty"
export MESSAGE="${2}"
shift 2
;;
# End of options
--)
shift
break
;;
*)
die "Error: unknown argument '${1}'"
;;
esac
done
#------------------------------------------------------------------------
# Start program
debug "This is a debug message on standard error"
${ECHO} "${MESSAGE}"