#!/bin/bash
# app - application support library
set -e
######
# Start/Exit Functions
# app_start() - Called by ``app_run()`` to perform all necessary startup
# actions. This includes loading configuration files, initializing settings,
# and finally calling the application callback: ``${script_name}_init``.
app_start() {
info "Running '$script_name${*:+ }$*'"
info " in '$PWD'..."
cleanup_init
app_timer_start
config_init
#; override lib_load to perform late initialization
func_chain config lib_load
config_load
config_check
settings_check
settings_final
#; override lib_load to perform late init/check
func_chain app lib_load
script_cmd_exec init
! $dumpenv || set >"$script_name.env"
}
# app_exit() - Called by ``app_run()`` to perform graceful exit actions.
app_exit() {
if [ "$1" ]; then
error "$@"
[ "$exit_code" ] || exit_code=1
else
info "... done"
fi
exit $exit_code
}
######
# Application Timer
# app_timer_start() - Starts the application timer to track execution time.
# This registers a cleanup function (``app_timer_cleanup()``).
app_timer_start() {
timer_start app_timer_runtime
cleanup_add app_timer_cleanup
}
# app_timer_cleanup() - Stops the application timer and reports the elapsed
# time (if ``$verbose = true``). Called automatically when the script exits.
app_timer_cleanup() {
timer_stop app_timer_runtime
local elapsed
elapsed=$(timer_elapsed app_timer_runtime)
info "Running time: $elapsed"
}
######
# Application Commands
# app_version() - Prints the package/tool version.
app_version() {
local name version desc
if [ $script_name = $package_name ]; then
name=$package_name
version=$package_version
else
name="$package_name $script_name"
version=$script_version
fi
desc=$(local -a script=( $script_name ) && cmd_exec desc)
echo "$name v$version ($package_build_date)${desc:+ }$desc"
}
# app_license() - Handles application license commands, displaying
# a summary, warranty information, or full license.
app_license() {
app_version
lib_load 'core/license'
case "$1" in
(''|short|blurb) license_blurb ;;
(warranty) license_warranty ;;
(full) license_full ;;
(*)
warn "$1: unknown license command"
;;
esac
}
# app_help() - Prints the top-level help text for the application.
app_help() {
app_version
cmd_help
}
# app_check() - Executes the check command if it exists, otherwise issues
# a warning. The normal disptch would give an error and usage message.
app_check() {
if cmd_exists check; then
app_echo "$script check${*+ }$*: started..."
cmd_dispatch check "$@"
app_echo "$script check${*+ }$*: ...finished"
else
# Obviously, this is NOT an error, just an embarassment.
warn "TODO: 'check' is not implemented"
fi
}
# app_check_lib() - Executes the ``lib_check`` callback for each named
# library (``$@``). With no arguments, checks all libraries that have a
# ``lib_check`` callback.
app_check_lib() {
lib_load 'sys/check'
if [ "$@" ]; then
for_each lib_load "$@"
for_each lib_check "$@"
else
lib_check_all
fi
}
# app_usage() - Top-level application usage function. These commands are
# automatically available in all scripts and displayed after the top-level
# script command usage function has been called.
app_usage() {
cat <<USAGE
Tool Commands:
--version Prints tool version and exits
--license [<kind>] Prints tool license details and exits
app ... Application management commands
check [...] Runs tool self-test/demo
check-lib <lib>+ Runs library self-test/demo
shell [<file> [<arg>+]] Runs tool command shell
USAGE
}
######
# Application Command Dispatch
# app_main() - Top-level application command dispatch function.
app_main() {
debug "processing command line arguments..."
local cmd=$1
[ "$cmd" ] || error_usage "command required"
shift
case "$cmd" in
-V|--version)
app_version
;;
--license)
app_license "$@"
;;
check)
app_check "$@"
;;
check-lib)
app_check_lib "$@"
;;
shell)
lib_load 'sys/shell'
shell_run "$@"
;;
app)
lib_cmd_dispatch app_cmd_builtin "$@"
;;
*)
app_cmd_dispatch "$cmd" "$@"
;;
esac
}
# app_cmd_dispatch - Top-level command dispatch handler. It allows scripts to
# provide their own ``${script_name}_dispatch`` function to add dynamic
# top-level commands. This mechanism should not be needed by most tools, as
# normal command dispatching methods suffice for a static command language.
app_cmd_dispatch() {
if cmd_exists dispatch; then
cmd_exec dispatch "$@"
else
cmd_dispatch "$@"
fi
}
######
# Application Commands
# app_cmd_builtin_usage() -
app_cmd_builtin_usage() {
cat <<USAGE
...
Application Commands:
client ... Client commands
server ... Server commands
backup ... Backup commands
restore ... Restore commands
USAGE
}
# app_cmd_builtin_config() - Dispatches application configuration commands.
app_cmd_builtin_config() { lib_cmd_dispatch 'config' "$@"; }
# app_cmd_builtin_backup() - Dispatches application backup commands.
app_cmd_builtin_backup() {
lib_load 'sys/backup'
backup_dispatch 'backup' "$@"
}
# app_cmd_builtin_restore() - Dispatches application restore commands.
app_cmd_builtin_restore() {
lib_load 'sys/backup'
backup_dispatch 'restore' "$@"
}
# app_cmd_builtin_client() - Dispatches application client commands.
app_cmd_builtin_client() {
lib_load 'sys/client'
lib_cmd_dispatch 'client' "$@"
}
# app_cmd_builtin_server() - Dispatches application server commands.
app_cmd_builtin_server() {
lib_load 'sys/server'
lib_cmd_dispatch 'server' "$@"
}
######
# Public Interface
# app_run() - Called at the end of every tool script, after defining all
# callbacks, commands, and other data and functions. It calls ``app_start()``,
# ``app_main()``, and ``app_exit()`` in that order.
app_run() {
app_start "$@"
app_main "$@"
app_exit
}
######
# Late Library Loading Function Chains
# config_lib_load() - Chain function to initialize libraries loaded "late".
config_lib_load() {
local name=$1
! is_lib_loaded "$name" || return 0
config_lib_load_next "$name"
config_init_lib "$name"
config_load_lib "$name"
}
# app_lib_load() - Chain function to initialize libraries loaded "late".
app_lib_load() {
local name=$1
! is_lib_loaded "$name" || return 0
app_lib_load_next "$name"
config_check_lib "$name"
! $settings_dump || settings_dump_lib "$name"
settings_check_lib "$name"
settings_final_lib "$name"
}
Generated on Fri Jul 28 14:34:49 PDT 2017 by mcsh d14 v0.23.0.