#!/bin/bash # MKit - simple install helper # See LICENSE file for copyright and license details. mkit_import ini mkit_import util plugin__lspaths() { # # List existing paths from $MKIT_PLUGINPATH # local path debug_var MKIT_PLUGINPATH tr ':' '\n' <<<"$MKIT_PLUGINPATH" \ | while read -r path; do debug_var path test -d "$path" || continue echo "$path" done } plugin__ls() { plugin__lspaths \ | while read -r path; do debug_var path find "$path" -mindepth 1 -maxdepth 1 -printf '%P\n' done } plugin__option_bool() { # # Safely load boolean option $1 # local name=$1 __plugin__option_safeload \ "$name" \ "util__isa_bool" \ "not a boolean (true|false)" } plugin__option_enum() { # # Safely load enum option $1, allowing values $2.. # __plugin__check_call || return 5 local name=$1; shift local allowed_values=("$@") local value local desc_allowed value=$(plugin__option_single "$name") debug_var name value test -n "$value" || return 1 util__isa_enum "$value" "${allowed_values[@]}" || { desc_allowed=$(util__join "|" "${allowed_values[@]}") warn "not one of supported values ($desc_allowed): $name = $value" return 3 } echo "$value" } plugin__option_multi() { # # Print multi-line plugin option $1 # __plugin__check_call || return 5 local name=$1 ini values "options:$_MKIT__PLUGIN__NAME:$name" \ | util__gate_printable } plugin__option_single() { # # Print single-line plugin option $1 # __plugin__check_call || return 5 local name=$1 ini 1value "options:$_MKIT__PLUGIN__NAME:$name" \ | grep . } plugin__option_int() { # # Safely load boolean option $1 # local name=$1 __plugin__option_safeload \ "$name" \ "util__isa_int" \ "not an integer" } plugin__option_name() { # # Safely load boolean option $1 # local name=$1 __plugin__option_safeload \ "$name" \ "util__isa_name" \ "not a valid name (alphanumeric, starting with letter)" } plugin__option_posint() { # # Safely load boolean option $1 # local name=$1 __plugin__option_safeload \ "$name" \ "util__isa_posint" \ "not a positive integer" } plugin__path() { # # Print path to plugin file $1 # local name=$1 local binpath plugin__lspaths \ | while read -r path; do binpath="$path/$name" debug_var binpath test -x "$binpath" || continue echo "$binpath" done } plugin__handle() { # # Run method $2 of plugin $1 # local _MKIT__PLUGIN__NAME=$1 local method=$2 local require=true local path local fn test "${method:0:1}" == "." && { require=false method=${method:1} } fn=${_MKIT__PLUGIN__NAME}__${method} path=$(plugin__path "$_MKIT__PLUGIN__NAME") test -n "$path" || die "plugin not found: $_MKIT__PLUGIN__NAME" bash -n "$path" || die "syntax errors in plugin file: $path" #shellcheck disable=SC1090 . "$path" || die "error importing plugin: $_MKIT__PLUGIN__NAME at $path" type -t "$fn" | grep -qw function || { $require && die "missing handler: $fn() in plugin $_MKIT__PLUGIN__NAME at $path" debug "SILENTLY SKIPPING UNDEFINED HANDLER: $fn() in $_MKIT__PLUGIN__NAME at $path" return 0 } debug "RUNNING HANDLER" debug_var fn "$fn" } plugin__isvalid() { # # True if plugin $1 is valid # local plugin=$1 plugin__ls | grep -qwxe "$plugin" } __plugin__check_call() { # # Check that this call is valid # local func=${FUNCNAME[1]} local caller=${FUNCNAME[2]} test -n "$_MKIT__PLUGIN__NAME" && return 0 warn "illegal call: $func() from $caller() _MKIT__PLUGIN__NAME=$_MKIT__PLUGIN__NAME" \ " hint: are we inside plugin?" return 3 } __plugin__option_safeload() { # # Safely load option $1 with validator $2 and error message $3 # __plugin__check_call || return 5 local name=$1 local validator=$2 local msg=$3 local value value=$(plugin__option_single "$name") debug_var name value test -n "$value" || return 1 "$validator" "$value" || { warn "$msg: $name=$value" return 3 } echo "$value" }