From 612534022b81a70ef4248e84a5e36ef34da990f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucio=20Andr=C3=A9s=20Illanes=20Albornoz?= Date: Wed, 30 Dec 2020 19:04:08 +0000 Subject: subr/rtl*.subr, subr.rtl/: moved. subr/build_init.subr:buildp_init_env(): updated. subr/pkgtool_init.subr:pkgtoolp_init_env(): updated. --- subr.rtl/rtl.subr | 14 +++ subr.rtl/rtl_complex.subr | 278 ++++++++++++++++++++++++++++++++++++++++++++++ subr.rtl/rtl_fetch.subr | 110 ++++++++++++++++++ subr.rtl/rtl_fileop.subr | 143 ++++++++++++++++++++++++ subr.rtl/rtl_install.subr | 53 +++++++++ subr.rtl/rtl_list.subr | 120 ++++++++++++++++++++ subr.rtl/rtl_log.subr | 78 +++++++++++++ subr.rtl/rtl_state.subr | 39 +++++++ subr.rtl/rtl_string.subr | 122 ++++++++++++++++++++ 9 files changed, 957 insertions(+) create mode 100644 subr.rtl/rtl.subr create mode 100644 subr.rtl/rtl_complex.subr create mode 100644 subr.rtl/rtl_fetch.subr create mode 100644 subr.rtl/rtl_fileop.subr create mode 100644 subr.rtl/rtl_install.subr create mode 100644 subr.rtl/rtl_list.subr create mode 100644 subr.rtl/rtl_log.subr create mode 100644 subr.rtl/rtl_state.subr create mode 100644 subr.rtl/rtl_string.subr (limited to 'subr.rtl') diff --git a/subr.rtl/rtl.subr b/subr.rtl/rtl.subr new file mode 100644 index 00000000..b123555f --- /dev/null +++ b/subr.rtl/rtl.subr @@ -0,0 +1,14 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +rtl_basename() { local _fname="${1##*/}"; printf "%s" "${_fname}"; }; +rtl_date() { command date "+${1:-${DEFAULT_TIMESTAMP_FMT:-"%Y/%m/%d %H:%M:%S"}}"; }; +rtl_set_IFS_nl() { IFS=" +"; }; +rtl_set_var_unsafe() { [ -n "${2}" ] && eval ${1}=\"${2}\" || return 0; }; +rtl_test_cmd() { command -v "${1}" >/dev/null; }; +rtl_uniq() { if [ "${#}" -gt 0 ]; then printf "%s" "${*}" | sed 's/ /\n/g' | awk '!x[$0]++' | paste -s -d" "; fi; }; +rtl_unset_vars() { while [ ${#} -gt 0 ]; do unset "${1}"; shift; done; }; + +# vim:filetype=sh diff --git a/subr.rtl/rtl_complex.subr b/subr.rtl/rtl_complex.subr new file mode 100644 index 00000000..4894e0f6 --- /dev/null +++ b/subr.rtl/rtl_complex.subr @@ -0,0 +1,278 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +rtl_check_digest() { + local _fname="${1}" _digest_check="${2}" _digest=""; RTL_CHECK_DIGEST_DIGEST=""; + if ! [ -e "${_fname}" ]; then + return 1; + else set -- $(sha256sum "${_fname}"); + RTL_CHECK_DIGEST_DIGEST="${1}"; + if [ "${RTL_CHECK_DIGEST_DIGEST}" = "${_digest_check}" ]; then + return 0; + else + return 1; + fi; + fi; +}; + +rtl_check_digest_file() { + local _fname="${1}" _digest_check="${2}" _digest_fname="${3}" _digest="" RTL_CHECK_DIGEST_DIGEST=""; + if ! [ -e "${_digest_fname}" ]; then + return 1; + else _digest="$(cat "${_digest_fname}")"; + if [ "${_digest}" != "${_digest_check}" ]\ + || ! rtl_check_digest "${_fname}" "${_digest_check}"; then + return 1; + fi; + fi; +}; + +rtl_check_path_vars() { + local _vnames="${1}" _rc=0 _vname="" _vname_val=""; _status=""; + for _vname in ${_vnames}; do + _vname_val="$(rtl_get_var_unsafe "${_vname}")"; + if [ -z "${_vname_val}" ]; then + _rc=1; _status="Error: variable \`${_vname}' is empty or unset."; break; + elif [ "${_vname_val#* *}" != "${_vname_val}" ]; then + _rc=2; _status="Error: variable \`${_vname}' contains one or more whitespace characters."; break; + fi; + done; + return "${_rc}"; +}; + +rtl_check_prereqs() { + local _cmd="" _cmds_missing="" _rc=0; _status=""; + for _cmd in "${@}"; do + if ! which "${_cmd}" >/dev/null 2>&1; then + _cmds_missing="${_cmds_missing:+${_cmds_missing} }${_cmd}"; + fi; + done; + if [ -n "${_cmds_missing}" ]; then + _rc=1; _status="Error: missing prerequisite package(s): ${_cmds_missing}"; + fi; + return "${_rc}"; +}; + +rtl_clean_env() { + local _env_vars_except="${1}" _env_var="" _env_vars=""; + _env_vars="$(export | sed -ne '/^export/{s/^export //;s/=.*$//p}')"; + for _env_var in ${_env_vars}; do + if [ "${_env_var#DEFAULT_}" != "${_env_var}" ]\ + || [ "${_env_var#PKG_}" != "${_env_var}" ]; then + _env_vars_except="$(rtl_lconcat "${_env_vars_except}" "${_env_var}")"; + fi; + done; + rtl_unset_vars $(rtl_lfilter "${_env_vars}" "${_env_vars_except}"); +}; + +rtl_dirname() { + local _dname="${1%/*}"; + while rtl_matchr "${_dname}" "*/"; do + _dname="${_dname%/}"; + done; printf "%s" "${_dname:-/}"; +}; + +rtl_exists_any() { + local _subdir="${1}"; shift; + while [ "${#}" -gt 0 ]; do + if [ -e "${_subdir}/${1}" ]; then + return 0; + else + shift; + fi; + done; return 1; +}; + +rtl_export_vars() { + local _unsetfl=0; [ "x${1}" = "x-u" ] && { _unsetfl=1; shift; }; + while [ "${#}" -ge 2 ]; do + if [ -n "${2}" ]; then + if [ "${_unsetfl:-0}" -eq 0 ]; then + rtl_set_var_unsafe "${1}" "${2}"; export "${1}"; + else + unset "${1}"; + fi; + fi; + shift 2; + done; +}; + +rtl_filter_vars() { + local _fn="${1}" _fnfl=0 _qchar="" _var_spec="" _vars="" _vname="" IFS; + rtl_set_IFS_nl; + for _var_spec in $(set); do + case "${_qchar}" in + "\"") if [ "${_var_spec%\"}" != "${_var_spec}" ]; then + _qchar=""; + fi; + if [ "${_fnfl:-0}" -eq 1 ]; then + _vars="$(rtl_lconcat "${_vars}" "${_var_spec}" "\n")"; + fi; + continue; ;; + "\'") if [ "${_var_spec%\'}" != "${_var_spec}" ]; then + _qchar=""; + fi; + if [ "${_fnfl:-0}" -eq 1 ]; then + _vars="$(rtl_lconcat "${_vars}" "${_var_spec}" "\n")"; + fi; + continue; ;; + *) case "${_var_spec}" in + [^=]*=\"*\") _qchar=""; _vname="${_var_spec%%=\"*}"; ;; + [^=]*=\"*) _qchar="\""; _vname="${_var_spec%%=\"*}"; ;; + [^=]*=\'*\') _qchar=""; _vname="${_var_spec%%=\'*}"; ;; + [^=]*=\'*) _qchar="\'"; _vname="${_var_spec%%=\'*}"; ;; + [^=]*=*) _qchar=""; _vname="${_var_spec%%=*}"; ;; + esac; ;; + esac; + if "${_fn}" "${_vname}"; then + _vars="${_vars:+${_vars} +}${_var_spec}"; _fnfl=1; + else + _fnfl=0; + fi; + done; + printf "%s" "${_vars}"; +}; + +rtl_flock_acquire() { + local _fd="${1}" _conflict_exit_code="${2:-622}" _wait="${3:-3600}" + while true; do + if flock -E "${_conflict_exit_code}" -w "${_wait}" "${_fd}"; then + break; + elif [ "${?}" -eq "${_conflict_exit_code}" ]; then + continue; + else + return "${?}"; + fi; + done; +}; + +rtl_get_cpu_count() { + local _line="" _ncpus=0 _rc=0 _sname="$(uname -s 2>/dev/null)"; _status=""; + case "${_sname}" in + Linux) if [ ! -e "/proc/cpuinfo" ]; then + _rc=1; _status="Error: /proc/cpuinfo non-existent."; + else while read -r _line; do + if rtl_match "${_line}" "processor*:"; then + : $((_ncpus+=1)); + fi; + done < /proc/cpuinfo; printf "%s" "${_ncpus}"; + fi; ;; + *) _rc=1; _status="Error: unknown platform \`${_sname}'."; ;; + esac; return "${_rc}"; +}; + +rtl_get_var_unsafe() { + local _vname=""; + if [ "x${1}" = "x-u" ]; then + shift; _vname="$(rtl_toupper "${1}")"; + else + _vname="${1}"; + fi; + eval echo \${${_vname}} 2>/dev/null; +}; + +rtl_get_vars_fast() { + local _pattern="${1}"; + set | awk -F= '/'"${_pattern}"'/{print $1}' | sort; +}; + +rtl_head() { + local _pattern="${1}" _s="${2}"; + while true; do + if [ "${_s%%${_pattern}}" = "${_s}" ]; then + break; + else + _s="${_s%%${_pattern}}"; + fi; + done; + printf "%s" "${_s}"; +}; + +rtl_is_newer() { + local _new_fname="${1}" _old_fname="${2}" _new_ts="" _old_ts=""; + if ! [ -e "${_old_fname}" ]; then + return 0; + else _new_ts="$(stat -c %Y "${_new_fname}" 2>&1)"; + _old_ts="$(stat -c %Y "${_old_fname}" 2>&1)"; + if [ "${_new_ts:-0}" -gt "${_old_ts:-0}" ]; then + return 0; + else + return 1; + fi; + fi; +}; + +rtl_kill_tree() { + local _pid="${1}" _signal="${2:-TERM}" _pid_child="" _pids=""; + if _pids="$(pgrep -P "${_pid}")"\ + && [ -n "${_pids}" ]; then + for _pid_child in ${_pids}; do + rtl_kill_tree "${_pid_child}" "${_signal}"; + done; + fi; + if [ "${_pid:-0}" -ne "${$}" ]\ + && kill "-${_signal}" "${_pid}" 2>/dev/null; then + RTL_KILL_TREE_PIDS="$(rtl_lconcat "${RTL_KILL_TREE_PIDS}" "${_pid}")"; + fi; +}; + +rtl_percentage() { + local _in="${1}" _max="${2}" _perc; + _perc="$((100 * ${_in} + ${_max} / 2))"; + _perc="$((${_perc} ? ${_perc} / ${_max} : ${_perc}))"; + printf "%d\n" "${_perc}"; +}; + +rtl_prompt() { + local _fmt="${1}" _choice=""; shift; + printf "${_fmt}? (y|N) " "${@}"; + read -r _choice; + case "${_choice}" in + [yY]) _choice=1; ;; + *) _choice=0; ;; + esac; + return "${_choice}"; +}; + +rtl_rc() { + local _nflag="${1}" _cmd="${2}"; shift 2; + case "${_nflag}" in + 1) if [ "${#}" -gt 0 ]; then + rtl_log_msg notice "Command line: %s %s" "${_cmd}" "${*}"; + else + rtl_log_msg notice "Command line: %s" "${_cmd}"; + fi; ;; + *) "${_cmd}" "${@}"; + esac; +}; + +rtl_run_cmd_unsplit() { + local _cmd="${1}" _cmdline="" _rc="" IFS; shift; + while [ ${#} -gt 0 ]; do + [ -n "${1}" ] &&\ + _cmdline="${_cmdline:+${_cmdline}:}${1}"; + shift; + done; + IFS=:; ${_cmd} ${_cmdline}; _rc=$?; + return ${_rc}; +}; + +rtl_set_vars() { + local _vars_set_vname="${1}" _vname_dst="${2}" _vname_src_tmpls="${3}" \ + _vars_set_old="" _vars_set_tmp="" _vname_src=""; + for _vname_src in $(rtl_toupper "${_vname_src_tmpls}"); do + _vname_src="${_vname_src}_${_vname_dst}"; + _vval_src="$(rtl_get_var_unsafe "${_vname_src}")"; + if [ -n "${_vval_src}" ]; then + rtl_set_var_unsafe "PKG_${_vname_dst}" "${_vval_src}"; + _vars_set_tmp="$(rtl_lconcat "${_vars_set_tmp}" "PKG_${_vname_dst}")"; + fi; + done; + _vars_set_old="$(rtl_get_var_unsafe "${_vars_set_vname}")"; + rtl_set_var_unsafe "${_vars_set_vname}" \ + "$(rtl_lconcat "${_vars_set_old}" "${_vars_set_tmp}")"; +}; + +# vim:filetype=sh diff --git a/subr.rtl/rtl_fetch.subr b/subr.rtl/rtl_fetch.subr new file mode 100644 index 00000000..d0ad54b0 --- /dev/null +++ b/subr.rtl/rtl_fetch.subr @@ -0,0 +1,110 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +rtlp_fetch_url_git() { + local _tgtdir="${1}" _subdir="${2}" _url="${3}" _branch="${4}" \ + _oldpwd=""; + (set -o errexit -o noglob -o nounset; + rtl_flock_acquire 4 || exit "${?}"; + trap "rm -f \"${BUILD_DLCACHEDIR}/${_subdir%%[/]}.fetching\"" EXIT; + if [ -e "${BUILD_DLCACHEDIR}/${_subdir}" ]; then + (rtl_fileop cd "${BUILD_DLCACHEDIR}/${_subdir}" &&\ + git pull ${DEFAULT_GIT_ARGS} origin "${_branch:-main}"); + (rtl_fileop cd "${BUILD_DLCACHEDIR}/${_subdir}" &&\ + git submodule update); + else + git clone ${DEFAULT_GIT_ARGS} "${_url}" "${BUILD_DLCACHEDIR}/${_subdir}"; + if [ -n "${_branch}" ]; then + (rtl_fileop cd "${BUILD_DLCACHEDIR}/${_subdir}" &&\ + git checkout "${_branch}"); + fi; + (rtl_fileop cd "${BUILD_DLCACHEDIR}/${_subdir}" &&\ + git submodule update --init); + fi; + _oldpwd="${PWD}"; rtl_fileop cd "${PKG_BASE_DIR}"; + rtl_fileop rm "${_tgtdir}/${_subdir}"; + rtl_fileop cp "${BUILD_DLCACHEDIR}/${_subdir}" "${_tgtdir}"; + rtl_fileop cd "${_oldpwd}";) 4<>"${BUILD_DLCACHEDIR}/${_subdir%%[/]}.fetching"; + if [ "${?}" -eq 0 ]; then + cd "$(pwd)"; + else + return 1; + fi; +}; + +rtl_fetch_urls_git() { + local _tgtdir="" _url_spec="" _subdir="" _url="" _git_branch=""; + _tgtdir="${1}"; shift; + if [ "${ARG_FETCH_FORCE}" = "offline" ]; then + return 0; + fi; + for _url_spec in "${@}"; do + _subdir="${_url_spec%=*}"; + _url="${_url_spec#*=}"; + _url="${_url%@*}"; + if [ "${_url_spec#*@}" != "${_url_spec}" ]; then + _git_branch=${_url_spec#*@}; + fi; + rtlp_fetch_url_git "${_tgtdir}" "${_subdir}" \ + "${_url}" "${_git_branch}"; + done; +}; + +# N.B. URLs ($1) may contain `?' or '&' characters. +rtl_fetch_url_wget() { + local _urls="${1}" _sha256sum_src="${2}" _target_fname="${3}" _rc=0 _target_fname_full=""\ + _url="" _urls_count=0; + if [ "${ARG_FETCH_FORCE}" = "offline" ]; then + return 0; + else _urls_count="$(rtl_llength "${_urls}")"; + for _url in ${_urls}; do + if [ -z "${_target_fname}" ]; then + _target_fname="$(rtl_basename "${_url}")"; + fi; + _target_fname_full="${BUILD_DLCACHEDIR}/${_target_fname}"; + (set +o errexit -o noglob -o nounset; + rtl_flock_acquire 4 || exit 1; + trap "_rc=\"\${?}\"; rm -f \"${_target_fname_full}.fetching\"; exit \"\${_rc}\";" EXIT; + if [ -z "${_sha256sum_src}" ]\ + || ! rtl_check_digest_file "${_target_fname_full}" "${_sha256sum_src}" "${_target_fname_full}.fetched"; then + wget ${DEFAULT_WGET_ARGS} -O "${_target_fname_full}" "${_url}"; _rc="${?}"; + if [ "${_rc}" -ne 0 ]; then + exit $((${_rc}+2)); + elif [ -n "${_sha256sum_src}" ]\ + && ! rtl_check_digest "${_target_fname_full}" "${_sha256sum_src}"; then + exit 2; + else + printf "%s" "${RTL_CHECK_DIGEST_DIGEST}" > "${_target_fname_full}.fetched"; exit 0; + fi; + else + exit 0; + fi;) 4<>"${_target_fname_full}.fetching"; _rc="${?}"; : $((_urls_count-=1)); + case "${_rc}" in + 0) break; ;; + 1) if [ "${_urls_count}" -ge 1 ]; then + rtl_log_msg warning "Warning: failed to acquire fetching lock for URL \`%s', retrying with alternative URL..." "${_url}"; + else + rtl_log_msg fatalexit "Error: failed to acquire fetching lock for URL \`%s'." "${_url}"; + fi; ;; + 2) if [ "${_urls_count}" -ge 1 ]; then + rtl_log_msg warning "Warning: hash mismatch for URL \`%s', retrying with alternative URL... (from build variables: %s.)"\ + "${_url}" "${_sha256sum_src}"; + else + rtl_log_msg fatalexit "Error: hash mismatch for URL \`%s' (from build variables: %s.)"\ + "${_url}" "${_sha256sum_src}"; + fi; ;; + *) if [ "${_urls_count}" -ge 1 ]; then + rtl_log_msg warning "Warning: failed to fetch URL \`%s', retrying with alternative URL... (wget(1) exit status: %s)"\ + "${_url}" "$((${_rc}-2))"; + else + rtl_log_msg fatalexit "Error: failed to fetch URL \`%s' (wget(1) exit status: %s)"\ + "${_url}" "$((${_rc}-2))"; + fi; ;; + esac; + done; + return "${_rc}"; + fi; +}; + +# vim:filetype=sh diff --git a/subr.rtl/rtl_fileop.subr b/subr.rtl/rtl_fileop.subr new file mode 100644 index 00000000..dd82311e --- /dev/null +++ b/subr.rtl/rtl_fileop.subr @@ -0,0 +1,143 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +# +# Private globals and subroutines +# +RTLP_FILEOP_LOG=0; +rtl_fileop_set_log() { RTLP_FILEOP_LOG="${1}"; }; + +rtlp_fileop_check() { + local _prefix="${1}" _pname="" _rname=""; shift; + while [ "${#}" -gt 0 ]; do + return 0; + shift; done; +}; + +rtlp_fileop_log() { + local _msg="${1}"; + if [ "${RTLP_FILEOP_LOG:-0}" -eq 1 ]; then + rtl_log_msg debug "${_msg}"; + fi; +}; + + +rtl_fileop() { + local _op="${1}" _dst="" _mode="" _install_args="" _owner="" _rc=0 _src=""; shift; + case "${_op}" in + cd) if [ \( -z "${1}" \) -o ! \( -L "${1}" -o -e "${1}" \) ]; then + rtl_log_msg fatalexit "Invalid or non-existent directory \`%s'." "${1}"; + elif rtlp_fileop_check "${PREFIX:-}" "${1}"; then + rtlp_fileop_log "Changing working directory to \`${1}'."; + cd -- "${1}"; _rc="${?}"; + fi; ;; + chmod) if [ "${#}" -lt 2 ]; then + rtl_log_msg fatalexit "Missing parameters (in: chmod %s.)" "${*}"; + elif _mode="${1}" && shift\ + && rtlp_fileop_check "${PREFIX:-}" "${*}"; then + rtlp_fileop_log "Changing file mode bits of \`${*}' to \`${_mode}'."; + chmod -- "${_mode}" "${@}"; _rc="${?}"; + fi; ;; + chown) if [ "${#}" -lt 2 ]; then + rtl_log_msg fatalexit "Missing parameters (in: chown %s.)" "${*}"; + elif _owner="${1}" && shift\ + && rtlp_fileop_check "${PREFIX:-}" "${*}"; then + rtlp_fileop_log "Changing file owner of \`${*}' to \`${_owner}'."; + chown -- "${_owner}" "${@}"; _rc="${?}"; + fi; ;; + cp_follow) + if [ "${#}" -lt 2 ]; then + rtl_log_msg fatalexit "Missing parameters (in: cp_follow %s}.)" "${*}"; + elif rtlp_fileop_check "${PREFIX:-}" "${*}"; then + _src="${*}"; _src="${_src% *}"; + _dst="${*}"; _dst="${_dst##* }"; + rtlp_fileop_log "Copying \`${_src}' into \`${_dst}' w/ -pLR."; + cp -pLR -- "${@}"; _rc="${?}"; + fi; ;; + cp) if [ "${#}" -lt 2 ]; then + rtl_log_msg fatalexit "Missing parameters (in: cp %s.)" "${*}"; + elif rtlp_fileop_check "${PREFIX:-}" "${*}"; then + _src="${*}"; _src="${_src% *}"; + _dst="${*}"; _dst="${_dst##* }"; + rtlp_fileop_log "Copying \`${_src}' into \`${_dst}' w/ -pPR."; + cp -pPR -- "${@}"; _rc="${?}"; + fi; ;; + install) + if [ "${#}" -lt 2 ]; then + rtl_log_msg fatalexit "Missing parameters (in: install %s.)" "${*}"; + else _dst="$(while [ ""${#}"" -gt 2 ]; do shift; done; printf "%s" "${2}")"; + _install_args="$(while [ ""${#}"" -gt 2 ]; do printf "%s" "${1}"; shift; done)"; + _src="$(while [ ""${#}"" -gt 2 ]; do shift; done; printf "%s" "${1}")"; + if rtlp_fileop_check "${PREFIX:-}" "${_dst}" "${_src}"; then + rtlp_fileop_log "Installing \`${_src}' into \`${_dst}' w/ ${_install_args}."; + install "${@}"; _rc="${?}"; + fi; + fi; ;; + ln_symbolic) + if [ \( -z "${1}" \) -o \( -z "${2}" \) ]; then + rtl_log_msg fatalexit "Missing parameters (in: ln_symbolic %s.)" "${*}"; + elif rtlp_fileop_check "${PREFIX:-}" "${2}"; then + if rtl_fileop test "${2}"; then + rtl_fileop rm "${2}"; + fi; + if [ "${?}" -eq 0 ]; then + rtlp_fileop_log "Linking \`${1}' to \`${2}' w/ -fs"; + ln -fs -- "${1}" "${2}"; _rc="${?}"; + fi; + fi; ;; + mv) if [ \( -z "${1}" \) -o \( -z "${2}" \) ]; then + rtl_log_msg fatalexit "Missing parameters (in: mv %s.)" "${*}"; + elif rtlp_fileop_check "${PREFIX:-}" "${1}" "${2}"; then + rtlp_fileop_log "Moving \`${1}' to \`${2}' w/ -fs"; + mv -f -- "${1}" "${2}"; _rc="${?}"; + fi; ;; + mkdir|mkfifo|rm|source|source_opt|test|touch) + while [ \( "${?}" -eq 0 \) -a \( ""${#}"" -gt 0 \) ]; do + if [ -z "${1}" ]; then + rtl_log_msg fatalexit "Missing parameters (in: %s %s.)" "${_op}" "${*}"; + elif [ "${_op}" = mkdir ]\ + && [ ! -d "${1}" ]\ + && rtlp_fileop_check "${PREFIX:-}" "${1}"; then + if rtl_fileop test "${1}"; then + rtl_fileop rm "${1}"; + fi; + rtlp_fileop_log "Making directory \`${1}'."; + mkdir -p -- "${1}"; _rc="${?}"; + elif [ "${_op}" = mkfifo ]\ + && rtlp_fileop_check "${PREFIX:-}" "${1}"; then + if rtl_fileop test "${1}"; then + rtl_fileop rm "${1}"; + fi; + rtlp_fileop_log "Creating FIFO \`${1}'."; + rtlp_fileop_check "${PREFIX:-}" "${1}"; + mkfifo -- "${1}"; _rc="${?}"; + elif [ "${_op}" = rm ]\ + && rtl_fileop test "${1}"\ + && rtlp_fileop_check "${PREFIX:-}" "${1}"; then + rtlp_fileop_log "Removing directory or file \`${1}'."; + rm -rf -- "${1}"; _rc="${?}"; + elif [ "${_op}" = source ]\ + && rtlp_fileop_check "${PREFIX:-}" "${1}"; then + rtlp_fileop_log "Sourcing file \`${1}'."; + . "${1}"; _rc="${?}"; + elif [ "${_op}" = source_opt ]\ + && rtl_fileop test "${1}"\ + && rtlp_fileop_check "${PREFIX:-}" "${1}"; then + rtlp_fileop_log "Sourcing file \`${1}'."; + . "${1}"; _rc="${?}"; + elif [ "${_op}" = test ]\ + && rtlp_fileop_check "${PREFIX:-}" "${1}"\ + && ! [ \( -L "${1}" \) -o \( -e "${1}" \) ]; then + return 1; + elif [ "${_op}" = touch ]\ + && rtlp_fileop_check "${PREFIX:-}" "${1}"; then + rtlp_fileop_log "Touching file \`${1}'."; + touch -- "${1}"; _rc="${?}"; + fi; shift; + done; ;; + *) rtl_log_msg fatalexit "Error: rtl_fileop() called w/ invalid parameter(s): %s" "${*}"; ;; + esac; return "${_rc}"; +}; + +# vim:filetype=sh diff --git a/subr.rtl/rtl_install.subr b/subr.rtl/rtl_install.subr new file mode 100644 index 00000000..be940cd9 --- /dev/null +++ b/subr.rtl/rtl_install.subr @@ -0,0 +1,53 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +rtl_install() { + local _verbose="" _prefix="" _ln_target="" _ln_fname="" \ + _mkdir_fname="" _file_fname_src="" _file_fname_dst=""; + if [ "${1}" = "-v" ]; then + _verbose=1; shift; + fi; _prefix="${1}"; shift; + while [ ${#} -gt 0 ]; do + case "${1}" in + @*=*) + _ln_target="${1%=*}"; + _ln_target="${_ln_target#@}"; + _ln_fname="${1#*=}"; + if [ "${_ln_fname#/}" = "${_ln_fname}" ]; then + _ln_fname="${_prefix:+${_prefix}/}${_ln_fname}"; + fi; + if [ -e "${_ln_fname}" ]; then + rtl_fileop rm "${_ln_fname}"; + fi; + if ! rtl_fileop ln_symbolic "${_ln_target}" "${_ln_fname}"; then + return 1; + fi; + ;; + /=*) + _mkdir_fname="${1#/=}"; + if [ "${_mkdir_fname#/}" = "${_mkdir_fname}" ]; then + _mkdir_fname="${_prefix:+${_prefix}/}${_mkdir_fname}"; + fi; + if ! rtl_fileop mkdir "${_mkdir_fname}"; then + return 1; + fi; + ;; + *) + _file_fname_src="${1%=*}"; + _file_fname_dst="${1#*=}"; + if [ "${_file_fname_src#/}" = "${_file_fname_src}" ]; then + _file_fname_src="${_prefix:+${_prefix}/}${_file_fname_src}"; + fi; + if [ "${_file_fname_dst#/}" = "${_file_fname_dst}" ]; then + _file_fname_dst="${_prefix:+${_prefix}/}${_file_fname_dst}"; + fi; + if ! rtl_fileop cp "${_file_fname_src}" "${_file_fname_dst}"; then + return 1; + fi; + ;; + esac; shift; + done; +}; + +# vim:filetype=sh diff --git a/subr.rtl/rtl_list.subr b/subr.rtl/rtl_list.subr new file mode 100644 index 00000000..369d3b46 --- /dev/null +++ b/subr.rtl/rtl_list.subr @@ -0,0 +1,120 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +rtl_lassign() { + local _vnames="${1}" _sep="${2}" _vname="" _vval=""\ + IFS RTL_LFIRST_HEAD="" RTL_LFIRST_TAIL=""; + IFS="${_sep}"; shift 2; + for _vval in ${@}; do + if ! rtl_lfirst "${_vnames}" " "; then + return 1; + else + _vname="${RTL_LFIRST_HEAD}"; _vnames="${RTL_LFIRST_TAIL}"; + rtl_set_var_unsafe "${_vname}" "${_vval}"; + fi; + done; +}; + +rtl_lconcat() { + local _list="${1}" _litem_new="${2}" _sep="${3:- }" IFS="${3:-${IFS:- }}"; + if [ -n "${_list}" ]; then + printf "%s%s%s" "${_list}" "${_sep}" "${_litem_new}"; + else + printf "%s" "${_litem_new}"; + fi; +}; + +rtl_lfilter() { + local _list="${1}" _filter="${2}" _sep="${3:- }" IFS="${3:-${IFS:- }}"\ + _filterfl="" _litem="" _litem_filter="" _lnew=""; + if [ -z "${_filter}" ]; then + printf "%s" "${_list}"; return 0; + else for _litem in ${_list}; do + _filterfl=0; + for _litem_filter in ${_filter}; do + if [ "${_litem_filter}" = "${_litem}" ]; then + _filterfl=1; break; + fi; + done; + if [ "${_filterfl:-0}" -eq 0 ]; then + _lnew="${_lnew:+${_lnew}${_sep}}${_litem}"; + fi; + done; fi; + printf "%s" "${_lnew}"; +}; + +rtl_lfirst() { + local _list="${1}" _sep="${2}" IFS; IFS="${_sep}"; + set -- ${_list}; RTL_LFIRST_HEAD="${1}"; + if [ "${#}" -ge 0 ]; then + shift; RTL_LFIRST_TAIL="${*}"; + else + RTL_LFIRST_TAIL=""; + fi; +}; + +rtl_llength() { + local _list="${1}" _sep="${2:- }" IFS="${2:-${IFS:- }}" _litem="" _llength=0; + for _litem in ${_list}; do + : $((_llength+=1)); + done; + printf "%s" "${_llength}"; +}; + +rtl_llift() { + local _list="${1}" _sep="${2}" _sep_new="${3}" IFS; IFS="${_sep}"; + set -- ${_list}; IFS="${_sep_new}"; + printf "%s" "${*}"; +}; + +rtl_lmatch() { + local _list="${1}" _item="${2}" _sep="${3:- }"; + [ -n "$(rtl_lsearch "${_list}" "${_item}" "${_sep}")" ]; +}; + +rtl_lmax() { + local _len=0 _len_max=0; + while [ "${#}" -gt 0 ]; do + _len="${#1}"; + if [ "${_len}" -gt "${_len_max}" ]; then + _len_max="${_len}"; + fi; shift; + done; printf "%s" "${_len_max}"; +}; + +rtl_lsearch() { + local _list="${1}" _filter="${2}" _sep="${3:- }" IFS="${3:-${IFS:- }}"\ + _litem="" _litem_filter="" _lnew=""; + if [ -z "${_filter}" ]; then + printf "%s" "${_list}"; return 0; + else for _litem in ${_list}; do + for _litem_filter in ${_filter}; do + if [ "${_litem_filter}" = "${_litem}" ]; then + _lnew="${_lnew:+${_lnew}${_sep}}${_litem}"; + break; + fi; + done; + done; fi; + printf "%s" "${_lnew}"; +}; + +rtl_lsort() { + local _list="${1}" _sep="${2:- }"; + printf "%s" "${_list}" | tr "${_sep}" "\n" | sort | paste -s -d "${_sep}"; +}; + +rtl_lunfold_depends() { + local _vname_template="${1}" _depends="" _name="" _names=""; shift; + for _name in "${@}"; do + if _depends="$(rtl_get_var_unsafe -u "$(eval printf \"%s\" \""${_vname_template}"\")")"\ + && [ -n "${_depends}" ]; then + _depends="$(rtl_lunfold_depends "${_vname_template}" ${_depends})"; + _names="$(rtl_lconcat "${_names}" "${_depends}")"; + fi; + _names="$(rtl_lconcat "${_names}" "${_name}")"; + done; + printf "%s" "${_names}"; +}; + +# vim:filetype=sh diff --git a/subr.rtl/rtl_log.subr b/subr.rtl/rtl_log.subr new file mode 100644 index 00000000..b91d1374 --- /dev/null +++ b/subr.rtl/rtl_log.subr @@ -0,0 +1,78 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +# +# Private globals and subroutines +# +RTLP_LOG_NO_ATTR=0; +RTLP_LOG_FNAME=""; +RTLP_LOG_LVL="0"; +rtl_log_set_fname() { RTLP_LOG_FNAME="${1}"; }; +rtl_log_set_lvl() { RTLP_LOG_LVL="${1}"; }; +rtl_log_set_no_attr() { RTLP_LOG_NO_ATTR="${1}"; }; + +rtlp_log_printf() { + local _attr="${1}" _fmt="${2}"; shift 2; _msg="$(printf "${_fmt}" "${@}")"; + if [ -n "${RTLP_LOG_FNAME}" ]; then + printf "%s\n" "${_msg}" >> "${RTLP_LOG_FNAME}"; + fi; + if [ "${RTLP_LOG_NO_ATTR:-0}" -eq 0 ]; then + printf "\033[0m\033[${_attr}m%s\033[0m\n" "${_msg}"; + else + printf "%s\n" "${_msg}"; + fi; +}; + +# +# Public globals +# +RTL_LOG_MSG_FATAL_COLOUR=91; # Bright red +RTL_LOG_MSG_WARNING_COLOUR=31; # Dark red +RTL_LOG_MSG_SUCCESS_COLOUR=33; # Dark yellow +RTL_LOG_MSG_SUCCESS_END_COLOUR=32; # Dark green +RTL_LOG_MSG_INFO_COLOUR=93; # Bright yellow +RTL_LOG_MSG_INFO_END_COLOUR=92; # Bright green +RTL_LOG_MSG_NOTICE_COLOUR=96; # Bright cyan +RTL_LOG_MSG_VERBOSE_COLOUR=90; # Dark grey +RTL_LOG_MSG_DEBUG_COLOUR=36; # Dark cyan + + +rtl_log_env_vars() { + local _arg_len_max=0; + rtl_log_msg info "Variables for this ${1:-build}:"; shift; + _arg_len_max="$(rtl_lmax "${@}")"; + while [ "${#}" -gt 0 ]; do + rtl_log_msg info \ + "%${_arg_len_max}.${_arg_len_max}s=%s" \ + "${1%%=*}" "$(rtl_get_var_unsafe "${1#*=}")"; + shift; + done; +}; + +rtl_log_msg() { + local _lvl="${1}" _fmt="${2}" _attr=""; shift 2; + case "${RTLP_LOG_LVL:-0}" in + 0) rtl_lmatch "notice verbose debug" "${_lvl}" && return; ;; + 1) rtl_lmatch "verbose debug" "${_lvl}" && return; ;; + 2) rtl_lmatch "debug" "${_lvl}" && return; ;; + 3) ;; + esac; + case "${_lvl}" in + fatal|fatalexit) _attr="${RTL_LOG_MSG_FATAL_COLOUR}"; ;; + warning) _attr="${RTL_LOG_MSG_WARNING_COLOUR}"; ;; + success) _attr="${RTL_LOG_MSG_SUCCESS_COLOUR}"; ;; + success_end) _attr="${RTL_LOG_MSG_SUCCESS_END_COLOUR}"; ;; + info) _attr="${RTL_LOG_MSG_INFO_COLOUR}"; ;; + info_end) _attr="${RTL_LOG_MSG_INFO_END_COLOUR}"; ;; + notice) _attr="${RTL_LOG_MSG_NOTICE_COLOUR}"; ;; + verbose) _attr="${RTL_LOG_MSG_VERBOSE_COLOUR}"; ;; + debug) _attr="${RTL_LOG_MSG_DEBUG_COLOUR}"; ;; + esac; + rtlp_log_printf "${_attr}" "==> %s ${_fmt}" "$(rtl_date)" "${@}"; + if [ "x${_lvl}" = "xfatalexit" ]; then + exit 1; + fi; +}; + +# vim:filetype=sh diff --git a/subr.rtl/rtl_state.subr b/subr.rtl/rtl_state.subr new file mode 100644 index 00000000..6d539563 --- /dev/null +++ b/subr.rtl/rtl_state.subr @@ -0,0 +1,39 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +rtl_state_clear() { + local _workdir="${1}" _pkg_name="${2}" _pkg_fname=""; + for _pkg_fname in $(find "${_workdir}" \ + -maxdepth 1 -mindepth 1 -name .${_pkg_name}.\* -type f); do + rtl_fileop rm "${_pkg_fname}"; + done; +}; + +rtl_state_set() { + local _workdir="${1}" _pkg_fname="${2}" _done_fname_pfx=""; + _done_fname_pfx="${_workdir}/.${_pkg_fname}"; + shift 2; while [ ${#} -ge 1 ]; do + if [ -z "${1}" ]; then + shift; continue; + elif [ "${1#-}" != "${1}" ]; then + rtl_fileop rm "${_done_fname_pfx}.${1#-}"; + else + rtl_fileop touch "${_done_fname_pfx}.${1}"; + fi; + shift; done; +}; + +rtl_state_test() { + local _workdir="${1}" _pkg_name="${2}" _build_step="${3}" _restart_at="${4:-}" _done_fname=""; + _done_fname="${_workdir}/.${_pkg_name}.${_build_step}"; + if [ -z "${_restart_at}" ]; then + rtl_fileop test "${_done_fname}"; + elif [ "${_restart_at}" = "ALL" ]; then + return 1; + else + ! rtl_lmatch "${_restart_at}" "${_build_step}" ","; + fi; +}; + +# vim:filetype=sh diff --git a/subr.rtl/rtl_string.subr b/subr.rtl/rtl_string.subr new file mode 100644 index 00000000..e642bebe --- /dev/null +++ b/subr.rtl/rtl_string.subr @@ -0,0 +1,122 @@ +# +# set +o errexit -o noglob -o nounset is assumed. +# + +rtl_isnumber() { + local _s="${1}" _rc=0; + while [ -n "${_s}" ]; do + case "${_s}" in + [0-9]*) _s="${_s#[0-9]}"; ;; + *) _rc=1; break; ;; + esac; done; + return "${_rc}"; +}; + +rtl_match() { + local _s="${1}" _find="${2}"; + if [ "${_s#${_find}}" != "${_s}" ]; then + return 0; + else + return 1; + fi; +}; + +rtl_matchr() { + local _s="${1}" _find="${2}"; + if [ "${_s%${_find}}" != "${_s}" ]; then + return 0; + else + return 1; + fi; +}; + +rtl_subst() { + local _s="${1}" _find="${2}" _replace="${3}" _prefix="" _s_new=""; + while [ -n "${_s}" ]; do + case "${_s}" in + *${_find}*) _prefix="${_s%%${_find}*}"; _s="${_s#*${_find}}"; + _s_new="${_s_new:+${_s_new}}${_prefix}${_replace}"; ;; + *) _s_new="${_s_new:+${_s_new}}${_s}"; _s=""; ;; + esac; done; + printf "%s" "${_s_new}"; +}; + +rtl_tolower() { + local _s="${1}" _s_new=""; + while [ -n "${_s}" ]; do + case "${_s}" in + A*) _s_new="${_s_new:+${_s_new}}a"; _s="${_s#A}"; ;; + B*) _s_new="${_s_new:+${_s_new}}b"; _s="${_s#B}"; ;; + C*) _s_new="${_s_new:+${_s_new}}c"; _s="${_s#C}"; ;; + D*) _s_new="${_s_new:+${_s_new}}d"; _s="${_s#D}"; ;; + E*) _s_new="${_s_new:+${_s_new}}e"; _s="${_s#E}"; ;; + F*) _s_new="${_s_new:+${_s_new}}f"; _s="${_s#F}"; ;; + G*) _s_new="${_s_new:+${_s_new}}g"; _s="${_s#G}"; ;; + H*) _s_new="${_s_new:+${_s_new}}h"; _s="${_s#H}"; ;; + I*) _s_new="${_s_new:+${_s_new}}i"; _s="${_s#I}"; ;; + J*) _s_new="${_s_new:+${_s_new}}j"; _s="${_s#J}"; ;; + K*) _s_new="${_s_new:+${_s_new}}k"; _s="${_s#K}"; ;; + L*) _s_new="${_s_new:+${_s_new}}l"; _s="${_s#L}"; ;; + M*) _s_new="${_s_new:+${_s_new}}m"; _s="${_s#M}"; ;; + N*) _s_new="${_s_new:+${_s_new}}n"; _s="${_s#N}"; ;; + O*) _s_new="${_s_new:+${_s_new}}o"; _s="${_s#O}"; ;; + P*) _s_new="${_s_new:+${_s_new}}p"; _s="${_s#P}"; ;; + Q*) _s_new="${_s_new:+${_s_new}}q"; _s="${_s#Q}"; ;; + R*) _s_new="${_s_new:+${_s_new}}r"; _s="${_s#R}"; ;; + S*) _s_new="${_s_new:+${_s_new}}s"; _s="${_s#S}"; ;; + T*) _s_new="${_s_new:+${_s_new}}t"; _s="${_s#T}"; ;; + U*) _s_new="${_s_new:+${_s_new}}u"; _s="${_s#U}"; ;; + V*) _s_new="${_s_new:+${_s_new}}v"; _s="${_s#V}"; ;; + W*) _s_new="${_s_new:+${_s_new}}w"; _s="${_s#W}"; ;; + X*) _s_new="${_s_new:+${_s_new}}x"; _s="${_s#X}"; ;; + Y*) _s_new="${_s_new:+${_s_new}}y"; _s="${_s#Y}"; ;; + Z*) _s_new="${_s_new:+${_s_new}}z"; _s="${_s#Z}"; ;; + [^ABCDEFGHIJKLMNOPQRSTUVWXYZ]*) + _s_new="${_s_new:+${_s_new}}${_s%%[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*}"; + while [ "${_s#[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]}" != "${_s}" ]; do + _s="${_s#[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]}"; + done; ;; + esac; done; + printf "%s" "${_s_new}"; +}; + +rtl_toupper() { + local _s="${1}" _s_new=""; + while [ -n "${_s}" ]; do + case "${_s}" in + a*) _s_new="${_s_new:+${_s_new}}A"; _s="${_s#a}"; ;; + b*) _s_new="${_s_new:+${_s_new}}B"; _s="${_s#b}"; ;; + c*) _s_new="${_s_new:+${_s_new}}C"; _s="${_s#c}"; ;; + d*) _s_new="${_s_new:+${_s_new}}D"; _s="${_s#d}"; ;; + e*) _s_new="${_s_new:+${_s_new}}E"; _s="${_s#e}"; ;; + f*) _s_new="${_s_new:+${_s_new}}F"; _s="${_s#f}"; ;; + g*) _s_new="${_s_new:+${_s_new}}G"; _s="${_s#g}"; ;; + h*) _s_new="${_s_new:+${_s_new}}H"; _s="${_s#h}"; ;; + i*) _s_new="${_s_new:+${_s_new}}I"; _s="${_s#i}"; ;; + j*) _s_new="${_s_new:+${_s_new}}J"; _s="${_s#j}"; ;; + k*) _s_new="${_s_new:+${_s_new}}K"; _s="${_s#k}"; ;; + l*) _s_new="${_s_new:+${_s_new}}L"; _s="${_s#l}"; ;; + m*) _s_new="${_s_new:+${_s_new}}M"; _s="${_s#m}"; ;; + n*) _s_new="${_s_new:+${_s_new}}N"; _s="${_s#n}"; ;; + o*) _s_new="${_s_new:+${_s_new}}O"; _s="${_s#o}"; ;; + p*) _s_new="${_s_new:+${_s_new}}P"; _s="${_s#p}"; ;; + q*) _s_new="${_s_new:+${_s_new}}Q"; _s="${_s#q}"; ;; + r*) _s_new="${_s_new:+${_s_new}}R"; _s="${_s#r}"; ;; + s*) _s_new="${_s_new:+${_s_new}}S"; _s="${_s#s}"; ;; + t*) _s_new="${_s_new:+${_s_new}}T"; _s="${_s#t}"; ;; + u*) _s_new="${_s_new:+${_s_new}}U"; _s="${_s#u}"; ;; + v*) _s_new="${_s_new:+${_s_new}}V"; _s="${_s#v}"; ;; + w*) _s_new="${_s_new:+${_s_new}}W"; _s="${_s#w}"; ;; + x*) _s_new="${_s_new:+${_s_new}}X"; _s="${_s#x}"; ;; + y*) _s_new="${_s_new:+${_s_new}}Y"; _s="${_s#y}"; ;; + z*) _s_new="${_s_new:+${_s_new}}Z"; _s="${_s#z}"; ;; + [^abcdefghijklmnopqrstuvwxyz]*) + _s_new="${_s_new:+${_s_new}}${_s%%[abcdefghijklmnopqrstuvwxyz]*}"; + while [ "${_s#[^abcdefghijklmnopqrstuvwxyz]}" != "${_s}" ]; do + _s="${_s#[^abcdefghijklmnopqrstuvwxyz]}"; + done; ;; + esac; done; + printf "%s" "${_s_new}"; +}; + +# vim:filetype=sh -- cgit v1.2.3