armbian-next: extensions: move 'extensions.sh' into library; replace manual source with init function

- wraps globals in `extension_manager_declare_globals()` -- and make them actually global
- whoever wrote this original code is insane, add copyright
This commit is contained in:
Ricardo Pardini
2023-01-21 05:15:19 +01:00
parent 092f9ad3b2
commit eb30aac310
5 changed files with 39 additions and 22 deletions

View File

@@ -131,10 +131,9 @@ function cli_entrypoint() {
fi fi
fi fi
# Source the extensions manager library at this point, before sourcing the config. # Legacy. We used to source the extension manager here, but now it's included in the library.
# This allows early calls to enable_extension(), but initialization proper is done later. # @TODO: a quick check on the globals in extensions.sh would get rid of this.
# shellcheck source=lib/extensions.sh extension_manager_declare_globals
source "${SRC}"/lib/extensions.sh
# Loop over the ARMBIAN_CONFIG_FILES array and source each. The order is important. # Loop over the ARMBIAN_CONFIG_FILES array and source each. The order is important.
for config_file in "${ARMBIAN_CONFIG_FILES[@]}"; do for config_file in "${ARMBIAN_CONFIG_FILES[@]}"; do

View File

@@ -1,11 +1,21 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# global variables managing the state of the extension manager. treat as private.
declare -A extension_function_info # maps a function name to a string with KEY=VALUEs information about the defining extension # The whole of this is Copyright (c) 2020-2023 Ricardo Pardini <ricardo@pardini.net>
declare -i initialize_extension_manager_counter=0 # how many times has the extension manager initialized? # This file is licensed under the terms of the GNU General Public
declare -A defined_hook_point_functions # keeps a map of hook point functions that were defined and their extension info # License version 2. This program is licensed "as is" without any
declare -A hook_point_function_trace_sources # keeps a map of hook point functions that were actually called and their source # warranty of any kind, whether express or implied.
declare -A hook_point_function_trace_lines # keeps a map of hook point functions that were actually called and their source
declare fragment_manager_cleanup_file # this is a file used to cleanup the manager's produced functions, for build_all_ng function extension_manager_declare_globals() {
# global variables managing the state of the extension manager. treat as private.
declare -g -A extension_function_info # maps a function name to a string with KEY=VALUEs information about the defining extension
declare -g -i initialize_extension_manager_counter=0 # how many times has the extension manager initialized?
declare -g -A defined_hook_point_functions # keeps a map of hook point functions that were defined and their extension info
declare -g -A hook_point_function_trace_sources # keeps a map of hook point functions that were actually called and their source
declare -g -A hook_point_function_trace_lines # keeps a map of hook point functions that were actually called and their source
declare -g fragment_manager_cleanup_file # this is a file used to cleanup the manager's produced functions, for build_all_ng
declare -g -i enable_extension_recurse_counter=0
declare -g -a enable_extension_recurse_stack
}
# This is a helper function for calling hooks. # This is a helper function for calling hooks.
# It follows the pattern long used in the codebase for hook-like behaviour: # It follows the pattern long used in the codebase for hook-like behaviour:
@@ -16,7 +26,7 @@ declare fragment_manager_cleanup_file # this is a file used to clean
# 2) it will read the stdin and assume it's (Markdown) documentation for the hook point. # 2) it will read the stdin and assume it's (Markdown) documentation for the hook point.
# combined with heredoc in the call site, it allows for "inline" documentation about the hook # combined with heredoc in the call site, it allows for "inline" documentation about the hook
# notice: this is not involved in how the hook functions came to be. read below for that. # notice: this is not involved in how the hook functions came to be. read below for that.
call_extension_method() { function call_extension_method() {
# First, consume the stdin and write metadata about the call. # First, consume the stdin and write metadata about the call.
write_hook_point_metadata "$@" write_hook_point_metadata "$@"
@@ -46,7 +56,7 @@ call_extension_method() {
# it came to be. (although it is encouraged to call hook points via call_extension_method() above) # it came to be. (although it is encouraged to call hook points via call_extension_method() above)
# to avoid hard coding the list of hook-points (eg: user_config, image_tweaks_pre_customize, etc) we use # to avoid hard coding the list of hook-points (eg: user_config, image_tweaks_pre_customize, etc) we use
# a marker in the function names, namely "__" (two underscores) to determine the hook point. # a marker in the function names, namely "__" (two underscores) to determine the hook point.
initialize_extension_manager() { function initialize_extension_manager() {
# before starting, auto-add extensions specified (eg, on the command-line) via the ENABLE_EXTENSIONS or EXT env var. Do it only once. # before starting, auto-add extensions specified (eg, on the command-line) via the ENABLE_EXTENSIONS or EXT env var. Do it only once.
[[ ${initialize_extension_manager_counter} -lt 1 ]] && [[ "${ENABLE_EXTENSIONS:-"${EXT}"}" != "" ]] && { [[ ${initialize_extension_manager_counter} -lt 1 ]] && [[ "${ENABLE_EXTENSIONS:-"${EXT}"}" != "" ]] && {
local auto_extension local auto_extension
@@ -241,7 +251,7 @@ initialize_extension_manager() {
return 0 # exit with success, short-circuit above. return 0 # exit with success, short-circuit above.
} }
cleanup_extension_manager() { function cleanup_extension_manager() {
if [[ -f "${fragment_manager_cleanup_file}" ]]; then if [[ -f "${fragment_manager_cleanup_file}" ]]; then
display_alert "Cleaning up" "extension manager" "debug" display_alert "Cleaning up" "extension manager" "debug"
# shellcheck disable=SC1090 # dynamic source, thanks, shellcheck # shellcheck disable=SC1090 # dynamic source, thanks, shellcheck
@@ -270,7 +280,7 @@ function cleanup_handler_extensions() {
# process everything that happened during extension related activities # process everything that happened during extension related activities
# and write it to the log. also, move the log from the .tmp dir to its # and write it to the log. also, move the log from the .tmp dir to its
# final location. this will make run_after_build() "hot" (eg, emit warnings) # final location. this will make run_after_build() "hot" (eg, emit warnings)
run_after_build__999_finish_extension_manager() { function run_after_build__999_finish_extension_manager() {
# export these maps, so the hook can access them and produce useful stuff. # export these maps, so the hook can access them and produce useful stuff.
export defined_hook_point_functions hook_point_function_trace_sources export defined_hook_point_functions hook_point_function_trace_sources
@@ -293,7 +303,7 @@ run_after_build__999_finish_extension_manager() {
} }
# This is called by call_extension_method(). To say the truth, this should be in an extension. But then it gets too meta for anyone's head. # This is called by call_extension_method(). To say the truth, this should be in an extension. But then it gets too meta for anyone's head.
write_hook_point_metadata() { function write_hook_point_metadata() {
# Dont do anything if told not to. # Dont do anything if told not to.
[[ "${WRITE_EXTENSIONS_METADATA:-yes}" == "no" ]] && return 0 [[ "${WRITE_EXTENSIONS_METADATA:-yes}" == "no" ]] && return 0
@@ -315,9 +325,7 @@ write_hook_point_metadata() {
# will look for it in /userpatches/extensions first. # will look for it in /userpatches/extensions first.
# if not found there will look in /extensions # if not found there will look in /extensions
# if not found will exit 17 # if not found will exit 17
declare -i enable_extension_recurse_counter=0 function enable_extension() {
declare -a enable_extension_recurse_stack
enable_extension() {
local extension_name="$1" local extension_name="$1"
local extension_dir extension_file extension_file_in_dir extension_floating_file local extension_dir extension_file extension_file_in_dir extension_floating_file
local stacktrace local stacktrace

View File

@@ -1,4 +1,5 @@
# Helper function, to get clean "stack traces" that do not include the hook/extension infrastructure code. # Helper function, to get clean "stack traces" that do not include the hook/extension infrastructure code.
# @TODO this in practice is only used... ?
function get_extension_hook_stracktrace() { function get_extension_hook_stracktrace() {
[[ "${CONFIG_DEFS_ONLY}" == "yes" ]] && return 0 # don't waste time here [[ "${CONFIG_DEFS_ONLY}" == "yes" ]] && return 0 # don't waste time here
local sources_str="$1" # Give this ${BASH_SOURCE[*]} - expanded local sources_str="$1" # Give this ${BASH_SOURCE[*]} - expanded
@@ -10,8 +11,8 @@ function get_extension_hook_stracktrace() {
local source="${sources[index]}" line="${lines[((index - 1))]}" local source="${sources[index]}" line="${lines[((index - 1))]}"
# skip extension infrastructure sources, these only pollute the trace and add no insight to users # skip extension infrastructure sources, these only pollute the trace and add no insight to users
[[ ${source} == */extension_function_definition.sh ]] && continue [[ ${source} == */extension_function_definition.sh ]] && continue
[[ ${source} == *lib/extensions.sh ]] && continue [[ ${source} == *lib/functions/general/extensions.sh ]] && continue
[[ ${source} == *lib/functions/logging.sh ]] && continue [[ ${source} == *lib/functions/logging.sh ]] && continue # @TODO this doesnt match for a looong time
[[ ${source} == */compile.sh ]] && continue [[ ${source} == */compile.sh ]] && continue
[[ ${line} -lt 1 ]] && continue [[ ${line} -lt 1 ]] && continue
# relativize the source, otherwise too long to display # relativize the source, otherwise too long to display

View File

@@ -469,6 +469,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
# shellcheck source=lib/functions/general/downloads.sh # shellcheck source=lib/functions/general/downloads.sh
source "${SRC}"/lib/functions/general/downloads.sh source "${SRC}"/lib/functions/general/downloads.sh
# no errors tolerated. invoked before each sourced file to make sure.
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
set -o errtrace # trace ERR through - enabled
set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled
### lib/functions/general/extensions.sh
# shellcheck source=lib/functions/general/extensions.sh
source "${SRC}"/lib/functions/general/extensions.sh
# no errors tolerated. invoked before each sourced file to make sure. # no errors tolerated. invoked before each sourced file to make sure.
#set -o pipefail # trace ERR through pipes - will be enabled "soon" #set -o pipefail # trace ERR through pipes - will be enabled "soon"
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled #set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled

View File

@@ -18,7 +18,7 @@ def get_group_from_filename(file):
return "extension_magic" return "extension_magic"
if file == "<START_HERE>": if file == "<START_HERE>":
return "start_here" return "start_here"
if file.startswith("lib/extensions.sh"): if file.startswith("lib/functions/general/extensions.sh"):
return "extensions_infra" return "extensions_infra"
if file.startswith("extensions/"): if file.startswith("extensions/"):
return "core_extensions" return "core_extensions"